Features/Smartcard: Difference between revisions

From QEMU
(add VSCard protocol)
(fix moinmoinisms)
Line 17: Line 17:


To create the include file run:
To create the include file run:
{{{
 
xsel | gawk 'BEGIN { x=0 }; /^{{{$/ { x+=1 }; /^}}}$/ { x-=1; print ""; }; x==1 && ! /{{{/ { print }' > libcacard/vscard_common.h
<pre>xsel | gawk 'BEGIN { x=0 }; /^<pre>$/ { x+=1 }; /^<\/pre>$/ { x-=1; print ""; }; x==1 && ! /<pre>/ { print }' > libcacard/vscard_common.h</pre>
}}}


=Preamble=
=Preamble=
{{{
<pre>
/* Virtual Smart Card protocol definition
/* Virtual Smart Card protocol definition
  *
  *
Line 42: Line 41:


#include <stdint.h>
#include <stdint.h>
}}}
</pre>
=Message Types=
=Message Types=
{{{
<pre>
typedef enum {
typedef enum {
     VSC_Init = 1,
     VSC_Init = 1,
Line 56: Line 55:
     VSC_Reconnect
     VSC_Reconnect
} VSCMsgType;
} VSCMsgType;
}}}
</pre>
=Error Codes=
=Error Codes=
{{{
<pre>
typedef enum {
typedef enum {
     VSC_NO_ERROR=0,
     VSC_NO_ERROR=0,
Line 65: Line 64:
     VSC_CARD_ALREAY_INSERTED,
     VSC_CARD_ALREAY_INSERTED,
} VSCErrorCode;
} VSCErrorCode;
}}}
</pre>
=Reserved Reader ID numbers=
=Reserved Reader ID numbers=
{{{
<pre>
#define VSCARD_UNDEFINED_READER_ID  0xffffffff
#define VSCARD_UNDEFINED_READER_ID  0xffffffff
#define VSCARD_MINIMAL_READER_ID    0
#define VSCARD_MINIMAL_READER_ID    0
}}}
</pre>
=Other Constants=
=Other Constants=
{{{
<pre>
#define VSCARD_MAGIC (*(uint32_t*)"VSCD")
#define VSCARD_MAGIC (*(uint32_t*)"VSCD")
}}}
</pre>
=Header struct=
=Header struct=
{{{
<pre>
/* Header
/* Header
  * Each message starts with the header. The reader_id
  * Each message starts with the header. The reader_id
Line 87: Line 86:
     uint8_t    data[0];
     uint8_t    data[0];
} VSCMsgHeader;
} VSCMsgHeader;
}}}
</pre>
=Messages=
=Messages=
==Init==
==Init==
{{{
<pre>
/* VSCMsgInit              Client <-> Host
/* VSCMsgInit              Client <-> Host
  * Client sends it on connection, Host replies with VSCMsgInit.
  * Client sends it on connection, Host replies with VSCMsgInit.
Line 104: Line 103:
                                   array may grow in the future*/
                                   array may grow in the future*/
} VSCMsgInit;
} VSCMsgInit;
}}}
</pre>
==Error==
==Error==
{{{
<pre>
/* VSCMsgError              Client <-> Host
/* VSCMsgError              Client <-> Host
  * This message is a possible response to any of:
  * This message is a possible response to any of:
Line 117: Line 116:
     uint32_t  code;
     uint32_t  code;
} VSCMsgAck;
} VSCMsgAck;
}}}
</pre>
==Reader Add==
==Reader Add==
{{{
<pre>
/* VSCMsgReaderAdd          Client -> Host
/* VSCMsgReaderAdd          Client -> Host
  * Host replies with allocated reader id in ReaderAddResponse
  * Host replies with allocated reader id in ReaderAddResponse
Line 129: Line 128:
     uint8_t    name[0];
     uint8_t    name[0];
} VSCMsgReaderAdd;
} VSCMsgReaderAdd;
}}}
</pre>
==Reader Add Response==
==Reader Add Response==
{{{
<pre>
/* VSCMsgReaderAddResponse  Host -> Client
/* VSCMsgReaderAddResponse  Host -> Client
  * Reply to ReaderAdd. The reader_id provided in this message
  * Reply to ReaderAdd. The reader_id provided in this message
Line 140: Line 139:
typedef struct VSCMsgReaderAddResponse {
typedef struct VSCMsgReaderAddResponse {
} VSCMsgReaderAddResponse;
} VSCMsgReaderAddResponse;
}}}
</pre>
==Reader Remove==
==Reader Remove==
{{{
<pre>
/* VSCMsgReaderRemove      Client -> Host
/* VSCMsgReaderRemove      Client -> Host
  * */
  * */
typedef struct VSCMsgReaderRemove {
typedef struct VSCMsgReaderRemove {
} VSCMsgReaderRemove;
} VSCMsgReaderRemove;
}}}
</pre>
==ATR==
==ATR==
{{{
<pre>
/* VSCMsgATR                Client -> Host
/* VSCMsgATR                Client -> Host
  * Answer to reset. Sent for card insertion or card reset.
  * Answer to reset. Sent for card insertion or card reset.
Line 156: Line 155:
     uint8_t    atr[0];
     uint8_t    atr[0];
} VSCMsgATR;
} VSCMsgATR;
}}}
</pre>
==Card Remove==
==Card Remove==
{{{
<pre>
/* VSCMsgCardRemove        Client -> Host
/* VSCMsgCardRemove        Client -> Host
  * */
  * */
typedef struct VSCMsgCardRemove {
typedef struct VSCMsgCardRemove {
} VSCMsgCardRemove;
} VSCMsgCardRemove;
}}}
</pre>
==APDU==
==APDU==
{{{
<pre>
/* VSCMsgAPDU              Client <-> Host
/* VSCMsgAPDU              Client <-> Host
  * Main reason of existance. Transfer a single APDU in either direction.
  * Main reason of existance. Transfer a single APDU in either direction.
Line 173: Line 172:
     uint8_t    data[0];
     uint8_t    data[0];
} VSCMsgAPDU;
} VSCMsgAPDU;
}}}
</pre>
==Reconnect==
==Reconnect==
{{{
<pre>
/* VSCMsgReconnect          Host -> Client
/* VSCMsgReconnect          Host -> Client
  * Host request client to disconnect from it and connect to another
  * Host request client to disconnect from it and connect to another
Line 186: Line 185:
     char      port[128];
     char      port[128];
} VSCMsgReconnect;
} VSCMsgReconnect;
}}}
</pre>

Revision as of 22:18, 29 January 2011

Smartcard support

Future smart card support will be based on:

  • CCID specification for USB Smart card reader device implemented as a ccid bus (-device usb-ccid)
  • passthru protocol to connect to remote computer carrying physical (or virtual) smartcard (-device ccid-card-passthru)
  • emulated card using NSS backend with certificates or real hardware on qemu running host (-device ccid-card-emulated)

This page is mainly about documention the protocol used for remote reader and card support.

The protocol header is libcacard/vscard_common.h.

VSCard protocol

A header/payload protocol between the ccid-card-passthru device and a remote client. The protocol is APDU oriented.

This page contains the header file in a form easy to extract, so this page can stay up to date with the source.

To create the include file run:

xsel | gawk 'BEGIN { x=0 }; /^<pre>$/ { x+=1 }; /^<\/pre>$/ { x-=1; print ""; }; x==1 && ! /<pre>/ { print }' > libcacard/vscard_common.h

Preamble

/* Virtual Smart Card protocol definition
 *
 * This protocol is between a host using virtual smart card readers,
 * and a client providing the smart cards, perhaps by emulating them or by
 * access to real cards.
 *
 * The current implementation passes the raw APDU's from 7816 and additionally
 * contains messages to setup and teardown readers, handle insertion and
 * removal of cards, negotiate the protocol via capabilities and provide for error responses.
 *
 * Copyright (c) 2011 Red Hat.
 *
 * This code is licensed under the LGPL.
 */

#ifndef VSCARD_COMMON_H
#define VSCARD_COMMON_H

#include <stdint.h>

Message Types

typedef enum {
    VSC_Init = 1,
    VSC_Error,
    VSC_ReaderAdd,
    VSC_ReaderAddResponse,
    VSC_ReaderRemove,
    VSC_ATR,
    VSC_CardRemove,
    VSC_APDU,
    VSC_Reconnect
} VSCMsgType;

Error Codes

typedef enum {
    VSC_NO_ERROR=0,
    VSC_GENERAL_ERROR=1,
    VSC_CANNOT_ADD_MORE_READERS,
    VSC_CARD_ALREAY_INSERTED,
} VSCErrorCode;

Reserved Reader ID numbers

#define VSCARD_UNDEFINED_READER_ID  0xffffffff
#define VSCARD_MINIMAL_READER_ID    0

Other Constants

#define VSCARD_MAGIC (*(uint32_t*)"VSCD")

Header struct

/* Header
 * Each message starts with the header. The reader_id
 * value is only relevant
 */
typedef struct VSCMsgHeader {
    uint32_t   type;
    uint32_t   reader_id;
    uint32_t   length;
    uint8_t    data[0];
} VSCMsgHeader;

Messages

Init

/* VSCMsgInit               Client <-> Host
 * Client sends it on connection, Host replies with VSCMsgInit.
 * Client fills its capabilities, host replies with its own.
 *
 * It is not meant to be used for negotiation, i.e. sending more then
 * once from any side, but could be used for that in the future.
 * */
typedef struct VSCMsgInit {
    uint32_t   magic;
    uint32_t   version;
    uint32_t   capabilities[1]; /* receiver must check length,
                                   array may grow in the future*/
} VSCMsgInit;

Error

/* VSCMsgError              Client <-> Host
 * This message is a possible response to any of:
 *  Reader Add
 *  Reader Remove
 *  Card Remove
 * At any point there can be a 
 * */
typedef struct VSCMsgAck {
    uint32_t   code;
} VSCMsgAck;

Reader Add

/* VSCMsgReaderAdd          Client -> Host
 * Host replies with allocated reader id in ReaderAddResponse
 * name - name of the reader on client side, UTF-8 encoded. Only used
 *  for client presentation (may be translated to the device presented to the guest),
 * protocol wise only reader_id 
 * */
typedef struct VSCMsgReaderAdd {
    uint8_t    name[0];
} VSCMsgReaderAdd;

Reader Add Response

/* VSCMsgReaderAddResponse  Host -> Client
 * Reply to ReaderAdd. The reader_id provided in this message
 * will be used to identify the new reader. Since there are no
 * message id's in the protocol there can be only a single outstanding
 * ReaderAdd message.
 * */
typedef struct VSCMsgReaderAddResponse {
} VSCMsgReaderAddResponse;

Reader Remove

/* VSCMsgReaderRemove       Client -> Host
 * */
typedef struct VSCMsgReaderRemove {
} VSCMsgReaderRemove;

ATR

/* VSCMsgATR                Client -> Host
 * Answer to reset. Sent for card insertion or card reset.
 * */
typedef struct VSCMsgATR {
    uint8_t     atr[0];
} VSCMsgATR;

Card Remove

/* VSCMsgCardRemove         Client -> Host
 * */
typedef struct VSCMsgCardRemove {
} VSCMsgCardRemove;

APDU

/* VSCMsgAPDU               Client <-> Host
 * Main reason of existance. Transfer a single APDU in either direction.
 * 
 * */
typedef struct VSCMsgAPDU {
    uint8_t    data[0];
} VSCMsgAPDU;

Reconnect

/* VSCMsgReconnect          Host -> Client
 * Host request client to disconnect from it and connect to another
 * host.
 * Contains new host address as two strings for IPv4 and
 * IPv6 support.
 * */
typedef struct VSCMsgReconnect {
    char       host[128];
    char       port[128];
} VSCMsgReconnect;