/* * sm.h: Support of Secure Messaging * * Copyright (C) 2010 Viktor Tarasov * OpenTrust * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SM_H #define _SM_H #include #ifdef HAVE_UNISTD_H #include #endif #ifdef __cplusplus extern "C" { #endif #include #include #include #define SM_TYPE_GP_SCP01 0x100 #define SM_TYPE_CWA14890 0x400 #define SM_TYPE_DH_RSA 0x500 /** don't use SM */ #define SM_MODE_NONE 0x0 /** let the card driver decide when to use SM, possibly based on the card's ACLs */ #define SM_MODE_ACL 0x100 /** use SM for all commands */ #define SM_MODE_TRANSMIT 0x200 #define SM_CMD_INITIALIZE 0x10 #define SM_CMD_MUTUAL_AUTHENTICATION 0x20 #define SM_CMD_RSA 0x100 #define SM_CMD_RSA_GENERATE 0x101 #define SM_CMD_RSA_UPDATE 0x102 #define SM_CMD_RSA_READ_PUBLIC 0x103 #define SM_CMD_FILE 0x200 #define SM_CMD_FILE_READ 0x201 #define SM_CMD_FILE_UPDATE 0x202 #define SM_CMD_FILE_CREATE 0x203 #define SM_CMD_FILE_DELETE 0x204 #define SM_CMD_PIN 0x300 #define SM_CMD_PIN_VERIFY 0x301 #define SM_CMD_PIN_RESET 0x302 #define SM_CMD_PIN_SET_PIN 0x303 #define SM_CMD_PSO 0x400 #define SM_CMD_PSO_DST 0x401 #define SM_CMD_APDU 0x500 #define SM_CMD_APDU_TRANSMIT 0x501 #define SM_CMD_APDU_RAW 0x502 #define SM_CMD_APPLET 0x600 #define SM_CMD_APPLET_DELETE 0x601 #define SM_CMD_APPLET_LOAD 0x602 #define SM_CMD_APPLET_INSTALL 0x603 #define SM_CMD_EXTERNAL_AUTH 0x700 #define SM_CMD_EXTERNAL_AUTH_INIT 0x701 #define SM_CMD_EXTERNAL_AUTH_CHALLENGE 0x702 #define SM_CMD_EXTERNAL_AUTH_DOIT 0x703 #define SM_CMD_SDO_UPDATE 0x800 #define SM_CMD_FINALIZE 0x900 #define SM_RESPONSE_CONTEXT_TAG 0xA1 #define SM_RESPONSE_CONTEXT_DATA_TAG 0xA2 #define SM_MAX_DATA_SIZE 0xE0 #define SM_SMALL_CHALLENGE_LEN 8 #define SM_GP_SECURITY_NO 0x00 #define SM_GP_SECURITY_MAC 0x01 #define SM_GP_SECURITY_ENC 0x03 /* Global Platform (SCP01) data types */ /* * @struct sm_type_params_gp * Global Platform SM channel parameters */ struct sm_type_params_gp { unsigned level; unsigned index; unsigned version; struct sc_cplc cplc; }; /* * @struct sm_gp_keyset * Global Platform keyset: * - version, index; * - keyset presented in three parts: 'ENC', 'MAC' and 'KEK'; * - keyset presented in continuous manner - raw or 'to be diversified'. */ struct sm_gp_keyset { int version; int index; unsigned char enc[16]; unsigned char mac[16]; unsigned char kek[16]; unsigned char kmc[48]; unsigned kmc_len; }; /* * @struct sm_gp_session * Global Platform SM session data */ struct sm_gp_session { struct sm_gp_keyset gp_keyset; struct sm_type_params_gp params; unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN]; unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN]; unsigned char *session_enc, *session_mac, *session_kek; unsigned char mac_icv[8]; }; /* CWA, IAS/ECC data types */ /* * @struct sm_type_params_cwa */ struct sm_type_params_cwa { struct sc_crt crt_at; }; /* * @struct sm_cwa_keyset * CWA keyset: * - SDO reference; * - 'ENC' and 'MAC' 3DES keys. */ struct sm_cwa_keyset { unsigned sdo_reference; unsigned char enc[16]; unsigned char mac[16]; }; /* * @struct sm_cwa_token_data * CWA token data: * - serial; * - 'small' random; * - 'big' random. */ struct sm_cwa_token_data { unsigned char sn[8]; unsigned char rnd[8]; unsigned char k[32]; }; /* * @struct sm_cwa_session * CWA working SM session data: * - ICC and IFD token data; * - ENC and MAC session keys; * - SSC (SM Sequence Counter); * - 'mutual authentication' data. */ struct sm_cwa_session { struct sm_cwa_keyset cwa_keyset; struct sm_type_params_cwa params; struct sm_cwa_token_data icc; struct sm_cwa_token_data ifd; unsigned char session_enc[16]; unsigned char session_mac[16]; unsigned char ssc[8]; unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN]; unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN]; unsigned char mdata[0x48]; size_t mdata_len; }; /* * @struct sm_dh_session * DH SM session data: */ struct sm_dh_session { struct sc_tlv_data g; struct sc_tlv_data N; struct sc_tlv_data ifd_p; struct sc_tlv_data ifd_y; struct sc_tlv_data icc_p; struct sc_tlv_data shared_secret; unsigned char session_enc[16]; unsigned char session_mac[16]; unsigned char card_challenge[32]; unsigned char ssc[8]; }; /* * @struct sc_info is the * placehold for the secure messaging working data: * - SM type; * - SM session state; * - command to execute by external SM module; * - data related to the current card context. */ struct sm_info { char config_section[64]; unsigned card_type; unsigned cmd; void *cmd_data; unsigned sm_type; union { struct sm_gp_session gp; struct sm_cwa_session cwa; struct sm_dh_session dh; } session; struct sc_serial_number serialnr; unsigned security_condition; struct sc_path current_path_df; struct sc_path current_path_ef; struct sc_aid current_aid; unsigned char *rdata; size_t rdata_len; }; /* * @struct sm_card_response * data type to return card response. */ typedef struct sm_card_response { int num; unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; size_t data_len; unsigned char mac[8]; size_t mac_len; unsigned char sw1, sw2; struct sm_card_response *next; struct sm_card_response *prev; } sm_card_response_t; struct sc_context; struct sc_card; /* * @struct sm_card_operations * card driver handlers related to secure messaging (in 'APDU TRANSMIT' mode) * - 'open' - initialize SM session; * - 'encode apdu' - SM encoding of the raw APDU; * - 'decrypt response' - decode card answer; * - 'close' - close SM session. */ struct sm_card_operations { int (*open)(struct sc_card *card); int (*get_sm_apdu)(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); int (*free_sm_apdu)(struct sc_card *card, struct sc_apdu *apdu, struct sc_apdu **sm_apdu); int (*close)(struct sc_card *card); int (*read_binary)(struct sc_card *card, unsigned int idx, unsigned char * buf, size_t count); int (*update_binary)(struct sc_card *card, unsigned int idx, const unsigned char * buf, size_t count); }; /* * @struct sm_module_operations * API to use external SM modules: * - 'initialize' - get APDU(s) to initialize SM session; * - 'get apdus' - get secured APDUs to execute particular command; * - 'finalize' - get APDU(s) to finalize SM session; * - 'module init' - initialize external module (allocate data, read configuration, ...); * - 'module cleanup' - free resources allocated by external module. */ struct sm_module_operations { int (*initialize)(struct sc_context *ctx, struct sm_info *info, struct sc_remote_data *out); int (*get_apdus)(struct sc_context *ctx, struct sm_info *sm_info, unsigned char *init_data, size_t init_len, struct sc_remote_data *out); int (*finalize)(struct sc_context *ctx, struct sm_info *info, struct sc_remote_data *rdata, unsigned char *out, size_t out_len); int (*module_init)(struct sc_context *ctx, const char *data); int (*module_cleanup)(struct sc_context *ctx); int (*test)(struct sc_context *ctx, struct sm_info *info, char *out); }; typedef struct sm_module { char filename[128]; void *handle; struct sm_module_operations ops; } sm_module_t; /* @struct sm_context * SM context -- top level of the SM data type * - SM mode ('ACL' or 'APDU TRANSMIT'), flags; * - working SM data; * - card operations related to SM in 'APDU TRANSMIT' mode; * - external SM module; * - 'lock'/'unlock' handlers to allow SM transfer in the locked card session. */ typedef struct sm_context { char config_section[64]; unsigned sm_mode, sm_flags; struct sm_info info; struct sm_card_operations ops; struct sm_module module; unsigned long (*app_lock)(void); void (*app_unlock)(void); } sm_context_t; int sc_sm_parse_answer(struct sc_card *, unsigned char *, size_t, struct sm_card_response *); int sc_sm_update_apdu_response(struct sc_card *, unsigned char *, size_t, int, struct sc_apdu *); int sc_sm_single_transmit(struct sc_card *, struct sc_apdu *); /** * @brief Stops SM and frees allocated resources. * * Calls \a card->sm_ctx.ops.close() if available and \c card->sm_ctx.sm_mode * is \c SM_MODE_TRANSMIT * * @param[in] card card * * @return \c SC_SUCCESS or error code if an error occurred */ int sc_sm_stop(struct sc_card *card); #ifdef __cplusplus } #endif #endif