Click here to Skip to main content
15,881,755 members
Articles / Programming Languages / C#

Using Smart cards with a Windows Store App

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
10 Feb 2013CPOL8 min read 32K   1.7K   18   4
This article describes a solution to access API and resources that are not available with WinRT.

Introduction 

Some time ago I tried to port my Smart card framework for .NET to WinRT components in C++. As I have some experience with both smart card technoogy and COM components, that was I thought an interesting exercise.

So I created a simple WinRT component project in C++/CX to give access to a Windows Store application to smart card features. In a C++ application, you include winscard.h and this gives you access to a PC/SC API to communicate with the card. Unfortunately if you do that in a Windows store project, all the smart card API definitions are disabled by Microsoft.

I got a confirmation from Microsoft of what I discovered in the source of the .h. For a reason I don't really understand there is simply no way to get access to a smart card in a Windows Store application or library using the standard PC/SC API.

However I'm kind of obstinate and I don't give up easily when I'm trying to do something. Windows 8 still can run legacy windows application in what they call Windows Desktop. I could perfectly run my .NET smart card framework application in the desktop mode of Windows 8, so I had the simple following idea. If I can run a WCF service in the Desktop mode and use this WCF service from a WinRT component, then I have a solution to build a smart card component for Windows Store apps ... So far Microsoft didn't disable WCF in WinRT, it is still highly necessary to access the cloud!

In a previous article I introduced a WCF wrapper for my Smart card framework for .NET. This exercice doesn't have a lot of interest with Windows 7 or XP as smart cards are supported by PC/SC, but it is currently the only way you can access a smart card from a Windows Store app.

Image 1

Fig. 1: Components interaction diagram

The WinRT component to connect with the WCF smart card service

A smart card is a relatively slow device, so the overhead introduced by the WCF service is unnoticeable, especially with one of the binary bindings like Net TCP or Named Pipe. The WCF smart card service is described in a previous article. It is hosted in a windows form application that needs to be started when the system starts-up. Windows 7 and Windows 8 have restriction for the smart card access when running in a Windows service, that's why it needs to be hosted in a windows application, that could be a console eventually.

The service has a MEX end point so it is easy to create the client component. For the WinRT component I chose the NetTcp binding because when importing the reference it creates everything and you just need to call a parameter-less constructor to instantiate the WCF client. If you want to use the NamedPipe binding you need to instantiate the WCF client with a binding and endpoint address. I tested both bindings in a console test application and I couldn't notice any performance difference between the 2 bindings.

The code of the WinRT wrapper is given below:  

/// <summary>
/// This is a simple component to manage a smartcard
/// 
/// Method are made synchronous because the service on the local machine and a smartcard
/// although not very fast is a quite responsive device..
/// </summary>
public sealed class Smartcard
{
    private SCardService.RemoteCardClient cardClient = null;
    private const int TIMEOUT = 10000;

    public Smartcard()
    {
	// Create an instance of the 
	cardClient = new SCardService.RemoteCardClient();
    }

