static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_info_t *key_info, char *label) { struct sc_context *ctx = p15card->card->ctx; sc_card_t *card = p15card->card; sc_pkcs15_pubkey_info_t pubkey_info; sc_pkcs15_object_t pubkey_obj; struct sc_pkcs15_pubkey pubkey; u8 efbin[1024]; sc_cvc_t cvc; u8 *cvcpo; size_t cvclen; int r; /* EF.CERT is selected */ r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(ctx, r, "Could not read CSR from EF"); cvcpo = efbin; cvclen = r; memset(&cvc, 0, sizeof(cvc)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc); LOG_TEST_RET(ctx, r, "Could decode certificate signing request"); memset(&pubkey, 0, sizeof(pubkey)); r = sc_pkcs15emu_sc_hsm_get_public_key(ctx, &cvc, &pubkey); LOG_TEST_RET(card->ctx, r, "Could not extract public key"); memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); LOG_TEST_RET(ctx, r, "Could not encode public key"); r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_info.direct.raw.value, &pubkey_info.direct.raw.len); LOG_TEST_RET(ctx, r, "Could not encode public key"); r = sc_pkcs15_encode_pubkey_as_spki(ctx, &pubkey, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); LOG_TEST_RET(ctx, r, "Could not encode public key"); pubkey_info.id = key_info->id; strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); if (pubkey.algorithm == SC_ALGORITHM_RSA) { pubkey_info.modulus_length = pubkey.u.rsa.modulus.len << 3; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); } else { /* TODO fix if support of non multiple of 8 curves are added */ pubkey_info.field_length = cvc.primeOrModuluslen << 3; r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); } LOG_TEST_RET(ctx, r, "Could not add public key"); sc_pkcs15emu_sc_hsm_free_cvc(&cvc); sc_pkcs15_erase_pubkey(&pubkey); return SC_SUCCESS; }
static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_info_t *key_info, char *label) { sc_card_t *card = p15card->card; sc_pkcs15_pubkey_info_t pubkey_info; sc_pkcs15_object_t pubkey_obj; struct sc_pkcs15_pubkey pubkey; u8 efbin[1024]; sc_cvc_t cvc; u8 *cvcpo; size_t cvclen; int r; // EF.CERT is selected r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read CSR from EF"); cvcpo = efbin; cvclen = r; memset(&cvc, 0, sizeof(cvc)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc); LOG_TEST_RET(card->ctx, r, "Could decode certificate signing request"); if (cvc.publicPoint || cvc.publicPointlen) { // ToDo implement support for EC Public Keys return SC_SUCCESS; } else { pubkey.algorithm = SC_ALGORITHM_RSA; pubkey.u.rsa.modulus.data = cvc.primeOrModulus; pubkey.u.rsa.modulus.len = cvc.primeOrModuluslen; pubkey.u.rsa.exponent.data = cvc.coefficientAorExponent; pubkey.u.rsa.exponent.len = cvc.coefficientAorExponentlen; } memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_encode_pubkey(p15card->card->ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); pubkey_info.id = key_info->id; strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); LOG_TEST_RET(card->ctx, r, "Could not add public key"); sc_pkcs15emu_sc_hsm_free_cvc(&cvc); return SC_SUCCESS; }
/* * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects * */ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_file_t *file = NULL; sc_path_t path; u8 filelist[MAX_EXT_APDU_LENGTH]; int filelistlength; int r, i; sc_cvc_t devcert; struct sc_app_info *appinfo; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; u8 efbin[512]; u8 *ptr; size_t len; LOG_FUNC_CALLED(card->ctx); appinfo = calloc(1, sizeof(struct sc_app_info)); if (appinfo == NULL) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } appinfo->aid = sc_hsm_aid; appinfo->ddo.aid = sc_hsm_aid; p15card->app = appinfo; sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); r = sc_select_file(card, &path, &file); LOG_TEST_RET(card->ctx, r, "Could not select SmartCard-HSM application"); p15card->card->version.hw_major = 24; /* JCOP 2.4.1r3 */ p15card->card->version.hw_minor = 13; p15card->card->version.fw_major = file->prop_attr[file->prop_attr_len - 2]; p15card->card->version.fw_minor = file->prop_attr[file->prop_attr_len - 1]; sc_file_free(file); /* Read device certificate to determine serial number */ len = sizeof efbin; r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len); LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut"); ptr = efbin; memset(&devcert, 0 ,sizeof(devcert)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert); LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut"); sc_pkcs15emu_sc_hsm_read_tokeninfo(p15card); if (p15card->tokeninfo->label == NULL) { p15card->tokeninfo->label = strdup("SmartCard-HSM"); if (p15card->tokeninfo->label == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) { free(p15card->tokeninfo->manufacturer_id); p15card->tokeninfo->manufacturer_id = NULL; } if (p15card->tokeninfo->manufacturer_id == NULL) { p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de"); if (p15card->tokeninfo->manufacturer_id == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } appinfo->label = strdup(p15card->tokeninfo->label); if (appinfo->label == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); len = strnlen(devcert.chr, sizeof devcert.chr); /* Strip last 5 digit sequence number from CHR */ assert(len >= 8); len -= 5; p15card->tokeninfo->serial_number = calloc(len + 1, 1); if (p15card->tokeninfo->serial_number == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(p15card->tokeninfo->serial_number, devcert.chr, len); *(p15card->tokeninfo->serial_number + len) = 0; sc_hsm_set_serialnr(card, p15card->tokeninfo->serial_number); sc_pkcs15emu_sc_hsm_free_cvc(&devcert); memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = 1; pin_info.path.aid = sc_hsm_aid; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = 0x81; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = 6; pin_info.attrs.pin.stored_length = 0; pin_info.attrs.pin.max_length = 15; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = 3; pin_info.max_tries = 3; strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = 2; pin_info.path.aid = sc_hsm_aid; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = 0x88; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED|SC_PKCS15_PIN_FLAG_SO_PIN; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_BCD; pin_info.attrs.pin.min_length = 16; pin_info.attrs.pin.stored_length = 0; pin_info.attrs.pin.max_length = 16; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = 15; pin_info.max_tries = 15; strlcpy(pin_obj.label, "SOPIN", sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); filelistlength = sc_list_files(card, filelist, sizeof(filelist)); LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); for (i = 0; i < filelistlength; i += 2) { switch(filelist[i]) { case KEY_PREFIX: r = sc_pkcs15emu_sc_hsm_add_prkd(p15card, filelist[i + 1]); break; case DCOD_PREFIX: r = sc_pkcs15emu_sc_hsm_add_dcod(p15card, filelist[i + 1]); break; case CD_PREFIX: r = sc_pkcs15emu_sc_hsm_add_cd(p15card, filelist[i + 1]); break; } if (r != SC_SUCCESS) { sc_log(card->ctx, "Error %d adding elements to framework", r); } } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_pubkey *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; sc_cardctl_sc_hsm_keygen_info_t sc_hsm_keyinfo; sc_cvc_t cvc; u8 *cvcbin, *cvcpo; unsigned int cla,tag; size_t taglen, cvclen; int r; LOG_FUNC_CALLED(p15card->card->ctx); key_info->key_reference = sc_hsm_determine_free_id(p15card, KEY_PREFIX); LOG_TEST_RET(card->ctx, key_info->key_reference, "Could not determine key reference"); memset(&cvc, 0, sizeof(cvc)); strcpy(cvc.car, "UTCA00001"); strcpy(cvc.chr, "UTTM00001"); switch(object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: r = sc_hsm_encode_gakp_rsa(p15card, &cvc, key_info->modulus_length); break; case SC_PKCS15_TYPE_PRKEY_EC: r = sc_hsm_encode_gakp_ec(p15card, &cvc, key_info); break; default: LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_IMPLEMENTED); break; } r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, &cvc, &cvcbin, &cvclen); sc_pkcs15emu_sc_hsm_free_cvc(&cvc); LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata"); cvcpo = cvcbin; sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen); sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen); sc_hsm_keyinfo.key_id = key_info->key_reference; sc_hsm_keyinfo.auth_key_id = 0; sc_hsm_keyinfo.gakprequest = cvcpo; sc_hsm_keyinfo.gakprequest_len = taglen; sc_hsm_keyinfo.gakpresponse = NULL; sc_hsm_keyinfo.gakpresponse_len = 0; r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_GENERATE_KEY, &sc_hsm_keyinfo); if (r < 0) goto out; cvcpo = sc_hsm_keyinfo.gakpresponse; cvclen = sc_hsm_keyinfo.gakpresponse_len; r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc); if (r < 0) { sc_log(p15card->card->ctx, "Could not decode GAKP rdata"); r = SC_ERROR_OBJECT_NOT_VALID; goto out; } r = sc_hsm_update_ef(p15card, EE_CERTIFICATE_PREFIX, key_info->key_reference, 1, sc_hsm_keyinfo.gakpresponse, sc_hsm_keyinfo.gakpresponse_len); if (r < 0) { sc_log(p15card->card->ctx, "Could not save certificate signing request"); goto out; } if (pubkey != NULL) { switch(object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: r = sc_hsm_decode_gakp_rsa(p15card, &cvc, key_info, pubkey); break; case SC_PKCS15_TYPE_PRKEY_EC: r = sc_hsm_decode_gakp_ec(p15card, &cvc, key_info, pubkey); break; } } out: sc_pkcs15emu_sc_hsm_free_cvc(&cvc); if (cvcbin) { free(cvcbin); } if (sc_hsm_keyinfo.gakpresponse) { free(sc_hsm_keyinfo.gakpresponse); } LOG_FUNC_RETURN(p15card->card->ctx, r); }