Introduction
In this article, you will learn how to use smart card that runs a .NET CLR and use it for secure storage operations and cryptographic operations. In a previous article, I described how to use a smart card certificate store with the .NET Framework security API. So what is the difference in using the CSP API and using a .NET card to achieve the same operation? The answer is a lot of flexibility and an extended security.
Background
The .NET smart card V2 is the equivalent of the Java card in the Microsoft ecosystem. I have used previously Java card and this .NET card brings some innovative solution to the limitation of the APDU protocol. Applications that you write into the card are exposed to the client application using an implementation of the .NET remoting technology. With this protocol, the card becomes a mini server that runs a .NET application. Of course, there are some limitations and I'll try to give some of them.
The smart card and the USB reader.
Important
In order to use the code of this article, you will need to have a Gemalto .NET card v2.2 and the .NET Smartcard SDK V2.2 that integrates the development with Visual Studio 2008. You can get some smart cards and readers from the Gemalto WEB store, however the .NET card SDK V2.2 is now free of charge.
.NET Remoting to Communicate with the On Card Application
The .NET card runs a small footprint .NET CLR and .NET Framework which means you can develop .NET assemblies that will run inside the card and take advantage of the on card APIs.
One of the most interesting features of that .NET smart card is that you don't have any more to design and use APDU commands, the framework provides a .NET remoting plumbing which allows the developer to expose its card services as simple remoting services.
In the card, you declare your services and then use the generate stub to communicate with those services.
public class CodeProjectServer
{
private const string REMOTE_LOGIN_URI = "LoginStoreService.uri";
private const string REMOTE_AUTH_URI = "AuthenticationService.uri";
public static int Main()
{
ChannelServices.RegisterChannel(new APDUServerChannel());
RemotingConfiguration.RegisterWellKnownServiceType(typeof(LoginStoreService),
REMOTE_LOGIN_URI, WellKnownObjectMode.Singleton);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(AuthenticationService),
REMOTE_AUTH_URI, WellKnownObjectMode.Singleton);
return 0;
}
}
In this example, two services are declared and started when you execute this application in the card. On the PC side, you will need to write very little code.
private const string AUTHENTICATION_URL =
"apdu://selfdiscover/AuthenticationService.uri";
private APDUClientChannel channel = null;
private AuthenticationService authService = null;
public AuthenticationDemo()
{
channel = new APDUClientChannel();
ChannelServices.RegisterChannel(channel, false);
authService = (AuthenticationService)Activator.GetObject
(typeof(AuthenticationService), AUTHENTICATION_URL);
aesAlgo = Rijndael.Create();
aesAlgo.Key = AESKey;
aesAlgo.IV = AESIv;
}
You can now use the authService
reference to call the methods of the AuthenticationService
.
byte[] encrSignature = authService.GetAuthenticationSignature(encrChallenge);
A Password Manager Server in the .NET Smart Card
In one of my previous jobs, I worked on an application that was using a PKCS smart card to securely store login credential. Those credentials were then used by an application that was auto-filling the login in a web browser as well as insuring a secure login for banking site, to avoid phishing and spoofing.
Storing those data in PKCS objects requires to use the PKCS#11 API which is a C API and use some mechanism that are not very flexible. Let's see how this can be done easily using the .NET smart card.
Programming an application in a smart card, even running a .NET CLR must respect some rules if you want to get a responsive application. First, you must consider that the byte code that is executed by the card is not pre-compiled by a JIT but executed by an VM that converts into machine code. Another consideration is the memory capacity of the smart card chip. This .NET smart card is using a chip that has 16K of RAM and you have around 70K of flash memory (non-volatile memory) for your assemblies, storage and the equivalent of the heap. Flash memory is of course much slower than RAM which means that your application is going to run 90% of its time on a hard drive! (if you compare with a PC)
By experience, I discovered that some framework implementations are quite slow, for example you can use the file system if you want but reading and writing to files using FileStream
is very slow. Because static
class members are stored in the flash memory like the file storage, it is a better approach to use a static
class to store data with a good performance.
Designing the Login Credential Storage Class
Because the flash memory is relatively slow, I designed the storage using a fixed size array of LoginItem
objects. I used a second fixed array of string
that contains a list of login alias names. So when it searches for a LoginItem
with a given name, it searches for the login alias and gets the index, then uses this index to get the LoginItem
. The result is fast access to any LoginItem
. As the memory is limited, using a fixed size array is not an issue.
The following extract show the simple algorithm I used to search the index list. Each iteration reads two elements of the array at the same time, one starting from the beginning and one starting from the end. Considering the amount of data in the array, this should ensure that an element would be found in a limited number if iterations.
public static int FindLogin(string name)
{
int index = -1;
for (int n = 0; n < MAX_LOGINS; n++)
{
if (loginAlias[n] != null && loginAlias[n] == name)
{
index = n;
break;
}
if (loginAlias[MAX_LOGINS - n - 1] != null &&
loginAlias[MAX_LOGINS - n - 1] == name)
{
index = MAX_LOGINS - n - 1;
break;
}
if (n == (MAX_LOGINS - n - 1))
{
break;
}
}
return index;
}
Adding a PIN to Access the LoginStoreService
Usually a smart card application is protected with a CHV code (Card Holder Verification). When this code is verified, the user can call the methods that are protected by the given code. The smart card .NET framework provides a PIN
class that implements the behavior of a PIN code. A PIN code is verified and remains verified until the card session is closed or the PIN is invalidated by calling the method Invalidate
.
The following code shows the declaration of the PIN code in the LoginStoreService
implementation class.
private static PIN pinCode = new PIN(DEFAULT_PIN, 3);
The LoginStorageService
class implements the service itself. This service has the following methods:
public string[] GetLoginAliasList();
public bool AddLogin(string alias, string loginPageUrl, string user, string password);
public bool GetLogin(string alias, out string loginPageUrl,
out string user, out string password);
public bool RemoveLogin(string alias);
Those methods are accessible using .NET remoting in the client application. However, there are some limitations to this implementation of .NET remoting. Only class that are defined in the smart card .NET framework can be used as parameters in the signature of a remote method and only exceptions defined in this framework can be thrown by the service method and caught in the client application.
A Client Application using the LoginStorageService
Now that we have written this service in the card, it is time to use it! The LoginStoreManager
application is a simple Winforms application that uses the LoginStorageService
on the card to manage your login information on the card. This application is not a password manager that would automatically register your login/passwords and enter them in a web page, it is only the part that will manage the login/password in the card. I think you can easily find an open source app that does that part and integrate this code to this app.
An Authentication Service in the .NET Smart Card
Authentication is a common security subject in which one party must prove to the other that he is the one he claims. In this example, the card is going to prove that it is what it claims to be.
Normally when you want to use a certificate you would enter a PIN, however in some cases you may not want to have to enter the PIN and for example use this PIN for another purpose, like certificate administration in the card.
The authentication service uses RSA signature and AES encryption. The challenge must be encrypted with a secret key which is hard coded in the token. The signature is done using the RSA key which is unique to each token and is then encrypted using the AES key.
The encryption is not necessary (but can be useful) and is used to demonstrate the capability of the .NET card compare to using the card as a certificate store for the Microsoft CSP.
The card proposes a simple interface for the authentication:
public RSAParameters GetPublicKey();
public byte[] GetAuthenticationSignature(byte[] encrChallenge);
and some methods for a very simple PIN management:
public void VerifyPIN(string pinValue);
public bool PINEnabled;
The AuthenticationServiceDemo
console application demonstrates the authentication process between the .NET card and the application.
The complete process of decryption/signature/encryption is done in around 1/2 a second by the smart card which is very correct performance for such a device. This smart card is built with a crypto chipset which explains this performance, however you will have to be very careful with the design of the card application and use the .NET framework differently than what you would with a PC application.
Points of Interest
As the price of such smart cards have dramatically gone down in the past few years, it is now cost effective to design security solutions that use cryptographic smart cards, if you have in your organization some engineers with a good knowledge of cryptographic mechanism and smart card knowledge.
For example, smart card technology is used by the most efficient software licensing systems using a dongle.
I hope that you enjoyed this article and that it opened your vision of what can be done with such a small device!
History
- 30th September, 2011: Initial version
- 9th October, 2011: Small update to include a link to the Gemalto .NET SDK which is now available for free from Gemalto WEB site