Features/Smartcard
Smartcard support
Future smart card support will be based on:
- A Bus:
- CCID specification for USB Smart card reader device implemented as a ccid bus (-device usb-ccid)
- Two devices (you can use either one)
- 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;