Features/Smartcard

From QEMU

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;