Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Wednesday, April 27, 2022

30 shades of PC/SC

In 2010 I started to write about the different programming languages you can use to talk to a smart card and a smart card reader.

12 years later I have 30 languages in the list.

They are, in alphabetical order:

  1. Ada
  2. C
  3. C#
  4. C for UEFI
  5. Common Lisp
  6. Elixir
  7. Erlang
  8. Flutter/Dart
  9. Free Pascal (Lazarus)
  10. go
  11. Java
  12. JavaScript (Node.js)
  13. Java using intarsys smartcard-io
  14. Kotlin
  15. lua
  16. Objective-C (synchronous)
  17. Objective-C (using Crypto Token Kit)
  18. OCaml
  19. Perl
  20. PHP5
  21. PHP (dead upstream as 11 January 2015)
  22. Prolog
  23. Python
  24. Python (using python-pcsclite)
  25. Ruby
  26. Rust
  27. Scala
  28. scriptor
  29. Smart Card Connector on Chromebook
  30. Swift (using Crypto Token Kit)

Top Computer Languages

Different lists exist for the top computer languages popularity. I will use the TIOBE Index for April 2022.

The "support" column indicates if the language has a smart card API available.

#
Language support
1 Python Yes
2 C Yes
3 Java Yes
4 C++ Yes
5 C# Yes
6 Visual Basic ?
7 JavaScript Yes
8 Assembly ?
9 SQL ?
10 PHP Yes
11 R ?
12 Pascal Yes
13 Go Yes
14 Swift Yes
15 Ruby Yes
16 Classic Visual Basic ?
17 Objective-C Yes
18 Perl Yes
19 Lua Yes
20 Mathlab ?
21 SAS ?
22 Prolog Yes
23 (Visual) FoxPro ?
24 Scratch ?
25 COBOL ?
26 Julia ?
27 Kotlin Yes
28 Rust Yes
29 Ada Yes
30 Lisp Yes
31 Fortran ?
32 Groovy ?
33 VBScript ?
34 PL/SQL ?
35 D ?
36 Scala Yes
37 Haskell ?
38 Dart Yes


Comments

It should be easy to call the C WinSCard API from assembly language. So the answer could be "yes". I learned assembly language with a Motorola 6809 and then a Motorola 68000. I am not a fan of the Intel x86 assembly language with its very strange register names (to be backward compatible). Yes, I could also use ARM or RISC-V CPUs. I let the exercise to write an example in assembly language to the readers.

Not listed

Some programming languages are not listed in the TIOBE index but do provide a PC/SC wrapper:

  • Elixir
  • Erlang
  • OCaml

Windows technologies

Some languages are specific to the Microsoft Windows system. I can't use them since I do not use Windows. They are:

  • Visual Basic
  • Classic Visual Basic
  • VBScript
  • Visual FoxPro.

It looks like Visual Basic is also available for GNU/Linux. But I don't want to invest time in these technologies.

Also note that all the computer languages with PC/SC support exist in a Free Software implementation. I am not sure for the Microsoft languages.

Language I would be surprised to get PC/SC support

R and SAS are languages used for statistics.

Scratch is used for education.

Mathlab is for numeric computing.

COBOL is very old. I do not expect any COBOL program needing access to smart cards. Same remark for Fortran. COBOL and Fortran are still used and it looks like it is possible to call C functions from both of them. So there is hope .

Languages that could have a PC/SC wrapper

What I had not yet found

SQL: (SQL Server) PC/SC List Smart Card Readers (and USB Tokens)

This is for SQL Server, so may be limited to the Microsoft product and not the SQL language.

Conclusion

It was a lot of fun to discover and write a sample codes for all the 30 languages.

For some (4) of the PC/SC wrappers I am the maintainer so writing a sample code was easy.

The list is not finished and may never be as new programming languages are created from time to time. If you want me to add a new language please contact me.

Thursday, April 14, 2022

PC/SC sample in Erlang

To continue the list of PC/SC wrappers initiated in 2010 with "PC/SC sample in different languages" I now present a new sample code in Erlang.

I use the PC/SC wrapper for Erlang: erlang-pcsc from Alex Wilson. The project description is "libpcsc NIF binding for erlang". The license is BSD 2 clause.

This is the same wrapper I used in the previous blog article "PC/SC sample in Elixir".

The wrapper is available on Hex.pm (The package manager for the Erlang ecosystem) at https://hex.pm/packages/pcsc.

API documentation is available at https://arekinath.github.io/erlang-pcsc/index.html

 

Create a new application

$ rebar3 new app blog
===> Writing blog/src/blog_app.erl
===> Writing blog/src/blog_sup.erl
===> Writing blog/src/blog.app.src
===> Writing blog/rebar.config
===> Writing blog/.gitignore
===> Writing blog/LICENSE
===> Writing blog/README.md

Install pcsc module