    /// <summary>
    /// Gets the list of readers
    /// 
    /// REM: This method is not really at its place and should be in a seperate 
    /// component. Maybe later if I have some time
    /// </summary>
    /// <returns>A string array of the readers</returns>
    public string[] ListReaders()
    {
	Task<ObservableCollection<string>> readers = cardClient.ListReadersAsync();

	try
	{
	    return readers.Result.ToArray();
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary>
    /// Connects to a card. Establishes a card session
    /// </summary>
    /// <param name="Reader">Reader string</param>
    /// <param name="ShareMode">Session share mode</param>
    /// <param name="PreferredProtocols">Session preferred protocol</param>
    public void Connect(string reader, SHARE shareMode, PROTOCOL preferredProtocols)
    {
	try
	{
	    cardClient.ConnectAsync(reader, (SCardService.SHARE)shareMode, (SCardService.PROTOCOL)preferredProtocols).Wait(TIMEOUT);
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary> 
    /// Disconnect the current session
    /// </summary>
    /// <param name="Disposition">Action when disconnecting from the card</param>
    public void Disconnect(DISCONNECT disposition)
    {
	try
	{
	    cardClient.DisconnectAsync((SCardService.DISCONNECT)disposition).Wait(TIMEOUT);
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary>
    /// Transmit an APDU command to the card
    /// </summary>
    /// <param name="ApduCmd">APDU Command to send to the card</param>
    /// <returns>An APDU Response from the card</returns>
    public APDUResponse Transmit(APDUCommand apduCmd)
    {
	Task<SCardService.APDUResponse> task = cardClient.TransmitAsync(
	    new SCardService.APDUCommand()
	    {
	        Class = apduCmd.Class,
		Ins = apduCmd.Ins,
		P1 = apduCmd.P1,
		P2 = apduCmd.P2,
		Le = apduCmd.Le,
		Data = apduCmd.Data
	    });

	try
	{
	    SCardService.APDUResponse resp = task.Result;

	    return new APDUResponse()
	    {
		SW1 = resp.SW1,
		SW2 = resp.SW2,
		Data = resp.Data
	    };
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
	}

    /// <summary>
    /// Begins a card transaction
    /// </summary>
    public void BeginTransaction()
    {
	try
	{
	    cardClient.BeginTransactionAsync().Wait(TIMEOUT);
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary>
    /// Ends a card transaction
    /// </summary>
    public void EndTransaction(DISCONNECT disposition)
    {
	try
	{
	    cardClient.EndTransactionAsync((SCardService.DISCONNECT)disposition).Wait(TIMEOUT);
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary>
    /// Gets the attributes of the card
    /// 
    /// This command can be used to get the Answer to reset
    /// </summary>
    /// <param name="AttribId">Identifier for the Attribute to get</param>
    /// <returns>Attribute content</returns>
    public byte[] GetAttribute(UInt32 attribId)
    {
	Task<byte[]> task = cardClient.GetAttributeAsync(attribId);

	try
	{
	    return task.Result;
	}
	catch (AggregateException ax)
	{
	    throw new Exception(ProcessAggregateException(ax));
	}
    }

    /// <summary>
    /// This method extract the error message carried by the WCF fault
    /// 
    /// Supports SmarcardFault and GeneralFault
    /// </summary>
    /// <param name="ax">AggregateException object</param>
    /// <returns>Extracted message</returns>
    private static string ProcessAggregateException(AggregateException ax)
    {
	string msg = "Unknown fault";
	FaultException<SCardService.SmartcardFault> scFault = ax.InnerException as FaultException<SCardService.SmartcardFault>;
	if (scFault != null)
	{
	    msg = scFault.Detail.Message;
	}
	else
	{
	    FaultException<SCardService.GeneralFault> exFault = ax.InnerException as FaultException<SCardService.GeneralFault>;
	    if (exFault != null)
	    {
		msg = exFault.Detail.Message;
	    }
	}

	return msg;
    }
}

The Smartcard class is a WinRT component written in C# that simply wraps the WCF smart card service client. To create the generated wrapper, I simply ran the WCF service on the windows desktop and because it exposes a MEX end-point I could let Visual Studio generate the proxy. I could have used the WCF service directly in the Windows Store application, but it is a much better construction to have a component that does the work as it can be reused by different applications.

When you import a WCF service in a WinRT component or a Windows Store app you only get an async version of the methods. In this first version I only provide synchronous methods as the service runs on the local machine and the smart card is a quite responsive device. However if I have some time and as an exercice I will implement some asynchronous version of the methods (which should be quite straightforward).

If you look at the Transmit method, which the most complex one, there are basically 2 actions:

  • Call the async method, TransmitAsync 
  • Call the Result method on the generated Task<> running the service method

As the method call is running in a separate thread if your service can throw a FaultException this exception cannot be caught simply with a catch(FaultException<SmartcardException> ex) for example. Fortunately WinRT provides an AggregateException that can be caught with a catch around the asynchronous call and that contains a reference to the exceptions that could have happened inside the thread.

So the code of an asynchronous call with exception handling looks like this:

public byte[] GetAttribute(UInt32 attribId)
{
    Task<byte[]> task = cardClient.GetAttributeAsync(attribId);

    try
    {
	return task.Result;
    }
    catch (AggregateException ax)
    {
	throw new Exception(ProcessAggregateException(ax));
    }
}

The AggregateException instance contains an InnerException member that contains the main exception that has interrupted the thread. In our case it should contains one of the FaultException that is supported by the service implementation. The method ProcessAggregateException extracts the expected FaultException and returns a message indicating what happens. This is a simplistic implementation, my objective being just to avoid a nasty app termination if an exception happens within a service call.

A real app should make the difference between a recoverable exception and an exception that terminated the communication with the WCF service and would need the app to reconnect to the WCF service.

The demo application: A Windows Store ExchangeAPDU app

In the Smart card framework for .NET article I published a simple ExchangeAPDU demo application to send low level command to a smart card. I chose to do a simple port of that application to Windows Store. However it is a simpler version as the WCF service doesn't support card events yet.

I used C# to write this application as there is no performance issue to worry with such a demonstration. Windows Store app in C# use a technology similar to WPF so my simple app UI has a model, the Smartcard component and its APDUCommand and APDUResponse components, a view which is the main page and a View model to manage the view. There is strictly no code behind for the view.

In order to support the commands I extracted few classes from a nice MVVM framework that can be obtained on Github.

Image 2

Fig. 2: ExchangeAPDU app, Select MF (3F00) on a SIM card 

Filter for the data byte TextBox 

The support of XAML in Windows Store app doesn't seem to be as complete as the latest version of WPF was. In order to add some character filtering to the different TextBox controls I couldn't use standard WPF features.

  • PreviewTextInput is not supported  
  • UpdateSourceTrigger is not supported 

Those are two issues to support filtering. Without UpdateSourceTrigger it is not possible to choose when the source data is updated when characters are entered in the TextBox control. Without PreviewTextInput it is not possible to get the text that was entered before it is displayed.  

The only event available that I could find is KeyDown, but it gets the value of the VirtualKey that was entered and the value that it returns is not exact for numbers. For example on a french keyboard if you press '6' without shift it is '-', but for both characters you get VirtualKey.Number6. As a result some unwanted characters are not filtered.

Without UpdateSourceTrigger it is not possible to change the way the source is updated, so by default it is updated when the control loses focus. As I want the data to be updated when text is entered I normally would have used UpdateSourceTrigger=PropertyChanged.

I searched on the forums and I found a solution to work around the lack of UpdateSourceTrigger. It is a custom behavior that can be applied to the TextBox to update the source when characters are entered.

public class TextBoxUpdateSourceBehaviour
{
    private static Dictionary<TextBox, PropertyInfo> _boundProperties = new Dictionary<TextBox, PropertyInfo>();

    public static readonly DependencyProperty BindingSourceProperty =
        DependencyProperty.RegisterAttached(
        "BindingSource",
        typeof(string),
        typeof(TextBoxUpdateSourceBehaviour),
        new PropertyMetadata(default(string), OnBindingChanged));

    public static void SetBindingSource(TextBox element, string value)
    {
        element.SetValue(BindingSourceProperty, value);
    }

    public static string GetBindingSource(TextBox element)
    {
        return (string)element.GetValue(BindingSourceProperty);
    }

    private static void OnBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var txtBox = d as TextBox;
        if (txtBox != null)
        {
            txtBox.Loaded += OnLoaded;
            txtBox.TextChanged += OnTextChanged;
        }
    }

    static void OnLoaded(object sender, RoutedEventArgs e)
    {
        var txtBox = sender as TextBox;
        if (txtBox != null)
        {

            // Reflect the datacontext of the textbox to find the field to bind to.
            if (txtBox.DataContext != null) // DataContext is null in the designer
            {
                var dataContextType = txtBox.DataContext.GetType();
                AddToBoundPropertyDictionary(txtBox, dataContextType.GetRuntimeProperty(GetBindingSource(txtBox)));
            }
        }
    }

    static void AddToBoundPropertyDictionary(TextBox txtBox, PropertyInfo boundProperty)
    {
        PropertyInfo propInfo;
        if (!_boundProperties.TryGetValue(txtBox, out propInfo))
        {
            _boundProperties.Add(txtBox, boundProperty);
        }
    }

    static void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var txtBox = sender as TextBox;
        if (txtBox != null)
        {
            _boundProperties[txtBox].SetValue(txtBox.DataContext, txtBox.Text);
        }
    }

} 

To use this behavior you need to set the namespace in the XAML that way xmlns:util="using:Core.Wpf", then in the TextBox XAML you must add the following property: util:TextBoxUpdateSourceBehaviour.BindingSource="Class" 

Getting the source

You can get the source code of those projects from the ZIP files attached to that article or you can follow those projects on github where they will be updated regularly as this is a public repository.

.NET Smartcard library: https://github.com/orouit/SmartcardFramework.git
 WinRT component and demo app: https://github.com/orouit/SmartcardWithWindowsStore.git

Points of Interest 

Like I mentioned in the previous article, a WCF service is the solution to access a smart card resource from a Windows Store app. This demo application proves it!

In fact this technique can be applied to any case where an API of windows is no longer available to a Windows Store application. However I would only suggest to use this technique in an enterprise context where your application is not distributed through the Windows store. I haven' checked with the App submission toolkit but I suspect that an application that would access a non supported feature of windows using a WCF service would not be accepted. 

History

  • 10/2/2013: UI updated with hexadecimal filtering. Code up to date on Github. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Connect In Private
Singapore Singapore
Software Architect, COM, .NET and Smartcard based security specialist.

I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I preferred digital to analog.

I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.

For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when things don't go right!

After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small computers!
I've been back into business to design the licensing system for the enterprise solution for Consistel using a .NET smart card (yes they can run .NET CLR!)

I'm currently designing a micro-payment solution using the NXP DESFire EV1 with the ACSO6 SAM of ACS. I can then add a full proficient expertise on those systems and NFC payments.
This technology being under strict NDA by NXP I cannot publish any related article about it, however I can provide professional consulting for it.

You can contact me for professional matter by using the forum or via my LinkedIn profile.

Comments and Discussions

 
QuestionQuery on Windoes RT Pin
mk_cs17-Oct-13 20:13
mk_cs17-Oct-13 20:13 
AnswerRe: Query on Windoes RT Pin
orouit18-Oct-13 18:14
professionalorouit18-Oct-13 18:14 
GeneralMy vote of 5 Pin
Abhishek Nandy5-Feb-13 19:04
professionalAbhishek Nandy5-Feb-13 19:04 
Excellent article..
GeneralMy vote of 5 Pin
Abinash Bishoyi5-Feb-13 7:51
Abinash Bishoyi5-Feb-13 7:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.