From 3ea5bb7987601f0cbf42aeb30176af7d318b0ac0 Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 13 Nov 2009 09:45:21 +0000 Subject: [PATCH] Merge [3804:3822/trunk] git-svn-id: https://www.opensc-project.org/svnp/opensc/branches/martin/0.12@3824 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/card-oberthur.c | 584 ++++++++++++++----------------- src/libopensc/card-rutoken.c | 9 +- src/libopensc/libopensc.exports | 2 + src/libopensc/opensc.h | 6 + src/libopensc/pkcs15-pubkey.c | 170 ++++++++- src/libopensc/pkcs15-syn.c | 2 +- src/libopensc/pkcs15.c | 4 +- src/libopensc/pkcs15.h | 43 ++- src/pkcs11/framework-pkcs15.c | 23 +- src/pkcs15init/oberthur.profile | 5 +- src/pkcs15init/pkcs15-init.h | 4 + src/pkcs15init/pkcs15-lib.c | 147 +++++++- src/pkcs15init/pkcs15-oberthur.c | 388 +++++++++++++------- src/pkcs15init/pkcs15.profile | 8 +- src/pkcs15init/profile.c | 19 +- src/pkcs15init/profile.h | 3 + src/tools/pkcs15-tool.c | 32 +- 17 files changed, 925 insertions(+), 524 deletions(-) diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index fab3a3b1..be5da48d 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -3,7 +3,7 @@ * CosmopolIC v5; * * Copyright (C) 2001, 2002 Juha Yrjölä - * Copyright (C) 2009 Viktor Tarasov , + * Copyright (C) 2009 Viktor Tarasov , * OpenTrust * * This library is free software; you can redistribute it and/or @@ -36,6 +36,12 @@ #include #include +/* #define OBERTHUR_VERIFY_SOPIN_TRY_LOCAL */ + +#define OBERTHUR_PIN_LOCAL 0x80 +#define OBERTHUR_PIN_REFERENCE_USER 0x01 +#define OBERTHUR_PIN_REFERENCE_SO 0x04 + /* keep OpenSSL 0.9.6 users happy ;-) */ #if OPENSSL_VERSION_NUMBER < 0x00907000L #define DES_cblock des_cblock @@ -63,18 +69,16 @@ struct auth_senv { int key_file_id; size_t key_size; }; -typedef struct auth_senv auth_senv_t; struct auth_private_data { unsigned char aid[SC_MAX_AID_SIZE]; int aid_len; struct sc_pin_cmd_pin pin_info; - auth_senv_t senv; + struct auth_senv senv; long int sn; }; -typedef struct auth_private_data auth_private_data_t; struct auth_update_component_info { enum SC_CARDCTL_OBERTHUR_KEY_TYPE type; @@ -82,11 +86,10 @@ struct auth_update_component_info { unsigned char *data; unsigned int len; }; -typedef struct auth_update_component_info auth_update_component_info_t; static const unsigned char *aidAuthentIC_V5 = - (const u8 *)"\xA0\x00\x00\x00\x77\x01\x03\x03\x00\x00\x00\xF1\x00\x00\x00\x02"; + (const unsigned char *)"\xA0\x00\x00\x00\x77\x01\x03\x03\x00\x00\x00\xF1\x00\x00\x00\x02"; static const int lenAidAuthentIC_V5 = 16; static const char *nameAidAuthentIC_V5 = "AuthentIC v5"; @@ -102,7 +105,7 @@ static const char *nameAidAuthentIC_V5 = "AuthentIC v5"; static unsigned char rsa_der[PUBKEY_2048_ASN1_SIZE]; static int rsa_der_len = 0; -static sc_file_t *auth_current_ef = NULL, *auth_current_df = NULL; +static struct sc_file *auth_current_ef = NULL, *auth_current_df = NULL; static struct sc_card_operations auth_ops; static struct sc_card_operations *iso_ops; static struct sc_card_driver auth_drv = { @@ -112,22 +115,24 @@ static struct sc_card_driver auth_drv = { NULL, 0, NULL }; -static int auth_get_pin_reference (sc_card_t *card, +static int auth_get_pin_reference (struct sc_card *card, int type, int reference, int cmd, int *out_ref); -static int auth_read_component(sc_card_t *card, +static int auth_read_component(struct sc_card *card, enum SC_CARDCTL_OBERTHUR_KEY_TYPE type, int num, unsigned char *out, size_t outlen); -static int auth_verify(sc_card_t *card, unsigned int type, - int ref, const u8 *data, size_t data_len, int *tries_left); -static int auth_create_reference_data (sc_card_t *card, +static int auth_is_verified(struct sc_card *card, int pin_reference, + int *tries_left); +static int auth_verify(struct sc_card *card, unsigned int type, + struct sc_pin_cmd_data *data, int *tries_left); +static int auth_create_reference_data (struct sc_card *card, struct sc_cardctl_oberthur_createpin_info *args); -static int auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial); -static int auth_select_file(sc_card_t *card, const sc_path_t *in_path, - sc_file_t **file_out); +static int auth_get_serialnr(struct sc_card *card, struct sc_serial_number *serial); +static int auth_select_file(struct sc_card *card, const struct sc_path *in_path, + struct sc_file **file_out); static int -auth_finish(sc_card_t *card) +auth_finish(struct sc_card *card) { free(card->drv_data); return SC_SUCCESS; @@ -135,20 +140,19 @@ auth_finish(sc_card_t *card) static int -auth_select_aid(sc_card_t *card) +auth_select_aid(struct sc_card *card) { - sc_apdu_t apdu; + struct sc_apdu apdu; unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE]; struct auth_private_data *data = (struct auth_private_data *) card->drv_data; int rv, ii; unsigned char cm[7] = {0xA0,0x00,0x00,0x00,0x03,0x00,0x00}; - sc_path_t tmp_path; + struct sc_path tmp_path; /* Select Card Manager (to deselect previously selected application) */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C); apdu.lc = sizeof(cm); /* apdu.le = sizeof(cm)+4; */ - apdu.le = 0; apdu.data = cm; apdu.datalen = sizeof(cm); apdu.resplen = sizeof(apdu_resp); @@ -198,8 +202,9 @@ auth_select_aid(sc_card_t *card) SC_FUNC_RETURN(card->ctx, 1, rv); } + static int -auth_match_card(sc_card_t *card) +auth_match_card(struct sc_card *card) { if (_sc_match_atr(card, oberthur_atrs, &card->type) < 0) return 0; @@ -207,19 +212,18 @@ auth_match_card(sc_card_t *card) return 1; } + static int -auth_init(sc_card_t *card) +auth_init(struct sc_card *card) { - int rv = 0; - unsigned long flags; struct auth_private_data *data; - sc_path_t path; + struct sc_path path; + unsigned long flags; + int rv = 0; - data = (struct auth_private_data *) malloc(sizeof(struct auth_private_data)); + data = (struct auth_private_data *) calloc(1, sizeof(struct auth_private_data)); if (!data) SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY); - else - memset(data, 0, sizeof(struct auth_private_data)); card->cla = 0x00; card->drv_data = data; @@ -262,8 +266,8 @@ auth_init(sc_card_t *card) static void -add_acl_entry(sc_card_t *card, sc_file_t *file, unsigned int op, - u8 acl_byte) +add_acl_entry(struct sc_card *card, struct sc_file *file, unsigned int op, + unsigned char acl_byte) { if ((acl_byte & 0xE0) == 0x60) { sc_debug(card->ctx, "called; op 0x%X; SC_AC_PRO; ref 0x%X\n", op, acl_byte); @@ -293,8 +297,7 @@ add_acl_entry(sc_card_t *card, sc_file_t *file, unsigned int op, static int -tlv_get(const unsigned char *msg, int len, - unsigned char tag, +tlv_get(const unsigned char *msg, int len, unsigned char tag, unsigned char *ret, int *ret_len) { int cur = 0; @@ -409,6 +412,9 @@ auth_process_fci(struct sc_card *card, struct sc_file *file, add_acl_entry(card, file, SC_AC_OP_CRYPTO, attr[1]); add_acl_entry(card, file, SC_AC_OP_LIST_FILES, attr[2]); add_acl_entry(card, file, SC_AC_OP_DELETE, attr[3]); + add_acl_entry(card, file, SC_AC_OP_PIN_DEFINE, attr[4]); + add_acl_entry(card, file, SC_AC_OP_PIN_CHANGE, attr[5]); + add_acl_entry(card, file, SC_AC_OP_PIN_RESET, attr[6]); } else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { /* EF */ switch (file->ef_structure) { @@ -451,18 +457,18 @@ auth_process_fci(struct sc_card *card, struct sc_file *file, static int -auth_select_file(sc_card_t *card, const sc_path_t *in_path, - sc_file_t **file_out) +auth_select_file(struct sc_card *card, const struct sc_path *in_path, + struct sc_file **file_out) { - int rv; + struct sc_path path; + struct sc_file *tmp_file = NULL; size_t offs, ii; - sc_path_t path; - sc_file_t *tmp_file = NULL; + int rv; SC_FUNC_CALLED(card->ctx, 1); assert(card != NULL && in_path != NULL); - memcpy(&path, in_path, sizeof(sc_path_t)); + memcpy(&path, in_path, sizeof(struct sc_path)); sc_debug(card->ctx, "in_path; type=%d, path=%s, out %p\n", in_path->type, sc_print_path(in_path), file_out); @@ -481,7 +487,7 @@ auth_select_file(sc_card_t *card, const sc_path_t *in_path, SC_TEST_RET(card->ctx, rv, "select file failed"); if (path.type == SC_PATH_TYPE_PARENT) { - memcpy(&tmp_file->path, &auth_current_df->path, sizeof(sc_path_t)); + memcpy(&tmp_file->path, &auth_current_df->path, sizeof(struct sc_path)); if (tmp_file->path.len > 2) tmp_file->path.len -= 2; @@ -529,9 +535,9 @@ auth_select_file(sc_card_t *card, const sc_path_t *in_path, sc_debug(card->ctx, "deep %i\n", deep); for (ii=0; iipath, sizeof(sc_path_t)); + memcpy(&tmp_path, &auth_current_df->path, sizeof(struct sc_path)); tmp_path.type = SC_PATH_TYPE_PARENT; rv = auth_select_file (card, &tmp_path, file_out); @@ -540,7 +546,7 @@ auth_select_file(sc_card_t *card, const sc_path_t *in_path, } if (path.len - offs > 0) { - sc_path_t tmp_path; + struct sc_path tmp_path; tmp_path.type = SC_PATH_TYPE_FILE_ID; tmp_path.len = 2; @@ -567,10 +573,10 @@ auth_select_file(sc_card_t *card, const sc_path_t *in_path, static int -auth_list_files(sc_card_t *card, u8 *buf, size_t buflen) +auth_list_files(struct sc_card *card, unsigned char *buf, size_t buflen) { - sc_apdu_t apdu; - u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + struct sc_apdu apdu; + unsigned char rbuf[SC_MAX_APDU_BUFFER_SIZE]; int rv; SC_FUNC_CALLED(card->ctx, 1); @@ -597,11 +603,11 @@ auth_list_files(sc_card_t *card, u8 *buf, size_t buflen) static int -auth_delete_file(sc_card_t *card, const sc_path_t *path) +auth_delete_file(struct sc_card *card, const struct sc_path *path) { + struct sc_apdu apdu; + unsigned char sbuf[2]; int rv; - u8 sbuf[2]; - sc_apdu_t apdu; SC_FUNC_CALLED(card->ctx, 1); if (card->ctx->debug >= 1) { @@ -620,7 +626,7 @@ auth_delete_file(sc_card_t *card, const sc_path_t *path) } if (path->len > 2) { - sc_path_t parent = *path; + struct sc_path parent = *path; parent.len -= 2; parent.type = SC_PATH_TYPE_PATH; @@ -643,10 +649,10 @@ auth_delete_file(sc_card_t *card, const sc_path_t *path) rv = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); if (apdu.sw1==0x6A && apdu.sw2==0x82) { - /* Clean the DF contents.*/ - sc_path_t tmp_path; - u8 lbuf[SC_MAX_APDU_BUFFER_SIZE]; + /* Clean up tDF contents.*/ + struct sc_path tmp_path; int ii, len; + unsigned char lbuf[SC_MAX_APDU_BUFFER_SIZE]; tmp_path.type = SC_PATH_TYPE_FILE_ID; memcpy(tmp_path.value, sbuf, 2); @@ -658,7 +664,7 @@ auth_delete_file(sc_card_t *card, const sc_path_t *path) SC_TEST_RET(card->ctx, len, "list DF failed"); for (ii=0; iictx, 1); @@ -833,9 +839,9 @@ encode_file_structure_V5(sc_card_t *card, const sc_file_t *file, ops[1] = SC_AC_OP_CRYPTO; ops[2] = SC_AC_OP_LIST_FILES; ops[3] = SC_AC_OP_DELETE; - ops[4] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_SET_REFERENCE */ - ops[5] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_CHANGE_REFERENCE */ - ops[6] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_RESET_COUNTER */ + ops[4] = SC_AC_OP_PIN_DEFINE; + ops[5] = SC_AC_OP_PIN_CHANGE; + ops[6] = SC_AC_OP_PIN_RESET; } else if (file->type == SC_FILE_TYPE_WORKING_EF) { if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { @@ -877,7 +883,7 @@ encode_file_structure_V5(sc_card_t *card, const sc_file_t *file, } for (ii = 0; ii < sizeof(ops); ii++) { - const sc_acl_entry_t *entry; + const struct sc_acl_entry *entry; p[16+ii] = 0xFF; if (ops[ii]==0xFF) @@ -895,13 +901,13 @@ encode_file_structure_V5(sc_card_t *card, const sc_file_t *file, static int -auth_create_file(sc_card_t *card, sc_file_t *file) +auth_create_file(struct sc_card *card, struct sc_file *file) { - u8 sbuf[0x18]; - size_t sendlen = sizeof(sbuf); + struct sc_apdu apdu; + struct sc_path path; int rv, rec_nr; - sc_apdu_t apdu; - sc_path_t path; + unsigned char sbuf[0x18]; + size_t sendlen = sizeof(sbuf); char pbuf[SC_MAX_PATH_STRING_SIZE]; SC_FUNC_CALLED(card->ctx, 1); @@ -955,8 +961,8 @@ auth_create_file(sc_card_t *card, sc_file_t *file) /* select created DF. */ if (file->type == SC_FILE_TYPE_DF) { - sc_path_t tmp_path; - sc_file_t *df_file = NULL; + struct sc_path tmp_path; + struct sc_file *df_file = NULL; tmp_path.type = SC_PATH_TYPE_FILE_ID; tmp_path.value[0] = file->id >> 8; @@ -974,30 +980,30 @@ auth_create_file(sc_card_t *card, sc_file_t *file) SC_FUNC_RETURN(card->ctx, 1, rv); } + static int -auth_set_security_env(sc_card_t *card, - const sc_security_env_t *env, int se_num) +auth_set_security_env(struct sc_card *card, + const struct sc_security_env *env, int se_num) { - auth_senv_t *auth_senv = &((struct auth_private_data *) card->drv_data)->senv; + struct auth_senv *auth_senv = &((struct auth_private_data *) card->drv_data)->senv; + struct sc_apdu apdu; long unsigned pads = env->algorithm_flags & SC_ALGORITHM_RSA_PADS; - long unsigned supported_pads = - SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_PAD_ISO9796; - sc_apdu_t apdu; - u8 rsa_sbuf[3] = { + long unsigned supported_pads = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_PAD_ISO9796; + int rv; + unsigned char rsa_sbuf[3] = { 0x80, 0x01, 0xFF }; - u8 des_sbuf[13] = { + unsigned char des_sbuf[13] = { 0x80, 0x01, 0x01, 0x87, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - int rv; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "op %i; path %s; key_ref 0x%X; algos 0x%X; flags 0x%X\n", env->operation, sc_print_path(&env->file_ref), env->key_ref[0], env->algorithm_flags, env->flags); - memset(auth_senv, 0, sizeof(auth_senv_t)); + memset(auth_senv, 0, sizeof(struct auth_senv)); if (!(env->flags & SC_SEC_ENV_FILE_REF_PRESENT)) SC_TEST_RET(card->ctx, SC_ERROR_INTERNAL, "Key file is not selected."); @@ -1069,17 +1075,17 @@ auth_set_security_env(sc_card_t *card, static int -auth_restore_security_env(sc_card_t *card, int se_num) +auth_restore_security_env(struct sc_card *card, int se_num) { return SC_SUCCESS; } static int -auth_compute_signature(sc_card_t *card, - const u8 *in, size_t ilen, u8 * out, size_t olen) +auth_compute_signature(struct sc_card *card, const unsigned char *in, size_t ilen, + unsigned char * out, size_t olen) { - sc_apdu_t apdu; + struct sc_apdu apdu; unsigned char resp[SC_MAX_APDU_BUFFER_SIZE]; int rv; @@ -1119,11 +1125,11 @@ auth_compute_signature(sc_card_t *card, static int -auth_decipher(sc_card_t *card, const u8 *in, size_t inlen, - u8 *out, size_t outlen) +auth_decipher(struct sc_card *card, const unsigned char *in, size_t inlen, + unsigned char *out, size_t outlen) { - sc_apdu_t apdu; - u8 resp[SC_MAX_APDU_BUFFER_SIZE]; + struct sc_apdu apdu; + unsigned char resp[SC_MAX_APDU_BUFFER_SIZE]; int rv, _inlen = inlen; SC_FUNC_CALLED(card->ctx, 1); @@ -1199,16 +1205,14 @@ done: /* Return the default AAK for this type of card */ static int -auth_get_default_key(sc_card_t *card, struct sc_cardctl_default_key *data) +auth_get_default_key(struct sc_card *card, struct sc_cardctl_default_key *data) { - int rv = SC_ERROR_NO_DEFAULT_KEY; - - SC_FUNC_RETURN(card->ctx, 1, rv); + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NO_DEFAULT_KEY); } static int -auth_encode_exponent(unsigned long exponent, u8 *buff, size_t buff_len) +auth_encode_exponent(unsigned long exponent, unsigned char *buff, size_t buff_len) { int shift; size_t ii; @@ -1228,12 +1232,12 @@ auth_encode_exponent(unsigned long exponent, u8 *buff, size_t buff_len) /* Generate key on-card */ static int -auth_generate_key(sc_card_t *card, int use_sm, +auth_generate_key(struct sc_card *card, int use_sm, struct sc_cardctl_oberthur_genkey_info *data) { - sc_apdu_t apdu; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - sc_path_t tmp_path; + struct sc_apdu apdu; + unsigned char sbuf[SC_MAX_APDU_BUFFER_SIZE]; + struct sc_path tmp_path; int rv = 0; SC_FUNC_CALLED(card->ctx, 1); @@ -1255,9 +1259,10 @@ auth_generate_key(sc_card_t *card, int use_sm, } sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x46, 0x00, 0x00); - if (!(apdu.resp = (u8 *) malloc(data->key_bits/8+8))) { + apdu.resp = (unsigned char *) calloc(1, data->key_bits/8+8); + if (!apdu.resp) SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_OUT_OF_MEMORY); - } + apdu.resplen = data->key_bits/8+8; apdu.lc = rv + 4; apdu.le = data->key_bits/8; @@ -1298,11 +1303,11 @@ auth_generate_key(sc_card_t *card, int use_sm, static int -auth_update_component(sc_card_t *card, struct auth_update_component_info *args) +auth_update_component(struct sc_card *card, struct auth_update_component_info *args) { - sc_apdu_t apdu; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE + 0x10]; - u8 ins, p1, p2; + struct sc_apdu apdu; + unsigned char sbuf[SC_MAX_APDU_BUFFER_SIZE + 0x10]; + unsigned char ins, p1, p2; int rv, len; SC_FUNC_CALLED(card->ctx, 1); @@ -1386,7 +1391,7 @@ auth_update_component(sc_card_t *card, struct auth_update_component_info *args) static int -auth_update_key(sc_card_t *card, struct sc_cardctl_oberthur_updatekey_info *info) +auth_update_key(struct sc_card *card, struct sc_cardctl_oberthur_updatekey_info *info) { int rv, ii; @@ -1397,7 +1402,7 @@ auth_update_key(sc_card_t *card, struct sc_cardctl_oberthur_updatekey_info *info if (info->type == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT) { struct sc_pkcs15_prkey_rsa *rsa = (struct sc_pkcs15_prkey_rsa *)info->data; - struct sc_pkcs15_bignum bn[5]; + struct sc_pkcs15_bignum bn[5]; sc_debug(card->ctx, "Import RSA CRT"); bn[0] = rsa->p; @@ -1430,7 +1435,7 @@ auth_update_key(sc_card_t *card, struct sc_cardctl_oberthur_updatekey_info *info static int -auth_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) +auth_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr) { switch (cmd) { case SC_CARDCTL_GET_DEFAULT_KEY: @@ -1446,7 +1451,7 @@ auth_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) return auth_create_reference_data(card, (struct sc_cardctl_oberthur_createpin_info *) ptr); case SC_CARDCTL_GET_SERIALNR: - return auth_get_serialnr(card, (sc_serial_number_t *)ptr); + return auth_get_serialnr(card, (struct sc_serial_number *)ptr); case SC_CARDCTL_LIFECYCLE_GET: case SC_CARDCTL_LIFECYCLE_SET: return SC_ERROR_NOT_SUPPORTED; @@ -1457,11 +1462,11 @@ auth_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) static int -auth_read_component(sc_card_t *card, enum SC_CARDCTL_OBERTHUR_KEY_TYPE type, +auth_read_component(struct sc_card *card, enum SC_CARDCTL_OBERTHUR_KEY_TYPE type, int num, unsigned char *out, size_t outlen) { + struct sc_apdu apdu; int rv; - sc_apdu_t apdu; unsigned char resp[SC_MAX_APDU_BUFFER_SIZE]; SC_FUNC_CALLED(card->ctx, 1); @@ -1489,8 +1494,8 @@ auth_read_component(sc_card_t *card, enum SC_CARDCTL_OBERTHUR_KEY_TYPE type, } -static int auth_get_pin_reference (sc_card_t *card, - int type, int reference, int cmd, int *out_ref) +static int +auth_get_pin_reference (struct sc_card *card, int type, int reference, int cmd, int *out_ref) { struct auth_private_data *prv; @@ -1505,7 +1510,7 @@ static int auth_get_pin_reference (sc_card_t *card, SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_PIN_REFERENCE); *out_ref = reference; - if (reference == 1 || reference == 2) + if (reference == 1 || reference == 4) if (cmd == SC_PIN_CMD_VERIFY) *out_ref |= 0x80; break; @@ -1519,10 +1524,10 @@ static int auth_get_pin_reference (sc_card_t *card, static void -auth_init_pin_info(sc_card_t *card, struct sc_pin_cmd_pin *pin, +auth_init_pin_info(struct sc_card *card, struct sc_pin_cmd_pin *pin, unsigned int type) { - pin->offset = 0; + pin->offset = 0; pin->pad_char = 0xFF; pin->encoding = SC_PIN_ENCODING_ASCII; @@ -1538,211 +1543,154 @@ auth_init_pin_info(sc_card_t *card, struct sc_pin_cmd_pin *pin, static int -auth_verify(sc_card_t *card, unsigned int type, - int ref, const u8 *data, size_t data_len, int *tries_left) +auth_verify(struct sc_card *card, unsigned int type, + struct sc_pin_cmd_data *data, int *tries_left) { - sc_apdu_t apdu; - int rv, pin_ref; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - struct sc_pin_cmd_pin pinfo; + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + int rv; SC_FUNC_CALLED(card->ctx, 1); - sc_debug(card->ctx,"type %i; ref %i, data_len %i\n", type, ref, data_len); - if (ref == 3) { - ref = 1; - rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_VERIFY, &pin_ref); - SC_TEST_RET(card->ctx, rv, "Get PIN reference failed"); + if (type != SC_AC_CHV) + SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "PIN type other then SC_AC_CHV is not supported"); - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, pin_ref); - apdu.lc = 0x0; - apdu.le = 0x0; - apdu.resplen = 0; - apdu.resp = NULL; - apdu.p2 = pin_ref; - rv = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); - - if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) { - ref = 2; - rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_VERIFY, &pin_ref); - if (rv) - SC_FUNC_RETURN(card->ctx, 1, rv); - - apdu.p2 = pin_ref; - rv = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); - } - - rv = sc_check_sw(card, apdu.sw1, apdu.sw2); - if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 ) { - if (data && data_len > 1 && *data!=ref && !isalnum(*data)) { - rv = auth_verify(card, type, *data, - data+1, data_len - 1, tries_left); - } - } - + data->flags |= SC_PIN_CMD_NEED_PADDING; + + auth_init_pin_info(card, &data->pin1, AUTH_PIN); + + /* User PIN is always local. */ + if (data->pin_reference == OBERTHUR_PIN_REFERENCE_USER) + data->pin_reference |= OBERTHUR_PIN_LOCAL; + +#ifdef OBERTHUR_VERIFY_SOPIN_TRY_LOCAL + /* SOPIN can be local -- firstly try to verify the local one. */ + if (data->pin_reference == OBERTHUR_PIN_REFERENCE_SO) + data->pin_reference |= OBERTHUR_PIN_LOCAL; +#endif + + rv = auth_is_verified(card, data->pin_reference, tries_left); + sc_debug(card->ctx, "auth_is_verified returned rv %i\n", rv); + +#ifdef OBERTHUR_VERIFY_SOPIN_TRY_LOCAL + if (rv == SC_ERROR_DATA_OBJECT_NOT_FOUND + && data->pin_reference == OBERTHUR_PIN_REFERENCE_SO | OBERTHUR_PIN_LOCAL) { + /* Local SOPIN is not defined -- try to verify the global one. */ + data->pin_reference &= ~OBERTHUR_PIN_LOCAL; + rv = auth_is_verified(card, data->pin_reference, tries_left); + } +#endif + + /* Return if only PIN status has been asked. */ + if (data->pin1.data && !data->pin1.len) SC_FUNC_RETURN(card->ctx, 1, rv); - } - rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_VERIFY, &pin_ref); - SC_TEST_RET(card->ctx, rv, "Get PIN reference failed"); - - sc_debug(card->ctx, " pin_ref %X\n", pin_ref); + /* Return SUCCESS without verifying if + * PIN has been already verified and PIN pad has to be used. */ + if (!rv && !data->pin1.data && !data->pin1.len) + SC_FUNC_RETURN(card->ctx, 1, rv); - auth_init_pin_info(card, &pinfo, AUTH_PIN); - if (data_len > pinfo.pad_length) - SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); + rv = iso_drv->ops->pin_cmd(card, data, tries_left); + SC_TEST_RET(card->ctx, rv, "PIN CMD 'VERIFY' failed"); - if (data_len) { - memset(sbuf, pinfo.pad_char, pinfo.pad_length); - memcpy(sbuf, data, data_len); - - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0, pin_ref); - apdu.data = sbuf; - apdu.datalen = pinfo.pad_length; - apdu.lc = pinfo.pad_length; - } - else { - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0, pin_ref); - apdu.lc = 0x0; - apdu.le = 0x0; - apdu.resplen = 0; - apdu.resp = NULL; - } - - rv = sc_transmit_apdu(card, &apdu); - sc_mem_clear(sbuf, sizeof(sbuf)); - SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); - - if (tries_left && apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) - *tries_left = apdu.sw2 & 0x0F; - - rv = sc_check_sw(card, apdu.sw1, apdu.sw2); - SC_FUNC_RETURN(card->ctx, 1, rv); } -static int -auth_change_reference_data (sc_card_t *card, unsigned int type, - int ref, const u8 *old, size_t oldlen, - const u8 *_new, size_t newlen, int *tries_left) +static int +auth_is_verified(struct sc_card *card, int pin_reference, int *tries_left) { - sc_apdu_t apdu; - int rv, pin_ref; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - struct sc_pin_cmd_pin pinfo; - - SC_FUNC_CALLED(card->ctx, 1); - rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_CHANGE, &pin_ref); - SC_TEST_RET(card->ctx, rv, "Failed to get PIN reference"); - - sc_debug(card->ctx, " pin ref %X\n", pin_ref); - - auth_init_pin_info(card, &pinfo, AUTH_PIN); - - if (oldlen > pinfo.pad_length || newlen > pinfo.pad_length) - SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid PIN length"); - - memset(sbuf, pinfo.pad_char, pinfo.pad_length * 2); - memcpy(sbuf, old, oldlen); - memcpy(sbuf + pinfo.pad_length, _new, newlen); - - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0, pin_ref); - apdu.data = sbuf; - apdu.datalen = pinfo.pad_length * 2; - apdu.lc = pinfo.pad_length * 2; + struct sc_apdu apdu; + int rv; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0, pin_reference); rv = sc_transmit_apdu(card, &apdu); - sc_mem_clear(sbuf, sizeof(sbuf)); SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); - if (tries_left && apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) + if (tries_left && apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) *tries_left = apdu.sw2 & 0x0F; - rv = sc_check_sw(card, apdu.sw1, apdu.sw2); - - SC_FUNC_RETURN(card->ctx, 1, rv); -} - - -static int -auth_reset_retry_counter(sc_card_t *card, unsigned int type, - int ref, const u8 *puk, size_t puklen, - const u8 *pin, size_t pinlen) -{ - sc_apdu_t apdu; - int rv, pin_ref; - size_t len; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - struct sc_pin_cmd_pin pin_info, puk_info; - - SC_FUNC_CALLED(card->ctx, 1); - rv = auth_get_pin_reference (card, type, ref, SC_PIN_CMD_CHANGE, &pin_ref); - SC_TEST_RET(card->ctx, rv, "Failed to get PIN reference"); - - sc_debug(card->ctx, "pin_ref 0x%X\n", pin_ref); - sc_debug(card->ctx, "current path ; type=%d, path=%s\n", - auth_current_df->path.type, sc_print_path(&auth_current_df->path)); - - auth_init_pin_info(card, &puk_info, AUTH_PUK); - auth_init_pin_info(card, &pin_info, AUTH_PIN); - - if (puklen > puk_info.pad_length || pinlen > pin_info.pad_length) - SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); - - memset(sbuf, puk_info.pad_char, puk_info.pad_length); - memcpy(sbuf, puk, puklen); - len = puk_info.pad_length; - if (pin && pinlen) { - memset(sbuf + len, pin_info.pad_char, pin_info.pad_length); - memcpy(sbuf + len, pin, pinlen); - len += pin_info.pad_length; + /* Replace 'no tries left' with 'auth method blocked' */ + if (apdu.sw1 == 0x63 && apdu.sw2 == 0xC0) { + apdu.sw1 = 0x69; + apdu.sw2 = 0x83; } - - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2C, - len == puk_info.pad_length ? 1 : 0, pin_ref); - apdu.data = sbuf; - apdu.datalen = len; - apdu.lc = len; - - rv = sc_transmit_apdu(card, &apdu); - sc_mem_clear(sbuf, sizeof(sbuf)); - SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); rv = sc_check_sw(card, apdu.sw1, apdu.sw2); + + return rv; +} + + +static int +auth_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left) +{ + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + struct auth_private_data *prv_data = (struct auth_private_data *) card->drv_data; + struct sc_apdu apdu; + int rv, _tries_left = 0; + + SC_FUNC_CALLED(card->ctx, 1); + if (data->pin_type != SC_AC_CHV) + SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "auth_pin_cmd() unsupported PIN type"); + + sc_debug(card->ctx, "PIN:%i; lengths %i/%i\n", data->pin_reference, data->pin1.len, data->pin2.len); + switch (data->cmd) { + case SC_PIN_CMD_VERIFY: + rv = auth_verify(card, SC_AC_CHV, data, tries_left); + SC_TEST_RET(card->ctx, rv, "CMD 'PIN VERIFY' failed"); + + break; + case SC_PIN_CMD_CHANGE: + data->flags |= SC_PIN_CMD_NEED_PADDING; + data->apdu = NULL; + + auth_init_pin_info(card, &data->pin1, AUTH_PIN); + auth_init_pin_info(card, &data->pin2, AUTH_PIN); + + rv = iso_drv->ops->pin_cmd(card, data, tries_left); + SC_TEST_RET(card->ctx, rv, "CMD 'PIN CHANGE' failed"); + + break; + case SC_PIN_CMD_UNBLOCK: + data->flags |= SC_PIN_CMD_NEED_PADDING; + data->apdu = NULL; + + auth_init_pin_info(card, &data->pin1, AUTH_PUK); + auth_init_pin_info(card, &data->pin2, AUTH_PIN); + + rv = iso_drv->ops->pin_cmd(card, data, tries_left); + SC_TEST_RET(card->ctx, rv, "CMD 'PIN UNBLOCK' failed"); + + break; + default: + SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported PIN operation"); + } + SC_FUNC_RETURN(card->ctx, 1, rv); } static int -auth_create_reference_data (sc_card_t *card, +auth_create_reference_data (struct sc_card *card, struct sc_cardctl_oberthur_createpin_info *args) { - sc_apdu_t apdu; - int rv, pin_ref, len; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + struct sc_apdu apdu; struct sc_pin_cmd_pin pin_info, puk_info; + int rv, len; + unsigned char sbuf[SC_MAX_APDU_BUFFER_SIZE]; SC_FUNC_CALLED(card->ctx, 1); + sc_debug(card->ctx, "PIN reference %i\n", args->ref); + + if (args->type != SC_AC_CHV) + SC_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported PIN type"); if (args->pin_tries < 1 || !args->pin || !args->pin_len) SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid PIN options"); - - if (args->type == SC_AC_CHV) { - if (args->ref == 1) - pin_ref = 0x01; - else if (args->ref == 2) - pin_ref = 0x02; - else - SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid PIN reference"); - } - else { - SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); - } - - sc_debug(card->ctx, "pin ref %X\n", pin_ref); + + if (args->ref != OBERTHUR_PIN_REFERENCE_USER && args->ref != OBERTHUR_PIN_REFERENCE_SO) + SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid PIN reference"); auth_init_pin_info(card, &puk_info, AUTH_PUK); auth_init_pin_info(card, &pin_info, AUTH_PIN); @@ -1764,7 +1712,7 @@ auth_create_reference_data (sc_card_t *card, len += args->puk_len; } - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 1, pin_ref); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 1, args->ref); apdu.data = sbuf; apdu.datalen = len; apdu.lc = len; @@ -1780,9 +1728,9 @@ auth_create_reference_data (sc_card_t *card, static int -auth_logout(sc_card_t *card) +auth_logout(struct sc_card *card) { - sc_apdu_t apdu; + struct sc_apdu apdu; int ii, rv = 0, pin_ref; int reset_flag = 0x20; @@ -1790,12 +1738,8 @@ auth_logout(sc_card_t *card) rv = auth_get_pin_reference (card, SC_AC_CHV, ii+1, SC_PIN_CMD_UNBLOCK, &pin_ref); SC_TEST_RET(card->ctx, rv, "Cannot get PIN reference"); - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2E, 0x00, 0x00); - apdu.cla = 0x80; - apdu.lc = 0x0; - apdu.le = 0x0; - apdu.resplen = 0; - apdu.resp = NULL; + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2E, 0x00, 0x00); + apdu.cla = 0x80; apdu.p2 = pin_ref | reset_flag; rv = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); @@ -1805,14 +1749,15 @@ auth_logout(sc_card_t *card) SC_FUNC_RETURN(card->ctx, 1, rv); } + static int -write_publickey (sc_card_t *card, unsigned int offset, - const u8 *buf, size_t count) +write_publickey (struct sc_card *card, unsigned int offset, + const unsigned char *buf, size_t count) { - int ii, rv; - struct sc_pkcs15_pubkey_rsa key; - size_t len = 0, der_size = 0; struct auth_update_component_info args; + struct sc_pkcs15_pubkey_rsa key; + int ii, rv; + size_t len = 0, der_size = 0; SC_FUNC_CALLED(card->ctx, 1); if (card->ctx->debug >= 5) { @@ -1869,8 +1814,8 @@ write_publickey (sc_card_t *card, unsigned int offset, static int -auth_update_binary(sc_card_t *card, unsigned int offset, - const u8 *buf, size_t count, unsigned long flags) +auth_update_binary(struct sc_card *card, unsigned int offset, + const unsigned char *buf, size_t count, unsigned long flags) { int rv = 0; @@ -1892,8 +1837,7 @@ auth_update_binary(sc_card_t *card, unsigned int offset, memset(&args, 0, sizeof(args)); args.type = SC_CARDCTL_OBERTHUR_KEY_DES; - args.component = 0; - args.data = (u8 *)buf; + args.data = (unsigned char *)buf; args.len = count; rv = auth_update_component(card, &args); } @@ -1906,8 +1850,8 @@ auth_update_binary(sc_card_t *card, unsigned int offset, static int -auth_read_binary(sc_card_t *card, unsigned int offset, - u8 *buf, size_t count, unsigned long flags) +auth_read_binary(struct sc_card *card, unsigned int offset, + unsigned char *buf, size_t count, unsigned long flags) { int rv; @@ -1935,7 +1879,7 @@ auth_read_binary(sc_card_t *card, unsigned int offset, for (jj=0; jjctx, rv, "Cannot read RSA public key component"); - bn[1].data = (u8 *) malloc(rv); + bn[1].data = (unsigned char *) calloc(1, rv); bn[1].len = rv; memcpy(bn[1].data, resp, rv); @@ -1984,18 +1928,17 @@ auth_read_binary(sc_card_t *card, unsigned int offset, static int auth_read_record(struct sc_card *card, unsigned int nr_rec, - u8 *buf, size_t count, - unsigned long flags) + unsigned char *buf, size_t count, unsigned long flags) { - int rv = 0; struct sc_apdu apdu; - u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; + int rv = 0; + unsigned char recvbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_debug(card->ctx, "auth_read_record(): nr_rec %i; count %i\n", nr_rec, count); - sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, nr_rec, 0); - apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; - if (flags & SC_RECORD_BY_REC_NR) + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, nr_rec, 0); + apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; + if (flags & SC_RECORD_BY_REC_NR) apdu.p2 |= 0x04; apdu.le = count; @@ -2016,20 +1959,16 @@ auth_read_record(struct sc_card *card, unsigned int nr_rec, static int -auth_delete_record(sc_card_t *card, unsigned int nr_rec) +auth_delete_record(struct sc_card *card, unsigned int nr_rec) { + struct sc_apdu apdu; int rv = 0; - sc_apdu_t apdu; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "auth_delete_record(): nr_rec %i\n", nr_rec); sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x32, nr_rec, 0x04); apdu.cla = 0x80; - apdu.lc = 0x0; - apdu.le = 0x0; - apdu.resplen = 0; - apdu.resp = NULL; rv = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); @@ -2038,8 +1977,9 @@ auth_delete_record(sc_card_t *card, unsigned int nr_rec) SC_FUNC_RETURN(card->ctx, 1, rv); } + static int -auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +auth_get_serialnr(struct sc_card *card, struct sc_serial_number *serial) { if (!card || !serial) SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS); @@ -2052,6 +1992,7 @@ auth_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); } + static struct sc_card_driver * sc_get_driver(void) { @@ -2076,12 +2017,7 @@ sc_get_driver(void) auth_ops.compute_signature = auth_compute_signature; auth_ops.decipher = auth_decipher; auth_ops.process_fci = auth_process_fci; - - auth_ops.pin_cmd = NULL; - auth_ops.verify = auth_verify; - auth_ops.reset_retry_counter = auth_reset_retry_counter; - auth_ops.change_reference_data = auth_change_reference_data; - + auth_ops.pin_cmd = auth_pin_cmd; auth_ops.logout = auth_logout; return &auth_drv; } diff --git a/src/libopensc/card-rutoken.c b/src/libopensc/card-rutoken.c index af1e8025..1ba0c65c 100644 --- a/src/libopensc/card-rutoken.c +++ b/src/libopensc/card-rutoken.c @@ -97,7 +97,8 @@ static struct sc_card_driver rutoken_drv = { }; static struct sc_atr_table rutoken_atrs[] = { - { "3b:6f:00:ff:00:56:72:75:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL }, + { "3b:6f:00:ff:00:56:72:75:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL }, /* Aktiv Rutoken S */ + { "3b:6f:00:ff:00:56:75:61:54:6f:6b:6e:73:30:20:00:00:90:00", NULL, NULL, SC_CARD_TYPE_GENERIC_BASE, 0, NULL }, /* Aktiv uaToken S */ { NULL, NULL, NULL, 0, 0, NULL } }; @@ -162,7 +163,11 @@ static int rutoken_init(sc_card_t *card) int ret; SC_FUNC_CALLED(card->ctx, 1); - ret = token_init(card, "Rutoken card"); + /* &rutoken_atrs[1] : { uaToken S ATR, NULL ATR } */ + if (_sc_match_atr(card, &rutoken_atrs[1], &card->type) >= 0) + ret = token_init(card, "uaToken S card"); + else + ret = token_init(card, "Rutoken S card"); SC_FUNC_RETURN(card->ctx, 1, ret); } diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index af3d7ade..405859d0 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -164,6 +164,8 @@ sc_pkcs15_read_data_object sc_pkcs15_read_file sc_pkcs15_read_prkey sc_pkcs15_read_pubkey +sc_pkcs15_pubkey_from_prvkey +sc_pkcs15_pubkey_from_cert sc_pkcs15_remove_df sc_pkcs15_remove_object sc_pkcs15_remove_unusedspace diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 39898914..6c099b68 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -111,6 +111,12 @@ extern "C" { #define SC_AC_OP_WRITE 3 /* rehab and invalidate are the same as in DF case */ +/* Special 'Oberthur IdOne AuthentIC's case: + * re-use the existing DF ACLs that are not relevant to this card. */ +#define SC_AC_OP_PIN_DEFINE SC_AC_OP_LOCK +#define SC_AC_OP_PIN_CHANGE SC_AC_OP_REHABILITATE +#define SC_AC_OP_PIN_RESET SC_AC_OP_DELETE_SELF + /* various maximum values */ #define SC_MAX_READER_DRIVERS 6 #define SC_MAX_READERS 16 diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 507fa546..8fd1f2ad 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -26,6 +26,12 @@ #include #include +#ifdef ENABLE_OPENSSL +#include +#include +#endif + + static const struct sc_asn1_entry c_asn1_com_key_attr[] = { { "iD", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL }, { "usage", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, @@ -36,7 +42,7 @@ static const struct sc_asn1_entry c_asn1_com_key_attr[] = { }; static const struct sc_asn1_entry c_asn1_com_pubkey_attr[] = { - /* FIXME */ + /* FIXME */ { NULL, 0, 0, 0, NULL, NULL } }; @@ -63,7 +69,7 @@ static const struct sc_asn1_entry c_asn1_dsa_type_attr[] = { }; static const struct sc_asn1_entry c_asn1_gostr3410key_attr[] = { - { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, + { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "params_r3410", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, { "params_r3411", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "params_28147", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, @@ -556,26 +562,168 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, return 0; } +static int +sc_pkcs15_dup_bignum (struct sc_pkcs15_bignum *dst, struct sc_pkcs15_bignum *src) +{ + assert(dst && src); + + if (src->data && src->len) { + dst->data = calloc(1, src->len); + if (!dst->data) + return SC_ERROR_OUT_OF_MEMORY; + memcpy(dst->data, src->data, src->len); + dst->len = src->len; + } + + return 0; +} + +int +sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, + struct sc_pkcs15_prkey *prvkey, struct sc_pkcs15_pubkey **out) +{ + struct sc_pkcs15_pubkey *pubkey; + int rv = SC_SUCCESS; + + assert(prvkey && out); + + *out = NULL; + pubkey = (struct sc_pkcs15_pubkey *) calloc(1, sizeof(struct sc_pkcs15_pubkey)); + if (!pubkey) + return SC_ERROR_OUT_OF_MEMORY; + + pubkey->algorithm = prvkey->algorithm; + switch (prvkey->algorithm) { + case SC_ALGORITHM_RSA: + rv = sc_pkcs15_dup_bignum(&pubkey->u.rsa.modulus, &prvkey->u.rsa.modulus); + if (!rv) + rv = sc_pkcs15_dup_bignum(&pubkey->u.rsa.exponent, &prvkey->u.rsa.exponent); + break; + case SC_ALGORITHM_DSA: + rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.pub, &prvkey->u.dsa.pub); + if (!rv) + rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.p, &prvkey->u.dsa.p); + if (!rv) + rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.q, &prvkey->u.dsa.q); + if (!rv) + rv = sc_pkcs15_dup_bignum(&pubkey->u.dsa.g, &prvkey->u.dsa.g); + break; + case SC_ALGORITHM_GOSTR3410: + break; + default: + sc_debug(ctx, "Unsupported private key algorithm"); + return SC_ERROR_NOT_SUPPORTED; + } + + if (rv) + sc_pkcs15_free_pubkey(pubkey); + else + *out = pubkey; + + return SC_SUCCESS; +} + + +int +sc_pkcs15_pubkey_from_cert(struct sc_context *ctx, + struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out) +{ +#ifndef ENABLE_OPENSSL + SC_FUNC_RETURN(ctx, 1, SC_ERROR_NOT_SUPPORTED); +#else + EVP_PKEY *pkey = NULL; + X509 *x = NULL; + BIO *mem = NULL; + struct sc_pkcs15_pubkey *pubkey = NULL; + int rv = 0; + + assert(cert_blob && out); + + pubkey = (struct sc_pkcs15_pubkey *) calloc(1, sizeof(struct sc_pkcs15_pubkey)); + if (!pubkey) + SC_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate pubkey"); + + pubkey->algorithm = SC_ALGORITHM_RSA; + do { + rv = SC_ERROR_INVALID_DATA; + mem = BIO_new_mem_buf(cert_blob->value, cert_blob->len); + if (!mem) + break; + + x = d2i_X509_bio(mem, NULL); + if (!x) + break; + + pkey=X509_get_pubkey(x); + if (!pkey || pkey->type != EVP_PKEY_RSA) + break; + + pubkey->u.rsa.modulus.len = BN_num_bytes(pkey->pkey.rsa->n); + pubkey->u.rsa.modulus.data = calloc(1, pubkey->u.rsa.modulus.len); + + pubkey->u.rsa.exponent.len = BN_num_bytes(pkey->pkey.rsa->e); + pubkey->u.rsa.exponent.data = calloc(1, pubkey->u.rsa.exponent.len); + + rv = SC_ERROR_OUT_OF_MEMORY; + if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data) + break; + + BN_bn2bin(pkey->pkey.rsa->n, pubkey->u.rsa.modulus.data); + BN_bn2bin(pkey->pkey.rsa->e, pubkey->u.rsa.exponent.data); + + rv = SC_SUCCESS; + } while (0); + + if (pkey) + EVP_PKEY_free(pkey); + + if (x) + X509_free(x); + + if (mem) + BIO_free(mem); + + if (rv) { + sc_pkcs15_free_pubkey(pubkey); + pubkey = NULL; + } + + *out = pubkey; + + SC_FUNC_RETURN(ctx, 1, rv); +#endif +} + + void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) { assert(key != NULL); switch (key->algorithm) { case SC_ALGORITHM_RSA: - free(key->u.rsa.modulus.data); - free(key->u.rsa.exponent.data); + if (key->u.rsa.modulus.data) + free(key->u.rsa.modulus.data); + if (key->u.rsa.exponent.data) + free(key->u.rsa.exponent.data); break; case SC_ALGORITHM_DSA: - free(key->u.dsa.pub.data); - free(key->u.dsa.g.data); - free(key->u.dsa.p.data); - free(key->u.dsa.q.data); + if (key->u.dsa.pub.data) + free(key->u.dsa.pub.data); + if (key->u.dsa.g.data) + free(key->u.dsa.g.data); + if (key->u.dsa.p.data) + free(key->u.dsa.p.data); + if (key->u.dsa.q.data) + free(key->u.dsa.q.data); break; case SC_ALGORITHM_GOSTR3410: - free(key->u.gostr3410.x.data); - free(key->u.gostr3410.y.data); + if (key->u.gostr3410.x.data) + free(key->u.gostr3410.x.data); + if (key->u.gostr3410.y.data) + free(key->u.gostr3410.y.data); break; } - free(key->data.value); + if (key->data.value) + free(key->data.value); sc_mem_clear(key, sizeof(*key)); } diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 7b5deb32..abca41a1 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -149,7 +149,7 @@ sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card) } } } - if (builtin_enabled) { + else if (builtin_enabled) { sc_debug(ctx, "no emulator list in config file, trying all builtin emulators\n"); for (i = 0; builtin_emulators[i].name; i++) { sc_debug(ctx, "trying %s\n", builtin_emulators[i].name); diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 9188ec8e..b83bae19 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -759,8 +759,8 @@ done: if (strcmp(p15card->card->driver->short_name,"cardos") == 0) { /* D-Trust cards (D-TRUST, D-SIGN) */ - if (strstr(p15card->label,"D-TRUST") == 0 - || strstr(p15card->label,"D-SIGN") == 0) { + if (strstr(p15card->label,"D-TRUST") != NULL + || strstr(p15card->label,"D-SIGN") != NULL) { /* D-TRUST Card 2.0 2cc (standard cards, which always add * SHA1 prefix itself */ diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 1ab2c3a6..ee33065d 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -434,12 +434,14 @@ typedef struct sc_pkcs15_card { char *preferred_language; } sc_pkcs15_card_t; -#define SC_PKCS15_CARD_FLAG_READONLY 0x01 -#define SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED 0x02 -#define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04 -#define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 -#define SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT 0x10 -#define SC_PKCS15_CARD_FLAG_EMULATED 0x20 +#define SC_PKCS15_CARD_FLAG_READONLY 0x01 +#define SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED 0x02 +#define SC_PKCS15_CARD_FLAG_PRN_GENERATION 0x04 +#define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 +#define SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT 0x10 +#define SC_PKCS15_CARD_FLAG_EMULATED 0x20 +#define SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED 0x40 +#define SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED 0x80 /* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object * and initializes a new PKCS #15 card object. Will return @@ -475,16 +477,16 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, unsigned long alg_flags, const u8 *in, size_t inlen, u8 *out, size_t outlen); -int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *card, - const struct sc_pkcs15_object *obj, - struct sc_pkcs15_pubkey **out); -int sc_pkcs15_decode_pubkey_rsa(struct sc_context *ctx, - struct sc_pkcs15_pubkey_rsa *pubkey, +int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, + struct sc_pkcs15_pubkey **); +int sc_pkcs15_decode_pubkey_rsa(struct sc_context *, + struct sc_pkcs15_pubkey_rsa *, const u8 *, size_t); int sc_pkcs15_encode_pubkey_rsa(struct sc_context *, struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *); -int sc_pkcs15_decode_pubkey_dsa(struct sc_context *ctx, - struct sc_pkcs15_pubkey_dsa *pubkey, +int sc_pkcs15_decode_pubkey_dsa(struct sc_context *, + struct sc_pkcs15_pubkey_dsa *, const u8 *, size_t); int sc_pkcs15_encode_pubkey_dsa(struct sc_context *, struct sc_pkcs15_pubkey_dsa *, u8 **, size_t *); @@ -492,13 +494,16 @@ int sc_pkcs15_decode_pubkey(struct sc_context *, struct sc_pkcs15_pubkey *, const u8 *, size_t); int sc_pkcs15_encode_pubkey(struct sc_context *, struct sc_pkcs15_pubkey *, u8 **, size_t *); -void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *pubkey); -void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *pubkey); - -int sc_pkcs15_read_prkey(struct sc_pkcs15_card *card, - const struct sc_pkcs15_object *obj, +void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *); +void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *); +int sc_pkcs15_pubkey_from_prvkey(struct sc_context *, struct sc_pkcs15_prkey *, + struct sc_pkcs15_pubkey **); +int sc_pkcs15_pubkey_from_cert(struct sc_context *, struct sc_pkcs15_der *, + struct sc_pkcs15_pubkey **); +int sc_pkcs15_read_prkey(struct sc_pkcs15_card *, + const struct sc_pkcs15_object *, const char *passphrase, - struct sc_pkcs15_prkey **out); + struct sc_pkcs15_prkey **); int sc_pkcs15_decode_prkey(struct sc_context *, struct sc_pkcs15_prkey *, const u8 *, size_t); diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index cf47e19e..48b3dc77 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1735,12 +1735,23 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card, goto kpgen_done; } - /* Write the new public and private keys to the pkcs15 files */ - rc = sc_pkcs15init_store_private_key(p15card, profile, - &keygen_args.prkey_args, &priv_key_obj); - if (rc >= 0) - rc = sc_pkcs15init_store_public_key(p15card, profile, - &pub_args, &pub_key_obj); + /* Write the new public and private keys to the pkcs15 files */ + /* To support smartcards that require different keybobjects for signing and encryption */ + if (sc_pkcs15init_requires_restrictive_usage(p15card, &keygen_args.prkey_args, 0)) { + sc_debug(context, "store split key required for this card", rv); + /* second key is the signature keyobject */ + rc = sc_pkcs15init_store_split_key(p15card, profile, &keygen_args.prkey_args, NULL, &priv_key_obj); + } + else { + rc = sc_pkcs15init_store_private_key(p15card, profile, &keygen_args.prkey_args, &priv_key_obj); + } + + if (rc >= 0) { + /* copy ID from private key(s) here to avoid bad link between private and public key */ + memcpy(&pub_args.id.value, &keygen_args.prkey_args.id.value, keygen_args.prkey_args.id.len); + pub_args.id.len = keygen_args.prkey_args.id.len; + rc = sc_pkcs15init_store_public_key(p15card, profile, &pub_args, &pub_key_obj); + } if (rc < 0) { sc_debug(context, "private/public keys not stored: %d\n", rc); rv = sc_to_cryptoki_error(rc, p11card->reader); diff --git a/src/pkcs15init/oberthur.profile b/src/pkcs15init/oberthur.profile index 4a6382ef..074f2d82 100644 --- a/src/pkcs15init/oberthur.profile +++ b/src/pkcs15init/oberthur.profile @@ -53,8 +53,9 @@ filesystem { DF OberthurAWP-AppDF { ACL = *=NONE; - #ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78; - ACL = CREATE=CHV4, CRYPTO=NEVER; + #ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78; + ACL = CREATE=CHV4, CRYPTO=NEVER, PIN-DEFINE=CHV4, PIN-RESET=CHV4; + #ACL = CREATE=CHV4, CRYPTO=NEVER; file-id = 5011; size = 40; diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index f993937d..9b99d2b5 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -175,6 +175,10 @@ struct sc_pkcs15init_operations { }; /* Do not change these or reorder these */ +#define SC_PKCS15INIT_ID_STYLE_NATIVE 0 +#define SC_PKCS15INIT_ID_STYLE_MOZILLA 1 +#define SC_PKCS15INIT_ID_STYLE_RFC2459 2 + #define SC_PKCS15INIT_SO_PIN 0 #define SC_PKCS15INIT_SO_PUK 1 #define SC_PKCS15INIT_USER_PIN 2 diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index de65352e..7cd39a55 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -119,6 +119,8 @@ static int check_key_compatibility(struct sc_pkcs15_card *, static int prkey_fixup(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *); static int prkey_bits(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *); static int prkey_pkcs15_algo(sc_pkcs15_card_t *, sc_pkcs15_prkey_t *); +static int select_intrinsic_id(sc_pkcs15_card_t *, struct sc_profile *, + int, sc_pkcs15_id_t *, void *); static int select_id(sc_pkcs15_card_t *, int, sc_pkcs15_id_t *, int (*)(const sc_pkcs15_object_t *, void *), void *, sc_pkcs15_object_t **); @@ -1220,8 +1222,8 @@ sc_pkcs15init_init_prkdf(sc_pkcs15_card_t *p15card, /* Split key; this ID exists already, don't check for * the pkcs15 object */ } else { - /* Select a Key ID if the user didn't specify one, otherwise - * make sure it's compatible with our intended use */ + /* Select a Key ID if the user didn't specify one, + * otherwise make sure it's compatible with our intended use */ r = select_id(p15card, SC_PKCS15_TYPE_PRKEY, &keyargs->id, can_reuse_prkey_obj, object, res_obj); if (r < 0) @@ -1302,7 +1304,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_pkcs15init_pubkeyargs pubkey_args; struct sc_pkcs15_object *object; struct sc_pkcs15_prkey_info *key_info; - int r; + int r, caller_supplied_id = 0; /* check supported key size */ r = check_key_size(p15card->card, keygen_args->prkey_args.key.algorithm, keybits); @@ -1328,6 +1330,8 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, if ((r = set_so_pin_from_card(p15card, profile)) < 0) return r; + caller_supplied_id = keygen_args->prkey_args.id.len != 0; + /* Set up the PrKDF object */ r = sc_pkcs15init_init_prkdf(p15card, profile, &keygen_args->prkey_args, &keygen_args->prkey_args.key, keybits, &object); @@ -1342,7 +1346,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, #if 0 pubkey_args.auth_id = keygen_args->prkey_args.auth_id; #endif - pubkey_args.label = keygen_args->pubkey_label; + pubkey_args.label = keygen_args->pubkey_label ? keygen_args->pubkey_label : object->label; pubkey_args.usage = keygen_args->prkey_args.usage; pubkey_args.x509_usage = keygen_args->prkey_args.x509_usage; pubkey_args.gost_params = keygen_args->prkey_args.gost_params; @@ -1368,8 +1372,23 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, /* update PrKDF entry */ if (r >= 0) { - r = sc_pkcs15init_add_object(p15card, profile, - SC_PKCS15_PRKDF, object); + if (!caller_supplied_id) { + struct sc_pkcs15_id iid; + + /* Caller not supplied ID, so, + * if intrinsic ID can be calculated -- overwrite the native one */ + memset(&iid, 0, sizeof(iid)); + r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &iid, &pubkey_args.key); + if (r < 0) + return r; + + if (iid.len) { + key_info->id = iid; + pubkey_args.id = iid; + } + } + + r = sc_pkcs15init_add_object(p15card, profile, SC_PKCS15_PRKDF, object); } if (r >= 0) { @@ -1439,6 +1458,11 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, if ((r = set_so_pin_from_card(p15card, profile)) < 0) return r; + /* Select a intrinsic Key ID if user didn't specify one */ + r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PRKEY, &keyargs->id, &keyargs->key); + if (r < 0) + return r; + /* Set up the PrKDF object */ r = sc_pkcs15init_init_prkdf(p15card, profile, keyargs, &key, keybits, &object); if (r < 0) @@ -1649,9 +1673,14 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, keyinfo_gostparams->gost28147 = keyargs->gost_params.gost28147; } - /* Select a Key ID if the user didn't specify one, otherwise - * make sure it's unique */ *res_obj = NULL; + /* Select a intrinsic Key ID if the user didn't specify one */ + r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, &key); + if (r < 0) + return r; + + /* Select a Key ID if the user didn't specify one and there is no intrinsic ID, + * otherwise make sure it's unique */ r = select_id(p15card, SC_PKCS15_TYPE_PUBKEY, &keyargs->id, can_reuse_pubkey_obj, object, res_obj); if (r < 0) @@ -1728,6 +1757,10 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, if ((r = set_so_pin_from_card(p15card, profile)) < 0) return r; + r = select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &args->id, &args->der_encoded); + if (r < 0) + return r; + /* Select an ID if the user didn't specify one, otherwise * make sure it's unique */ if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id, NULL, NULL, NULL)) < 0) @@ -1992,7 +2025,7 @@ static size_t sc_pkcs15init_keybits(sc_pkcs15_bignum_t *bn) if (!bn || !bn->len) return 0; bits = bn->len << 3; - for (mask = 0x80; !(bn->data[0] & mask); mask >>= 1) + for (mask = 0x80; mask && !(bn->data[0] & mask); mask >>= 1) bits--; return bits; } @@ -2247,6 +2280,102 @@ find_df_by_type(struct sc_pkcs15_card *p15card, unsigned int type) return df; } +static int select_intrinsic_id(sc_pkcs15_card_t *p15card, struct sc_profile *profile, + int type, sc_pkcs15_id_t *id, void *data) +{ + struct sc_context *ctx = p15card->card->ctx; + struct sc_pkcs15_pubkey *pubkey = NULL; + unsigned id_style = profile->id_style; + int rv, allocated = 0; + + SC_FUNC_CALLED(ctx, 1); +#ifndef ENABLE_OPENSSL + SC_FUNC_RETURN(ctx, 1, 0); +#else + /* ID already exists */ + if (id->len) + SC_FUNC_RETURN(ctx, 1, 0); + + /* Native ID style is not an intrisic one */ + if (profile->id_style == SC_PKCS15INIT_ID_STYLE_NATIVE) + SC_FUNC_RETURN(ctx, 1, 0); + + /* Get PKCS15 public key */ + switch(type) { + case SC_PKCS15_TYPE_CERT_X509: + rv = sc_pkcs15_pubkey_from_cert(ctx, (struct sc_pkcs15_der *)data, &pubkey); + SC_TEST_RET(ctx, rv, "X509 parse error"); + + allocated = 1; + break; + case SC_PKCS15_TYPE_PRKEY: + rv = sc_pkcs15_pubkey_from_prvkey(ctx, (struct sc_pkcs15_prkey *)data, &pubkey); + SC_TEST_RET(ctx, rv, "Cannot get public key"); + + allocated = 1; + break; + case SC_PKCS15_TYPE_PUBKEY: + pubkey = (struct sc_pkcs15_pubkey *)data; + + allocated = 0; + break; + default: + sc_debug(ctx, "Intrinsic ID is not implemented for the object type 0x%X\n", type); + SC_FUNC_RETURN(ctx, 1, 0); + } + + /* Skip silently if key is not inintialized. */ + if (pubkey->algorithm == SC_ALGORITHM_RSA && !pubkey->u.rsa.modulus.len) + goto done; + else if (pubkey->algorithm == SC_ALGORITHM_DSA && !pubkey->u.dsa.pub.data) + goto done; + else if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 && + (!pubkey->u.gostr3410.x.data || !pubkey->u.gostr3410.y.data)) + goto done; + + /* In Mozilla 'GOST R 34.10' is not yet supported. + * So, switch to the ID recommended by RFC2459 */ + if (pubkey->algorithm == SC_ALGORITHM_GOSTR3410 && id_style == SC_PKCS15INIT_ID_STYLE_MOZILLA) + id_style = SC_PKCS15INIT_ID_STYLE_RFC2459; + + if (id_style == SC_PKCS15INIT_ID_STYLE_MOZILLA) { + if (pubkey->algorithm == SC_ALGORITHM_RSA) + SHA1(pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len, id->value); + else if (pubkey->algorithm == SC_ALGORITHM_DSA) + SHA1(pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len, id->value); + else + goto done; + + id->len = SHA_DIGEST_LENGTH; + } + else if (id_style == SC_PKCS15INIT_ID_STYLE_RFC2459) { + unsigned char *id_data = NULL; + size_t id_data_len = 0; + + rv = sc_pkcs15_encode_pubkey(ctx, pubkey, &id_data, &id_data_len); + SC_TEST_RET(ctx, rv, "Encoding public key error"); + + if (!id_data || !id_data_len) + SC_TEST_RET(ctx, SC_ERROR_INTERNAL, "Encoding public key error"); + + SHA1(id_data, id_data_len, id->value); + id->len = SHA_DIGEST_LENGTH; + + free(id_data); + } + else { + sc_debug(ctx, "Unsupported ID style: %i", profile->id_style); + SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non supported ID style"); + } + +done: + if (allocated) + sc_pkcs15_free_pubkey(pubkey); + + SC_FUNC_RETURN(ctx, 1, id->len); +#endif +} + static int select_id(sc_pkcs15_card_t *p15card, int type, sc_pkcs15_id_t *id, int (*can_reuse)(const sc_pkcs15_object_t *, void *), void *data, sc_pkcs15_object_t **reuse_obj) diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c index 437e96c2..bc45bba5 100644 --- a/src/pkcs15init/pkcs15-oberthur.c +++ b/src/pkcs15init/pkcs15-oberthur.c @@ -47,7 +47,7 @@ #define COSM_TITLE "OberthurAWP" #define TLV_TYPE_V 0 -#define TLV_TYPE_LV 1 +#define TLV_TYPE_LV 1 #define TLV_TYPE_TLV 2 /* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */ @@ -56,19 +56,133 @@ #define COSM_TYPE_PRKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PRKEY_RSA) #define COSM_TYPE_PUBKEY_RSA (SC_DEVICE_SPECIFIC_TYPE | SC_PKCS15_TYPE_PUBKEY_RSA) +#define COSM_TOKEN_FLAG_PRN_GENERATION 0x01 +#define COSM_TOKEN_FLAG_LOGIN_REQUIRED 0x04 +#define COSM_TOKEN_FLAG_USER_PIN_INITIALIZED 0x08 +#define COSM_TOKEN_FLAG_TOKEN_INITIALIZED 0x0400 -static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card, - struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len, - const u8 *puk, size_t puk_len); +static int cosm_create_reference_data(struct sc_profile *, struct sc_card *, + struct sc_pkcs15_pin_info *, + const unsigned char *pin, size_t pin_len, + const unsigned char *puk, size_t puk_len); +static int cosm_update_pin(struct sc_profile *profile, struct sc_card *card, + struct sc_pkcs15_pin_info *info, const unsigned char *pin, size_t pin_len, + const unsigned char *puk, size_t puk_len); -int cosm_delete_file(sc_card_t *card, struct sc_profile *profile, - sc_file_t *df); +int cosm_delete_file(struct sc_card *card, struct sc_profile *profile, + struct sc_file *df); -int cosm_delete_file(sc_card_t *card, struct sc_profile *profile, - sc_file_t *df) + +static int +cosm_write_tokeninfo (struct sc_card *card, struct sc_profile *profile, + char *label, unsigned p15_flags) { - sc_path_t path; - sc_file_t *parent; + struct sc_file *file = NULL; + unsigned mask = SC_PKCS15_CARD_FLAG_PRN_GENERATION + | SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED + | SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED + | SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED; + int rv, sz, flags = 0; + char *buffer = NULL; + + if (!card || !profile) + return SC_ERROR_INVALID_ARGUMENTS; + + SC_FUNC_CALLED(card->ctx, 1); + sc_debug(card->ctx, "cosm_write_tokeninfo() label '%s'; flags 0x%X\n", label, p15_flags); + if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find "COSM_TITLE"-token-info"); + + if (file->size < 16) + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Unsufficient size of the "COSM_TITLE"-token-info file"); + + buffer = calloc(1, file->size); + if (!buffer) + SC_TEST_RET(card->ctx, SC_ERROR_MEMORY_FAILURE, "Allocation error in cosm_write_tokeninfo()"); + + if (label) + strncpy(buffer, label, file->size - 4); + else if (profile->p15_data && profile->p15_data->label) + snprintf(buffer, file->size - 4, profile->p15_data->label); + else if (profile->p15_spec && profile->p15_spec->label) + snprintf(buffer, file->size - 4, profile->p15_spec->label); + else + snprintf(buffer, file->size - 4, "OpenSC-Token"); + + sz = strlen(buffer); + if (sz < file->size - 4) + memset(buffer + sz, ' ', file->size - sz); + + if (p15_flags & SC_PKCS15_CARD_FLAG_PRN_GENERATION) + flags |= COSM_TOKEN_FLAG_PRN_GENERATION; + + if (p15_flags & SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED) + flags |= COSM_TOKEN_FLAG_LOGIN_REQUIRED; + + if (p15_flags & SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED) + flags |= COSM_TOKEN_FLAG_USER_PIN_INITIALIZED; + + if (p15_flags & SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED) + flags |= COSM_TOKEN_FLAG_TOKEN_INITIALIZED; + + sc_debug(card->ctx, "cosm_write_tokeninfo() token label '%s'; oberthur flags 0x%X\n", buffer, flags); + + memset(buffer + file->size - 4, 0, 4); + *(buffer + file->size - 1) = flags & 0xFF; + *(buffer + file->size - 2) = (flags >> 8) & 0xFF; + + rv = sc_pkcs15init_update_file(profile, card, file, buffer, file->size); + if (rv > 0) + rv = 0; + + if (profile->p15_data) + profile->p15_data->flags = (profile->p15_data->flags & ~mask) | p15_flags; + + if (profile->p15_spec) + profile->p15_spec->flags = (profile->p15_spec->flags & ~mask) | p15_flags; + + free(buffer); + SC_FUNC_RETURN(card->ctx, 1, rv); +} + + +static int +cosm_update_pukfile (struct sc_card *card, struct sc_profile *profile, + unsigned char *data, size_t data_len) +{ + struct sc_pkcs15_pin_info profile_puk; + struct sc_file *file = NULL; + int rv, sz, flags = 0; + unsigned char buffer[16]; + + SC_FUNC_CALLED(card->ctx, 1); + if (!data || data_len > 16) + return SC_ERROR_INVALID_ARGUMENTS; + + sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_puk); + if (profile_puk.max_length > 16) + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Invalid PUK settings"); + + if (sc_profile_get_file(profile, COSM_TITLE"-puk-file", &file)) + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find PUKFILE"); + + memset(buffer, profile_puk.pad_char, 16); + memcpy(buffer, data, data_len); + + rv = sc_pkcs15init_update_file(profile, card, file, buffer, sizeof(buffer)); + if (rv > 0) + rv = 0; + + SC_FUNC_RETURN(card->ctx, 1, rv); +} + + +int +cosm_delete_file(struct sc_card *card, struct sc_profile *profile, + struct sc_file *df) +{ + struct sc_path path; + struct sc_file *parent; int rv = 0; SC_FUNC_CALLED(card->ctx, 1); @@ -104,9 +218,10 @@ int cosm_delete_file(sc_card_t *card, struct sc_profile *profile, /* * Erase the card */ -static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card) +static int +cosm_erase_card(struct sc_profile *profile, struct sc_card *card) { - sc_file_t *df = profile->df_info->file, *dir; + struct sc_file *df = profile->df_info->file, *dir; int rv; SC_FUNC_CALLED(card->ctx, 1); @@ -150,6 +265,7 @@ static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card) sc_file_free(dir); } + sc_free_apps(card); done: sc_keycache_forget_key(NULL, -1, -1); @@ -164,14 +280,14 @@ done: * Initialize the Application DF */ static int -cosm_init_app(struct sc_profile *profile, sc_card_t *card, +cosm_init_app(struct sc_profile *profile, struct sc_card *card, struct sc_pkcs15_pin_info *pinfo, - const u8 *pin, size_t pin_len, - const u8 *puk, size_t puk_len) + const unsigned char *pin, size_t pin_len, + const unsigned char *puk, size_t puk_len) { - int rv; + struct sc_file *file = NULL; size_t ii; - sc_file_t *file = NULL; + int rv; static const char *create_dfs[] = { COSM_TITLE"-AppDF", "private-DF", @@ -192,7 +308,7 @@ cosm_init_app(struct sc_profile *profile, sc_card_t *card, }; SC_FUNC_CALLED(card->ctx, 1); - sc_debug(card->ctx, "pin_len %i; puk_len %i\n", pin_len, puk_len); + sc_debug(card->ctx, "cosm_init_app() pin_len %i; puk_len %i\n", pin_len, puk_len); /* Oberthur AWP file system is expected.*/ /* Create private objects DF */ @@ -206,22 +322,43 @@ cosm_init_app(struct sc_profile *profile, sc_card_t *card, sc_debug(card->ctx, "rv %i\n", rv); sc_file_free(file); if (rv && rv!=SC_ERROR_FILE_ALREADY_EXISTS) - SC_TEST_RET(card->ctx, rv, "sc_pkcs15init_create_file() failed"); + SC_TEST_RET(card->ctx, rv, "cosm_init_app() sc_pkcs15init_create_file failed"); } - SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); + rv = cosm_write_tokeninfo(card, profile, NULL, + SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED | SC_PKCS15_CARD_FLAG_PRN_GENERATION); + + if (pin && pin_len) { + /* Create local SOPIN */ + struct sc_pkcs15_pin_info pin_info; + + sc_profile_get_file(profile, COSM_TITLE"-AppDF", &file); + + pin_info.flags = SC_PKCS15_PIN_FLAG_SO_PIN; + pin_info.reference = 4; + memcpy(&pin_info.path, &file->path, sizeof(pin_info.path)); + + sc_file_free(file); + + rv = cosm_create_reference_data(profile, card, &pin_info, pin, pin_len, NULL, 0); + SC_TEST_RET(card->ctx, rv, "cosm_init_app() cosm_update_pin failed"); + } + + SC_FUNC_RETURN(card->ctx, 1, rv); } -static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *card, + +static int +cosm_create_reference_data(struct sc_profile *profile, struct sc_card *card, struct sc_pkcs15_pin_info *pinfo, - const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len ) + const unsigned char *pin, size_t pin_len, + const unsigned char *puk, size_t puk_len ) { - int rv; - int puk_buff_len = 0; - unsigned char *puk_buff = NULL; - sc_pkcs15_pin_info_t profile_pin; - sc_pkcs15_pin_info_t profile_puk; + struct sc_pkcs15_pin_info profile_pin; + struct sc_pkcs15_pin_info profile_puk; struct sc_cardctl_oberthur_createpin_info args; + unsigned char *puk_buff = NULL; + int rv, puk_buff_len = 0; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "pin lens %i/%i\n", pin_len, puk_len); @@ -233,9 +370,14 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car rv = sc_select_file(card, &pinfo->path, NULL); SC_TEST_RET(card->ctx, rv, "Cannot select file"); - sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin); + if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) + sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &profile_pin); + else + sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_pin); + if (profile_pin.max_length > 0x100) - SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INCONSISTENT_PROFILE); + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Invalid (SO)PIN profile settings"); + if (puk) { int ii, jj; @@ -277,7 +419,13 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car args.puk_len = puk_buff_len; args.puk_tries = profile_puk.tries_left; - rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args); + rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args); + SC_TEST_RET(card->ctx, rv, "'CREATE_PIN' card specific command failed"); + + if (puk_buff_len == 16) { + rv = cosm_update_pukfile (card, profile, puk_buff, puk_buff_len); + SC_TEST_RET(card->ctx, rv, "Failed to update pukfile"); + } if (puk_buff) free(puk_buff); @@ -288,46 +436,53 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car /* * Update PIN */ -static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card, - struct sc_pkcs15_pin_info *pinfo, const u8 *pin, size_t pin_len, - const u8 *puk, size_t puk_len ) +static int +cosm_update_pin(struct sc_profile *profile, struct sc_card *card, + struct sc_pkcs15_pin_info *pinfo, const unsigned char *pin, size_t pin_len, + const unsigned char *puk, size_t puk_len ) { - int rv; - int tries_left = -1; + int rv, tries_left = -1; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags); if (pinfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { - sc_debug(card->ctx,"Pin references should be only in the profile" - "and in the card-oberthur.\n"); if (pinfo->reference != 4) - return SC_ERROR_INVALID_PIN_REFERENCE; + SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "cosm_update_pin() invalid SOPIN reference"); rv = sc_change_reference_data(card, SC_AC_CHV, pinfo->reference, puk, puk_len, pin, pin_len, &tries_left); - sc_debug(card->ctx, "return value %X; tries left %i\n", rv, tries_left); - if (tries_left != -1) - sc_debug(card->ctx, "Failed to change reference data for soPin: rv %X", rv); + SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to change SOPIN"); + if (tries_left != -1) + SC_TEST_RET(card->ctx, SC_ERROR_INTERNAL, "cosm_update_pin() failed to change SOPIN"); } else { rv = cosm_create_reference_data(profile, card, pinfo, pin, pin_len, puk, puk_len); + SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to change PIN"); + + rv = cosm_write_tokeninfo(card, profile, NULL, + SC_PKCS15_CARD_FLAG_TOKEN_INITIALIZED + | SC_PKCS15_CARD_FLAG_PRN_GENERATION + | SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED + | SC_PKCS15_CARD_FLAG_USER_PIN_INITIALIZED); + SC_TEST_RET(card->ctx, rv, "cosm_update_pin() failed to update tokeninfo"); } SC_FUNC_RETURN(card->ctx, 1, rv); } + static int -cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card, - sc_pkcs15_pin_info_t *pin_info) +cosm_select_pin_reference(struct sc_profile *profile, struct sc_card *card, + struct sc_pkcs15_pin_info *pin_info) { - sc_file_t *pinfile; + struct sc_file *pinfile; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "ref %i; flags %X\n", pin_info->reference, pin_info->flags); - if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { + if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF"); return SC_ERROR_INCONSISTENT_PROFILE; } @@ -337,37 +492,36 @@ cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card, if (!pin_info->reference) { if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) - pin_info->reference = 4; + pin_info->reference = 4; else - pin_info->reference = 1; + pin_info->reference = 1; } - if (pin_info->reference < 0 || pin_info->reference > 4) + if (pin_info->reference < 0 || pin_info->reference > 4) return SC_ERROR_INVALID_PIN_REFERENCE; SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); } + /* * Store a PIN */ static int -cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df, - sc_pkcs15_object_t *pin_obj, +cosm_create_pin(struct sc_profile *profile, struct sc_card *card, struct sc_file *df, + struct sc_pkcs15_object *pin_obj, const unsigned char *pin, size_t pin_len, const unsigned char *puk, size_t puk_len) { - sc_pkcs15_pin_info_t *pinfo = (sc_pkcs15_pin_info_t *) pin_obj->data; - sc_file_t *pinfile; + struct sc_pkcs15_pin_info *pinfo = (struct sc_pkcs15_pin_info *) pin_obj->data; + struct sc_file *pinfile; int rv = 0, type; SC_FUNC_CALLED(card->ctx, 1); sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags); - if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { - sc_debug(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF"); - return SC_ERROR_INCONSISTENT_PROFILE; - } - + if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) + SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "\""COSM_TITLE"-AppDF\" not defined"); + pinfo->path = pinfile->path; sc_file_free(pinfile); @@ -375,23 +529,20 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df, type = SC_PKCS15INIT_SO_PIN; if (pinfo->reference != 4) - return SC_ERROR_INVALID_ARGUMENTS; + SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid SOPIN reference"); } else { type = SC_PKCS15INIT_USER_PIN; if (pinfo->reference !=1 && pinfo->reference != 2) - return SC_ERROR_INVALID_PIN_REFERENCE; + SC_TEST_RET(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE, "Invalid PIN reference"); } if (pin && pin_len) { - rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len); + rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len); + SC_TEST_RET(card->ctx, rv, "Update PIN failed"); } - else { - sc_debug(card->ctx, "User PIN not updated"); - } - sc_debug(card->ctx, "return %i\n", rv); - + sc_keycache_set_pin_name(&pinfo->path, pinfo->reference, type); pinfo->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL; @@ -403,15 +554,15 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df, * Allocate a file */ static int -cosm_new_file(struct sc_profile *profile, sc_card_t *card, - unsigned int type, unsigned int num, sc_file_t **out) +cosm_new_file(struct sc_profile *profile, struct sc_card *card, + unsigned int type, unsigned int num, struct sc_file **out) { struct sc_file *file; const char *_template = NULL, *desc = NULL; unsigned int structure = 0xFFFFFFFF; SC_FUNC_CALLED(card->ctx, 1); - sc_debug(card->ctx, "type %X; num %i\n",type, num); + sc_debug(card->ctx, "cosm_new_file() type %X; num %i\n",type, num); while (1) { switch (type) { case SC_PKCS15_TYPE_PRKEY_RSA: @@ -457,20 +608,20 @@ cosm_new_file(struct sc_profile *profile, sc_card_t *card, type &= SC_PKCS15_TYPE_CLASS_MASK; } - sc_debug(card->ctx, "template %s; num %i\n",_template, num); + sc_debug(card->ctx, "cosm_new_file() template %s; num %i\n",_template, num); if (sc_profile_get_file(profile, _template, &file) < 0) { sc_debug(card->ctx, "Profile doesn't define %s template '%s'\n", desc, _template); - return SC_ERROR_NOT_SUPPORTED; + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED); } - + file->id |= (num & 0xFF); file->path.value[file->path.len-1] |= (num & 0xFF); if (file->type == SC_FILE_TYPE_INTERNAL_EF) { file->ef_structure = structure; } - sc_debug(card->ctx, "file size %i; ef type %i/%i; id %04X\n",file->size, + sc_debug(card->ctx, "cosm_new_file() file size %i; ef type %i/%i; id %04X\n",file->size, file->type, file->ef_structure, file->id); *out = file; @@ -482,9 +633,9 @@ cosm_new_file(struct sc_profile *profile, sc_card_t *card, * RSA key generation */ static int -cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card, +cosm_old_generate_key(struct sc_profile *profile, struct sc_card *card, unsigned int idx, unsigned int keybits, - sc_pkcs15_pubkey_t *pubkey, + struct sc_pkcs15_pubkey *pubkey, struct sc_pkcs15_prkey_info *info) { struct sc_cardctl_oberthur_genkey_info args; @@ -493,45 +644,37 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card, int rv; SC_FUNC_CALLED(card->ctx, 1); - sc_debug(card->ctx, "index %i; nn %i\n", idx, keybits); + sc_debug(card->ctx, "cosm_generate_key() index %i; nn %i\n", idx, keybits); if (keybits < 512 || keybits > 2048 || (keybits%0x20)) { sc_debug(card->ctx, "Unsupported key size %u\n", keybits); - return SC_ERROR_INVALID_ARGUMENTS; + SC_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); } /* Get private key file from profile. */ - if ((rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, - &prkf)) < 0) - goto failed; - sc_debug(card->ctx, "prv ef type 0x%X\n",prkf->ef_structure); + rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, &prkf); + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() cannot allocate new file SC_PKCS15_TYPE_PRKEY_RSA"); prkf->size = keybits; /* Access condition of private object DF. */ path = prkf->path; path.len -= 2; - rv = sc_select_file(card, &path, &tmpf); - SC_TEST_RET(card->ctx, rv, "Generate RSA: no private object DF"); + rv = sc_select_file(card, &path, &tmpf); + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() no private object DF"); rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO); - sc_debug(card->ctx, "rv %i\n",rv); - if (rv < 0) - goto failed; + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CRYPTO) failed"); rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CREATE); - sc_debug(card->ctx, "rv %i\n",rv); - if (rv < 0) - goto failed; + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() pkcs15init_authenticate(SC_AC_OP_CREATE) failed"); sc_file_free(tmpf); /* In the private key DF create the temporary public RSA file. */ - sc_debug(card->ctx, "ready to create public key\n"); + sc_debug(card->ctx, "cosm_generate_key() ready to create temporary public key\n"); sc_file_dup(&tmpf, prkf); - if (tmpf == NULL) { - rv = SC_ERROR_OUT_OF_MEMORY; - goto failed; - } + if (!tmpf) + SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot duplicate private key file"); tmpf->type = SC_FILE_TYPE_INTERNAL_EF; tmpf->ef_structure = SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC; tmpf->id = 0x1012; @@ -539,18 +682,10 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card, tmpf->path.value[tmpf->path.len - 1] = 0x12; rv = sc_pkcs15init_create_file(profile, card, prkf); - sc_debug(card->ctx, "rv %i\n",rv); - if (rv) { - sc_debug(card->ctx, "prkf create file failed\n"); - goto failed; - } + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create private key EF"); rv = sc_pkcs15init_create_file(profile, card, tmpf); - sc_debug(card->ctx, "rv %i\n",rv); - if (rv) { - sc_debug(card->ctx, "pubf create failed\n"); - goto failed; - } + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() failed to create temporary public key EF"); memset(&args, 0, sizeof(args)); args.id_prv = prkf->id; @@ -559,49 +694,37 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card, args.key_bits = keybits; args.pubkey_len = keybits/8; args.pubkey = (unsigned char *) malloc(keybits/8); - if (!args.pubkey) { - rv = SC_ERROR_OUT_OF_MEMORY; - goto failed; - } + if (!args.pubkey) + SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate pubkey"); rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_GENERATE_KEY, &args); - if (rv < 0) - goto failed; + SC_TEST_RET(card->ctx, rv, "cosm_generate_key() CARDCTL_OBERTHUR_GENERATE_KEY failed"); /* extract public key */ pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->u.rsa.modulus.len = keybits / 8; - pubkey->u.rsa.modulus.data = (u8 *) malloc(keybits / 8); - if (!pubkey->u.rsa.modulus.data) { - rv = SC_ERROR_MEMORY_FAILURE; - goto failed; - } + pubkey->u.rsa.modulus.data = (unsigned char *) malloc(keybits / 8); + if (!pubkey->u.rsa.modulus.data) + SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate modulus buf"); /* FIXME and if the exponent length is not 3? */ pubkey->u.rsa.exponent.len = 3; - pubkey->u.rsa.exponent.data = (u8 *) malloc(3); - if (!pubkey->u.rsa.exponent.data) { - rv = SC_ERROR_MEMORY_FAILURE; - goto failed; - } + pubkey->u.rsa.exponent.data = (unsigned char *) malloc(3); + if (!pubkey->u.rsa.exponent.data) + SC_TEST_RET(card->ctx, SC_ERROR_OUT_OF_MEMORY, "cosm_generate_key() cannot allocate exponent buf"); memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3); memcpy(pubkey->u.rsa.modulus.data, args.pubkey, args.pubkey_len); info->key_reference = 1; info->path = prkf->path; - if (rv) { - sc_debug(card->ctx, "rv %i\n", rv); - goto failed; - } + sc_debug(card->ctx, "cosm_generate_key() now delete temporary public key\n"); + rv = cosm_delete_file(card, profile, tmpf); - sc_debug(card->ctx, "delete temporary public key\n"); - if ((rv = cosm_delete_file(card, profile, tmpf))) - goto failed; - -failed: - if (tmpf) sc_file_free(tmpf); - if (prkf) sc_file_free(prkf); + if (tmpf) + sc_file_free(tmpf); + if (prkf) + sc_file_free(prkf); SC_FUNC_RETURN(card->ctx, 1, rv); } @@ -611,7 +734,7 @@ failed: * Store a private key */ static int -cosm_new_key(struct sc_profile *profile, sc_card_t *card, +cosm_new_key(struct sc_profile *profile, struct sc_card *card, struct sc_pkcs15_prkey *key, unsigned int idx, struct sc_pkcs15_prkey_info *info) { @@ -652,7 +775,8 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card, rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE); SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation"); -#ifdef ENABLE_OPENSSL +#ifdef ENABLE_OPENSSL + /* Mozilla style ID */ if (!info->id.len) { SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value); info->id.len = SHA_DIGEST_LENGTH; diff --git a/src/pkcs15init/pkcs15.profile b/src/pkcs15init/pkcs15.profile index da4c6e1d..9b9a7202 100644 --- a/src/pkcs15init/pkcs15.profile +++ b/src/pkcs15init/pkcs15.profile @@ -21,7 +21,13 @@ pkcs15 { # Put the DF length into the ODF file? encode-df-length = no; # Have a lastUpdate field in the EF(TokenInfo)? - do-last-update = yes; + do-last-update = yes; + # Method to calculate ID of the crypto objects + # mozilla: SHA1(modulus) for RSA, SHA1(pub) for DSA + # rfc2459: SHA1(SequenceASN1 of public key components as ASN1 integers) + # native: 'E' + number_of_present_objects_of_the_same_type + # default value: 'native' + # pkcs15-id-style = mozilla; } # Default settings. diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index be7bbfc0..f1067303 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -104,7 +104,10 @@ static struct map fileOpNames[] = { { "UPDATE", SC_AC_OP_UPDATE }, { "WRITE", SC_AC_OP_WRITE }, { "ERASE", SC_AC_OP_ERASE }, - { "CRYPTO", SC_AC_OP_CRYPTO }, + { "CRYPTO", SC_AC_OP_CRYPTO }, + { "PIN-DEFINE", SC_AC_OP_PIN_DEFINE }, + { "PIN-CHANGE", SC_AC_OP_PIN_CHANGE }, + { "PIN-RESET", SC_AC_OP_PIN_RESET }, { NULL, 0 } }; static struct map fileTypeNames[] = { @@ -169,6 +172,12 @@ static struct map pinFlagNames[] = { { "exchangeRefData", 0x0800 }, { NULL, 0 } }; +static struct map idStyleNames[] = { + { "native", SC_PKCS15INIT_ID_STYLE_NATIVE }, + { "mozilla", SC_PKCS15INIT_ID_STYLE_MOZILLA }, + { "rfc2459", SC_PKCS15INIT_ID_STYLE_RFC2459 }, + { NULL, 0 } +}; static struct { const char * name; struct map * addr; @@ -280,6 +289,7 @@ sc_profile_new(void) pro->pin_minlen = 4; pro->pin_maxlen = 8; pro->keep_public_key = 1; + pro->id_style = SC_PKCS15INIT_ID_STYLE_NATIVE; return pro; } @@ -780,6 +790,12 @@ do_encode_update_field(struct state *cur, int argc, char **argv) return get_bool(cur, argv[0], &cur->profile->pkcs15.do_last_update); } +static int +do_pkcs15_id_style(struct state *cur, int argc, char **argv) +{ + return map_str2int(cur, argv[0], &cur->profile->id_style, idStyleNames); +} + /* * Process an option block */ @@ -1525,6 +1541,7 @@ static struct command p15_commands[] = { { "direct-certificates", 1, 1, do_direct_certificates }, { "encode-df-length", 1, 1, do_encode_df_length }, { "do-last-update", 1, 1, do_encode_update_field }, + { "pkcs15-id-style", 1, 1, do_pkcs15_id_style }, { NULL, 0, 0, NULL } }; diff --git a/src/pkcs15init/profile.h b/src/pkcs15init/profile.h index f4e62589..fdabe3ce 100644 --- a/src/pkcs15init/profile.h +++ b/src/pkcs15init/profile.h @@ -120,6 +120,9 @@ struct sc_profile { * needs to be updated (in other words: if the card content * has been changed) */ int dirty; + + /* PKCS15 object ID style */ + unsigned int id_style; }; struct sc_profile *sc_profile_new(void); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 431c8d50..5800c3a1 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -68,7 +68,7 @@ enum { #endif OPT_PIN, OPT_NEWPIN, - OPT_PUK, + OPT_PUK }; #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) @@ -119,7 +119,9 @@ static const char *option_help[] = { "Lists private keys", "Lists public keys", "Reads public key with ID ", +#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) "Reads public key with ID , outputs ssh format", +#endif "Test if the card needs a security update", "Update the card with a security update", "Uses reader number ", @@ -402,6 +404,7 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) { unsigned int i; struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; + const char *types[] = { "", "RSA", "DSA", "GOSTR3410" }; const char *usages[] = { "encrypt", "decrypt", "sign", "signRecover", "wrap", "unwrap", "verify", "verifyRecover", @@ -414,13 +417,13 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) }; const unsigned int af_count = NELEMENTS(access_flags); - printf("Private RSA Key [%s]\n", obj->label); + printf("Private %s Key [%s]\n", types[3 & obj->type], obj->label); printf("\tCom. Flags : %X\n", obj->flags); printf("\tUsage : [0x%X]", prkey->usage); for (i = 0; i < usage_count; i++) - if (prkey->usage & (1 << i)) { - printf(", %s", usages[i]); - } + if (prkey->usage & (1 << i)) { + printf(", %s", usages[i]); + } printf("\n"); printf("\tAccess Flags: [0x%X]", prkey->access_flags); for (i = 0; i < af_count; i++) @@ -440,9 +443,9 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) static int list_private_keys(void) { int r, i; - struct sc_pkcs15_object *objs[32]; - - r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, objs, 32); + struct sc_pkcs15_object *objs[32]; + + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, objs, 32); if (r < 0) { fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); return 1; @@ -460,6 +463,7 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj) { unsigned int i; const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data; + const char *types[] = { "", "RSA", "DSA", "GOSTR3410" }; const char *usages[] = { "encrypt", "decrypt", "sign", "signRecover", "wrap", "unwrap", "verify", "verifyRecover", @@ -472,7 +476,7 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj) }; const unsigned int af_count = NELEMENTS(access_flags); - printf("Public RSA Key [%s]\n", obj->label); + printf("Public %s Key [%s]\n", types[3 & obj->type], obj->label); printf("\tCom. Flags : %X\n", obj->flags); printf("\tUsage : [0x%X]", pubkey->usage); for (i = 0; i < usage_count; i++) @@ -498,8 +502,8 @@ static int list_public_keys(void) { int r, i; struct sc_pkcs15_object *objs[32]; - - r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PUBKEY_RSA, objs, 32); + + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PUBKEY, objs, 32); if (r < 0) { fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r)); return 1; @@ -906,7 +910,7 @@ static void print_pin_info(const struct sc_pkcs15_object *obj) (unsigned long)pin->stored_length); printf("\tPad char : 0x%02X\n", pin->pad_char); printf("\tReference : %d\n", pin->reference); - if (pin->type >= 0 && pin->type < sizeof(pin_types)/sizeof(pin_types[0])) + if (pin->type < sizeof(pin_types)/sizeof(pin_types[0])) printf("\tType : %s\n", pin_types[pin->type]); else printf("\tType : [encoding %d]\n", pin->type); @@ -1146,7 +1150,7 @@ static int learn_card(void) return 1; } cert_count = r; - r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, NULL, 0); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0); if (r < 0) { fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); return 1; @@ -1241,7 +1245,7 @@ static int test_update(sc_card_t *in_card) } { - int i=0; + size_t i=0; while(i < rbuf[1]) { if (rbuf[2+i] == 0x86) { /* found our buffer */ break;