Edit the file rebar.config to use:

{deps, [pcsc]}.
{erl_opts, [{i, "_build/default/lib/pcsc/include/"}]}. 

The erl_opts option is needed because we will include one header file from the pcsc module. Maybe it is possible to have a less ugly/hardcoded path.

Upgrade the dependencies:

$ rebar3 upgrade --all
===> Verifying dependencies...
===> Fetching pcsc v1.3.1
===> Fetching rebar3_hex v7.0.1
===> Fetching hex_core v0.8.4
===> Fetching verl v1.1.1
===> Analyzing applications...
===> Compiling verl
===> Compiling hex_core
===> Compiling rebar3_hex
_build/default/plugins/rebar3_hex/src/rebar3_hex_organization.erl:391:5: Warning: public_key:ssh_encode/2 is deprecated and will be removed in OTP 26; use ssh_file:encode/2 instead

===> Fetching lager v3.9.2
===> Fetching goldrush v0.1.9
===> No upgrade needed for pcsc
===> No upgrade needed for lager
===> No upgrade needed for goldrush

Build the dependencies:

$ rebar3 compile
===> Verifying dependencies...
make : on entre dans le rĂ©pertoire « /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src »
cc  -Wall -g -O2 -Wextra -pipe -funsigned-char -fstrict-aliasing -Wchar-subscripts -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wunused -Wuninitialized -Wpointer-arith -Wredundant-decls -Winline -Wformat -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs -Wempty-body -fdiagnostics-color=auto -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wbad-function-cast -Wnested-externs  -Wmissing-declarations -fPIC -I /usr/lib/erlang/erts-12.3.1/include/ -I /usr/lib/erlang/lib/erl_interface-5.2.2/include -pthread -I/usr/include/PCSC  -c -o /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src/pcsc_nif.o /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src/pcsc_nif.c
[...]
cc /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src/pcsc_nif.o -shared -L /usr/lib/erlang/lib/erl_interface-5.2.2/lib -lei -lpcsclite -o /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src/../priv/pcsc_nif.so
make : on quitte le rĂ©pertoire « /home/rousseau/Documents/blog/erlang/_build/default/lib/pcsc/c_src »
===> Analyzing applications...
===> Compiling goldrush
===> Compiling lager
===> Compiling pcsc
===> Analyzing applications... ===> Compiling blog

Edit the file src/blog.app.src to declare the pcsc application.

It should look like:

[...]
  {applications,
   [kernel,
    stdlib,
    pcsc
   ]},
[...]

Sample code

Create the source code file src/blog.erl with the content:

-module(blog).
-export([main/0]).

-include("iso7816.hrl").

main() ->
  % get all the available readers
  {ok, Readers} = pcsc_card_db:list_readers(),

  % use the first reader
  [Reader | _] = Readers,
  io:fwrite("Using: ~s~n", [Reader]),

  % connect
  {ok, Card} = pcsc_card:start_link(Reader, shared, [t1, t0]),

  % select applet
  Aid = << 160, 0, 0, 0, 98, 3, 1, 12, 6, 1 >>,
  Select_apdu = #apdu_cmd{cla = iso, ins = select, p1 = 4, p2 = 0, data = Aid},
  {ok, Select_replies} = pcsc_card:command(Card, Select_apdu),
  io:write(Select_replies),
  io:fwrite("~n"),

  % command
  Command_apdu = #apdu_cmd{ cla = iso, ins = 0, p1 = 0, p2 = 0 },
  {ok, Command_replies} = pcsc_card:command(Card, Command_apdu),
  io:write(Command_replies),
  io:fwrite("~n"),

  % extract the answer
  [Reply | _] = Command_replies,
  case Reply of
    {apdu_reply, _, ok, Msg} ->
      io:write(binary_to_atom(Msg)),
      io:fwrite("~n");
    {apdu_reply, _, error, _} ->
      io:fwrite("Error~n")
  end.

Output

Generating a standalone Erlang application looks complex. But you can test your code using the interactive shell.

$ rebar3 shell
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling blog
Erlang/OTP 24 [erts-12.3.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Eshell V12.3.1  (abort with ^G)
===> Booted syntax_tools
===> Booted compiler
===> Booted goldrush
===> Booted lager
===> Booted pcsc
===> Booted blog
 
1> blog:main().
Using: Gemalto PC Twin Reader 00 00
[{apdu_reply,t1,ok,none}]
[{apdu_reply,t1,ok,<<72,101,108,108,111,32,119,111,114,108,100,33>>}]
'Hello world!'
ok
2> 

Comments

ehecatl

An older github project also exist at https://github.com/zgbjgg/ehecatl
Its description is "An erlang library for read/write nfc smart cards".

I filed 2 issues in 2020: Missing <PCSC/winscard.h>? and More complete PC/SC wrapper? but got no answer.

This project has not seen any commit since 2014.

So I guess this project is dead.

erlang-pcsc 

The only problem I have with erlang-pcsc is that, if no smart card reader is connected, I get:

$ rebar3 shell
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling blog
Erlang/OTP 24 [erts-12.3.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Eshell V12.3.1  (abort with ^G)
1> ===> Booted syntax_tools
===> Booted compiler
===> Booted goldrush
===> Booted lager
===> Booted pcsc
===> Booted blog
23:31:49.563 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.622 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.677 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.729 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.782 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.836 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.889 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.941 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:49.992 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
23:31:50.044 [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok
etc...

The error -2146435026 is SCARD_E_NO_READERS_AVAILABLE and is not really an error for SCardListReaders().

I filed a github issue [warning] got pcsc_reader_error: {error,{pcsc_error,-2146435026,no_readers,"Cannot find a smart card reader."}}; restarted ok #4 but with no answer so far.

Conclusion

Thanks Alex for the Erlang PC/SC wrapper. And thanks tofferoma, from the elixir forum, for your help in writing the Erlang sample code.

If you work on a Free Software PC/SC wrapper that is not yet in my list please let me know.

Wednesday, April 13, 2022

PC/SC sample in Elixir

To continue the list of PC/SC wrappers initiated in 2010 with "PC/SC sample in different languages" I now present a new sample code in Elixir.

Elixir uses the Erlang virtual machine: BEAM. I wanted to start with an example in Erlang but Erlang is more complex (for me) so I have not yet a working sample code in Erlang.

I use the PC/SC wrapper for Erlang: erlang-pcsc from Alex Wilson. The project description is "libpcsc NIF binding for erlang". The license is BSD 2 clause.

The wrapper is available on Hex.pm (The package manager for the Erlang ecosystem) at https://hex.pm/packages/pcsc.

API documentation is available at https://arekinath.github.io/erlang-pcsc/index.html

Elixir sample project

Create a new Elixir project using mix new ...

$ mix new blog
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/blog.ex
* creating test
* creating test/test_helper.exs
* creating test/blog_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd blog
    mix test

Run "mix help" for more commands.

Edit the file mix.exs and add the pcsc dependency. You should have something like:

[...]
  defp deps do
    [
	{:pcsc, "~> 1.3"},
    ]
  end
[...]

Install the dependency using mix deps.get

$ mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
New:
  goldrush 0.1.9
  lager 3.9.2
  pcsc 1.3.1
* Getting pcsc (Hex package)
* Getting lager (Hex package)
* Getting goldrush (Hex package)

Source code

Now we create a file blog.exs that contains (sorry, source-highlight does not provide syntax colorization for Elixir):

# list card readers
{:ok, readers} = :pcsc_card_db.list_readers()

# use the fist reader
[reader | _] = readers
IO.puts("Using reader: " <> reader)

# connect to the card
{:ok, card} = :pcsc_card.start_link(reader, :shared, [:t1, :t0])

aid = << 160, 0, 0, 0, 98, 3, 1, 12, 6, 1 >>
select_apdu = {:apdu_cmd, :default, :iso, :select, 4, 0, aid, :none}

# send select APDU
{:ok, replies} = :pcsc_card.command(card, select_apdu)
IO.inspect replies

# send command APDU
command_apdu = {:apdu_cmd, :default, :iso, 0, 0, 0, :none, :none}
{:ok, replies} = :pcsc_card.command(card, command_apdu)
IO.inspect replies

# get the first reply only
[reply | _] = replies
case reply do
	{:apdu_reply, _, :ok, msg} -> IO.puts(msg)
	{:apdu_reply, _, :error, _} -> IO.puts("Failed")
end

Output

You can now build and run the code using mix run ...

The first time you run mix run the pcsc wrapper will be built automatically. After that you only get the build & execution of the sample code.

$ mix run blog.exs

17:40:50.239 [error] calling logger:remove_handler(default) failed: :error {:badmatch, {:error, {:not_found, :default}}}
17:40:50.273 [info] Application lager started on node nonode@nohost
17:40:50.280 [info] Application pcsc started on node nonode@nohost
17:40:50.281 [info] Application blog started on node nonode@nohost
Using reader: Gemalto PC Twin Reader 00 00
[{:apdu_reply, :t1, :ok, :none}]
[{:apdu_reply, :t1, :ok, "Hello world!"}]
Hello world!

Remarks

I do not have any complaints for the Erlang PC/SC wrapper. It built fine on the first try. Nice work Alex.

As always my sample code is very minimal with no error handling. It is just a short sample.

Thanks to Stéphane Bortzmeyer for his Elixir training. That gave me the idea to try Elixir.

A big thank to tofferoma for his help on the Elixir forum on "How to access PCSC card readers via erlang/elixir?".

Conclusion

If you work on a Free Software PC/SC wrapper that is not yet in my list please let me know.