int sc_pkcs15emu_initialize_pins(sc_pkcs15_card_t *p15card, p15data_items* items) { /* set pins */ int i,r; const pindata* pins = items->pins; if(!pins) return SC_SUCCESS; for (i = 0; pins[i].label; i++) { struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.attrs.pin.reference = pins[i].ref; pin_info.attrs.pin.flags = pins[i].flags; pin_info.attrs.pin.type = pins[i].type; pin_info.attrs.pin.min_length = pins[i].minlen; pin_info.attrs.pin.stored_length = pins[i].storedlen; pin_info.attrs.pin.max_length = pins[i].maxlen; pin_info.attrs.pin.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; if(0 > (r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info))) SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r); } return SC_SUCCESS; }
int sc_pkcs15emu_initialize_objects(sc_pkcs15_card_t *p15card, p15data_items *items) { sc_card_t* card = p15card->card; const objdata* objects = items->objects; int i, r; if(!objects) return SC_SUCCESS; for (i = 0; objects[i].label; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(objects[i].id, &obj_info.id); sc_format_path(objects[i].path, &obj_info.path); strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_format_oid(&obj_info.app_oid, objects[i].aoid); if (r != SC_SUCCESS) return r; strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); obj_obj.flags = objects[i].obj_flags; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } return SC_SUCCESS; }
static int infocamere_1200_init(sc_pkcs15_card_t * p15card) { const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; sc_card_t *card = p15card->card; sc_path_t path; sc_file_t *file; sc_pkcs15_id_t id, auth_id; unsigned char buffer[256]; unsigned char ef_gdo[256]; char serial[256]; unsigned char certlen[2]; int authority, change_sign = 0; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; const char *label = "User Non-repudiation Certificate"; const char *calabel = "CA Certificate"; const char *authlabel = "User Authentication Certificate"; const char *infocamere_cert_path[2] = { "DF01C000", "3F00000011111A02" }; const char *infocamere_auth_certpath[2] = { "11111A02", "000011111B02" }; const char *infocamere_cacert_path[2] = { "DF01C008", "000011114101" }; const char *infocamere_auth_path[2] = { "3F001111", "3F0000001111" }; const char *infocamere_nrepud_path[2] = { "3F00DF01", "3F0000001111" }; const int infocamere_idpin_auth_obj[2] = { 0x95, 0x81 }; const int infocamere_idpin_nrepud_obj[2] = { 0x99, 0x81 }; const int infocamere_idprkey_auth_obj[2] = { 0x9B, 0x01 }; const int infocamere_idprkey_nrepud_obj[2] = { 0x84, 0x01 }; const char *authPIN = "Authentication PIN"; const char *nonrepPIN = "Non-repudiation PIN"; const char *authPRKEY = "Authentication Key"; const char *nonrepPRKEY = "Non repudiation Key"; const int flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; int r, len_iccsn, len_chn; sc_format_path("3F002F02", &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(card->ctx); if (r != SC_SUCCESS || file->size > 255) { /* Not EF.GDO */ return SC_ERROR_WRONG_CARD; } sc_read_binary(card, 0, ef_gdo, file->size, 0); if (ef_gdo[0] != 0x5A || file->size < 3) { /* Not EF.GDO */ return SC_ERROR_WRONG_CARD; } len_iccsn = ef_gdo[1]; memcpy(buffer, ef_gdo + 2, len_iccsn); sc_bin_to_hex(buffer, len_iccsn, serial, sizeof(serial), 0); if (file->size < (size_t) (len_iccsn + 5)) { /* Not CHN */ return SC_ERROR_WRONG_CARD; } if (! (ef_gdo[len_iccsn + 2] == 0x5F && ef_gdo[len_iccsn + 3] == 0x20)) { /* Not CHN */ return SC_ERROR_WRONG_CARD; } len_chn = ef_gdo[len_iccsn + 4]; if (len_chn < 2 || len_chn > 8) { /* Length CHN incorrect */ return SC_ERROR_WRONG_CARD; } if (! (ef_gdo[len_iccsn + 5] == 0x12 && (ef_gdo[len_iccsn + 6] == 0x02 || ef_gdo[len_iccsn + 6] == 0x03))) { /* Not Infocamere Card */ return SC_ERROR_WRONG_CARD; } set_string(&p15card->serial_number, serial); if (ef_gdo[len_iccsn + 6] == 0x02) set_string(&p15card->label, "Infocamere 1202 Card"); else { set_string(&p15card->label, "Infocamere 1203 Card"); change_sign = 1; } set_string(&p15card->manufacturer_id, "Infocamere"); authority = 0; /* Get the authentication certificate length */ sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r >= 0) { sc_read_binary(card, 0, certlen, 2, 0); /* Now set the certificate offset/len */ path.index = 2; path.count = (certlen[1] << 8) + certlen[0]; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("1", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, authlabel, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; /* XXX: the IDs for the key/pin in case of the 1203 type * are wrong, therefore I disable them for now -- Nils */ if (!change_sign) { /* add authentication PIN */ sc_format_path(infocamere_auth_path[ef_gdo[len_iccsn+6]-2], &path); sc_pkcs15_format_id("1", &id); sc_pkcs15emu_add_pin(p15card, &id, authPIN, &path, infocamere_idpin_auth_obj[ef_gdo[len_iccsn+6]-2], SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add authentication private key */ auth_id.value[0] = 1; auth_id.len = 1; sc_pkcs15emu_add_prkey(p15card, &id, authPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, authprkey_usage, &path, infocamere_idprkey_auth_obj[ef_gdo[len_iccsn+6]-2], &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); } } /* Get the non-repudiation certificate length */ sc_format_path(infocamere_cert_path[ef_gdo[len_iccsn+6]-2], &path); if (sc_select_file(card, &path, NULL) < 0) { return SC_ERROR_INTERNAL; } sc_read_binary(card, 0, certlen, 2, 0); /* Now set the certificate offset/len */ path.index = 2; path.count = (certlen[1] << 8) + certlen[0]; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("2", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, label, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; /* Get the CA certificate length */ authority = 1; sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r >= 0) { size_t len; sc_read_binary(card, 0, certlen, 2, 0); len = (certlen[1] << 8) + certlen[0]; if (len != 0) { /* Now set the certificate offset/len */ path.index = 2; path.count = len; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("3", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, calabel, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; } } /* add non repudiation PIN */ sc_format_path(infocamere_nrepud_path[ef_gdo[len_iccsn+6]-2], &path); sc_pkcs15_format_id("2", &id); sc_pkcs15emu_add_pin(p15card, &id, nonrepPIN, &path, infocamere_idpin_nrepud_obj[ef_gdo[len_iccsn+6]-2], SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add non repudiation private key */ auth_id.value[0] = 2; auth_id.len = 1; sc_pkcs15emu_add_prkey(p15card, &id, nonrepPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, prkey_usage, &path, infocamere_idprkey_nrepud_obj[ef_gdo[len_iccsn+6]-2], &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return r; if (change_sign) { /* save old signature funcs */ set_security_env = card->ops->set_security_env; /* set new one */ card->ops->set_security_env = set_sec_env; card->ops->compute_signature = do_sign; } return SC_SUCCESS; }
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) { int r, i, type; unsigned char *buf = NULL; size_t len; sc_pkcs15_tokeninfo_t tokeninfo; sc_path_t tmppath; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; /* Parse the TokenInfo EF */ sc_format_path("3f004f005032", &tmppath); r = sc_select_file(card, &tmppath, &p15card->file_tokeninfo); if (r) goto end; if ( (len = p15card->file_tokeninfo->size) == 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EF(TokenInfo) is empty\n"); goto end; } buf = malloc(len); if (buf == NULL) return SC_ERROR_OUT_OF_MEMORY; r = sc_read_binary(card, 0, buf, len, 0); if (r < 0) goto end; if (r <= 2) { r = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } memset(&tokeninfo, 0, sizeof(tokeninfo)); r = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t) r); if (r != SC_SUCCESS) goto end; *(p15card->tokeninfo) = tokeninfo; /* Card type detection */ if (card->type == SC_CARD_TYPE_IAS_PTEID) type = IAS_CARD; else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) type = GEMSAFE_CARD; else { r = SC_ERROR_INTERNAL; goto end; } p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* TODO: Use the cardholder's name? */ /* TODO: Use Portuguese descriptions? */ /* Add X.509 Certificates */ for (i = 0; i < 4; i++) { static const char *pteid_cert_names[4] = { "AUTHENTICATION CERTIFICATE", "SIGNATURE CERTIFICATE", "SIGNATURE SUB CA", "AUTHENTICATION SUB CA" }; /* X.509 Certificate Paths */ static const char *pteid_cert_paths[4] = { "3f005f00ef09", /* Authentication Certificate path */ "3f005f00ef08", /* Digital Signature Certificate path */ "3f005f00ef0f", /* Signature sub CA path */ "3f005f00ef10" /* Authentication sub CA path */ }; /* X.509 Certificate IDs */ static const int pteid_cert_ids[4] = {0x45, 0x46, 0x51, 0x52}; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); cert_info.id.value[0] = pteid_cert_ids[i]; cert_info.id.len = 1; sc_format_path(pteid_cert_paths[i], &cert_info.path); strlcpy(cert_obj.label, pteid_cert_names[i], sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add PINs */ for (i = 0; i < 3; i++) { static const char *pteid_pin_names[3] = { "Auth PIN", "Sign PIN", "Address PIN" }; /* PIN References */ static const int pteid_pin_ref[2][3] = { {1, 130, 131}, {129, 130, 131} }; /* PIN Authentication IDs */ static const int pteid_pin_authid[3] = {1, 2, 3}; /* PIN Paths */ static const char *pteid_pin_paths[2][3] = { {NULL, "3f005f00", "3f005f00"}, {NULL, NULL, NULL} }; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = pteid_pin_authid[i]; pin_info.attrs.pin.reference = pteid_pin_ref[type][i]; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_CASE_SENSITIVE; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = 4; pin_info.attrs.pin.stored_length = 8; pin_info.attrs.pin.max_length = 8; pin_info.attrs.pin.pad_char = type == IAS_CARD ? 0x2F : 0xFF; pin_info.tries_left = -1; if (pteid_pin_paths[type][i] != NULL) sc_format_path(pteid_pin_paths[type][i], &pin_info.path); strlcpy(pin_obj.label, pteid_pin_names[i], sizeof(pin_obj.label)); pin_obj.flags = 0; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add Private Keys */ for (i = 0; i < 2; i++) { /* Key reference */ static const int pteid_prkey_keyref[2][2] = { {1, 130}, {2, 1} }; /* RSA Private Key usage */ static int pteid_prkey_usage[2] = { SC_PKCS15_PRKEY_USAGE_SIGN, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION}; /* RSA Private Key IDs */ static const int pteid_prkey_ids[2] = {0x45, 0x46}; static const char *pteid_prkey_names[2] = { "CITIZEN AUTHENTICATION KEY", "CITIZEN SIGNATURE KEY"}; /* RSA Private Key Paths */ static const char *pteid_prkey_paths[2][2] = { {NULL, "3f005f00"}, {NULL, NULL} }; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); prkey_info.id.len = 1; prkey_info.id.value[0] = pteid_prkey_ids[i]; prkey_info.usage = pteid_prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = pteid_prkey_keyref[type][i]; prkey_info.modulus_length = 1024; if (pteid_prkey_paths[type][i] != NULL) sc_format_path(pteid_prkey_paths[type][i], &prkey_info.path); strlcpy(prkey_obj.label, pteid_prkey_names[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = i + 1; prkey_obj.user_consent = (i == 1) ? 1 : 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add objects */ for (i = 0; i < 3; i++) { static const char *object_ids[3] = {"1", "2", "3"}; static const char *object_oids[3] = {"-1", "-1", "-1"}; static const char *object_labels[3] = {"Citizen Data", "Citizen Address Data", "Citizen Notepad"}; static const char *object_authids[3] = {NULL, "3", "1"}; static const char *object_paths[3] = {"3f005f00ef02", "3f005f00ef05", "3f005f00ef07"}; static const int object_flags[3] = {0, SC_PKCS15_CO_FLAG_PRIVATE, SC_PKCS15_CO_FLAG_MODIFIABLE}; struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(object_ids[i], &obj_info.id); sc_format_path(object_paths[i], &obj_info.path); r = sc_format_oid(&obj_info.app_oid, object_oids[i]); if (r != SC_SUCCESS) goto end; strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); if (object_authids[i] != NULL) sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id); strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); obj_obj.flags = object_flags[i]; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) goto end; } end: if (buf != NULL) { free(buf); buf = NULL; } if (r) return r; return SC_SUCCESS; }
int sc_pkcs15emu_initialize_certificates(sc_pkcs15_card_t *p15card, p15data_items* items) { /* set certs */ sc_card_t* card = p15card->card; const cdata* certs = items->certs; int onFailResume = items->cert_continue; int i, r; if(!certs) return SC_SUCCESS; for (i = 0; certs[i].label; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); cert_obj.flags = certs[i].obj_flags; if(items->cert_load) { u8* cert_buffer = NULL; size_t cert_length = 0; int should_free = 0; if(SC_SUCCESS != sc_select_file(card, &cert_info.path, NULL)) { if(onFailResume) continue; else break; } if(SC_SUCCESS != (r = items->cert_load(card, &cert_buffer, &cert_length, &should_free))) { if(onFailResume) continue; else break; } /* Handle cert */ /* If no cert handler, add.. if cert handler succeeds.. add */ if(!items->cert_handle || SC_SUCCESS == (r = items->cert_handle(p15card, items, &certs[i], cert_buffer, cert_length))) { r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); } if(should_free) free(cert_buffer); if(SC_SUCCESS != r) { if(onFailResume) continue; else break; } } else { /* Automatically add */ if(SC_SUCCESS != sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info)) { if(onFailResume) continue; else break; } } } return SC_SUCCESS; }
static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card) { const cdata certs[] = { {"DS certificate", 0, "3F00DF01C000","1", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"CA certificate", 1, "3F00DF01C008","2", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"KE certificate", 0, "3F00DF01C200","3", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"AUT certificate",0, "3F00DF01C500","4", SC_PKCS15_CO_FLAG_MODIFIABLE}, {NULL, 0, NULL, NULL, 0} }; const pindata pins[] = { { "99", "DS pin", "3F00DF01", 0x99, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 8, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const prdata prkeys[] = { { "1", "DS key", 1024, USAGE_NONREP, "3F00DF01", 0x84, "99", SC_PKCS15_CO_FLAG_PRIVATE}, { "3", "KE key", 1024, USAGE_KE, "3F00DF01", 0x85, NULL, SC_PKCS15_CO_FLAG_PRIVATE}, { "4", "AUT key", 1024, USAGE_AUT, "3F00DF01", 0x82, NULL, SC_PKCS15_CO_FLAG_PRIVATE}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; char buf[256]; sc_path_t path; sc_file_t *file = NULL; sc_card_t *card = p15card->card; sc_serial_number_t serial; /* get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; if (p15card->serial_number) free(p15card->serial_number); p15card->serial_number = (char *) malloc(strlen(buf) + 1); if (!p15card->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->serial_number, buf); /* the TokenInfo version number */ p15card->version = 0; /* the manufacturer ID, in this case Giesecke & Devrient GmbH */ if (p15card->manufacturer_id) free(p15card->manufacturer_id); p15card->manufacturer_id = (char *) malloc(strlen(MANU_ID) + 1); if (!p15card->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->manufacturer_id, MANU_ID); /* set certs */ for (i = 0; certs[i].label; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); if (!get_cert_len(card, &cert_info.path)) /* skip errors */ continue; strlcpy(cert_obj.label, certs[i].label, sizeof(cert_obj.label)); cert_obj.flags = certs[i].obj_flags; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set pins */ for (i = 0; pins[i].label; i++) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strlcpy(pin_obj.label, pins[i].label, sizeof(pin_obj.label)); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set private keys */ for (i = 0; prkeys[i].label; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); strlcpy(prkey_obj.label, prkeys[i].label, sizeof(prkey_obj.label)); prkey_obj.flags = prkeys[i].obj_flags; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } /* select the application DF */ sc_format_path("3F00DF01", &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; }
static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card) { const cdata certs[] = { {"C.CH.EKEY", 0, "DF71C001","1", 0},/* Decryption Certificate */ {NULL, 0, NULL, NULL, 0} }; const pindata pins[] = { { "01", "PIN.DEC", "3F00DF71", 0x81, /* Decryption PIN */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 4, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const prdata prkeys[] = { { "01", "SK.CH.EKEY", 1536, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP, "", /* do not specify file here to prevent reset of security state */ 0x88, "01", SC_PKCS15_CO_FLAG_PRIVATE}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; u8 buf[256]; char buf2[256]; sc_path_t path; sc_file_t *file = NULL; sc_card_t *card = p15card->card; /* get serial number */ /* read EF_CIN_CSN file */ sc_format_path("DF71D001", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; r = sc_read_binary(card, 0, buf, 8, 0); if (r != 8) return SC_ERROR_INTERNAL; r = sc_bin_to_hex(buf, 8, buf2, sizeof(buf2), 0); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; if (p15card->tokeninfo->serial_number) free(p15card->tokeninfo->serial_number); p15card->tokeninfo->serial_number = malloc(strlen(buf2) + 1); if (!p15card->tokeninfo->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->serial_number, buf2); /* manufacturer ID */ if (p15card->tokeninfo->manufacturer_id) free(p15card->tokeninfo->manufacturer_id); p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1); if (!p15card->tokeninfo->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID); /* card label */ if (p15card->tokeninfo->label) free(p15card->tokeninfo->label); p15card->tokeninfo->label = malloc(strlen(CARD_LABEL) + 1); if (!p15card->tokeninfo->label) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->label, CARD_LABEL); /* set certs */ for (i = 0; certs[i].label; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); if (!get_cert_len(card, &cert_info.path)) /* skip errors */ continue; strlcpy(cert_obj.label, certs[i].label, sizeof(cert_obj.label)); cert_obj.flags = certs[i].obj_flags; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set pins */ for (i = 0; pins[i].label; i++) { struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = pins[i].ref; pin_info.attrs.pin.flags = pins[i].flags; pin_info.attrs.pin.type = pins[i].type; pin_info.attrs.pin.min_length = pins[i].minlen; pin_info.attrs.pin.stored_length = pins[i].storedlen; pin_info.attrs.pin.max_length = pins[i].maxlen; pin_info.attrs.pin.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strlcpy(pin_obj.label, pins[i].label, sizeof(pin_obj.label)); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set private keys */ for (i = 0; prkeys[i].label; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); strlcpy(prkey_obj.label, prkeys[i].label, sizeof(prkey_obj.label)); prkey_obj.flags = prkeys[i].obj_flags; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } /* select the application DF */ sc_format_path("DF71", &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; }
static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) { int r; unsigned int i; struct sc_path path; struct sc_file *file = NULL; struct sc_card *card = p15card->card; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n"); if (p15card->tokeninfo->label) free(p15card->tokeninfo->label); p15card->tokeninfo->label = malloc(strlen(APPLET_NAME) + 1); if (!p15card->tokeninfo->label) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->label, APPLET_NAME); if (p15card->tokeninfo->serial_number) free(p15card->tokeninfo->serial_number); p15card->tokeninfo->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1); if (!p15card->tokeninfo->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER); /* the GemSAFE applet version number */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03); apdu.cla = 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); /* Manual says Le=0x05, but should be 0x08 to return full version numer */ apdu.le = 0x08; apdu.lc = 0; apdu.datalen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) return SC_ERROR_INTERNAL; if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; /* the manufacturer ID, in this case GemPlus */ if (p15card->tokeninfo->manufacturer_id) free(p15card->tokeninfo->manufacturer_id); p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1); if (!p15card->tokeninfo->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID); /* determine allocated key containers and length of certificates */ r = gemsafe_get_cert_len(card); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; /* set certs */ sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n"); for (i = 0; i < gemsafe_cert_max; i++) { struct sc_pkcs15_id p15Id; struct sc_path path; if (gemsafe_cert[i].label == NULL) continue; sc_format_path(gemsafe_cert[i].path, &path); sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id); path.index = gemsafe_cert[i].index; path.count = gemsafe_cert[i].count; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, gemsafe_cert[i].authority, &path, &p15Id, gemsafe_cert[i].label, gemsafe_cert[i].obj_flags); } /* set gemsafe_pin */ sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n"); for (i=0; i < gemsafe_pin_max; i++) { struct sc_pkcs15_id p15Id; struct sc_path path; sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id); sc_format_path(gemsafe_pin[i].path, &path); if (gemsafe_pin[i].atr_len == 0 || (gemsafe_pin[i].atr_len == p15card->card->atr.len && memcmp(p15card->card->atr.value, gemsafe_pin[i].atr, p15card->card->atr.len) == 0)) { sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label, &path, gemsafe_pin[i].ref, gemsafe_pin[i].type, gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen, gemsafe_pin[i].flags, gemsafe_pin[i].tries_left, gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags); break; } }; /* set private keys */ sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n"); for (i = 0; i < gemsafe_cert_max; i++) { struct sc_pkcs15_id p15Id, authId, *pauthId; struct sc_path path; int key_ref = 0x03; if (gemsafe_prkeys[i].label == NULL) continue; sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id); if (gemsafe_prkeys[i].auth_id) { sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId); pauthId = &authId; } else pauthId = NULL; sc_format_path(gemsafe_prkeys[i].path, &path); /* * The key ref may be different for different sites; * by adding flags=n where the low order 4 bits can be * the key ref we can force it. */ if ( p15card->card->flags & 0x0F) { key_ref = p15card->card->flags & 0x0F; sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Overriding key_ref %d with %d\n", gemsafe_prkeys[i].ref, key_ref); } else key_ref = gemsafe_prkeys[i].ref; sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label, SC_PKCS15_TYPE_PRKEY_RSA, gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage, &path, key_ref, pauthId, gemsafe_prkeys[i].obj_flags); } /* select the application DF */ sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n"); sc_format_path(GEMSAFE_APP_PATH, &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; }
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) { u8 buf[1024]; sc_pkcs15_df_t *df; sc_pkcs15_object_t *p15_obj; sc_path_t path; struct sc_file *file = NULL; size_t len; int rv; int i; sc_context_t *ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); /* Check for correct card atr */ if (pteid_detect_card(p15card->card) != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_log(p15card->card->ctx, "Selecting application DF"); sc_format_path("4F00", &path); rv = sc_select_file(p15card->card, &path, &file); if (rv != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; /* Load TokenInfo */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005032", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } memset(p15card->tokeninfo, 0, sizeof(*p15card->tokeninfo)); rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo, buf, len); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* Load ODF */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005031", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } rv = parse_odf(buf, len, p15card); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } /* Decode EF.PrKDF, EF.PuKDF, EF.CDF and EF.AODF */ for (df = p15card->df_list; df != NULL; df = df->next) { if (df->type == SC_PKCS15_PRKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PrKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_PUKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PuKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_CDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.CDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_AODF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.AODF (%s) failed: %d", sc_print_path(&df->path), rv); } } } p15_obj = p15card->obj_list; while (p15_obj != NULL) { if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PRKDF) ) { struct sc_pkcs15_prkey_info *prkey_info = (sc_pkcs15_prkey_info_t *) p15_obj->data; prkey_info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_LOCAL; p15_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE; } if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_AODF) ) { static const char *pteid_pin_names[3] = { "Auth PIN", "Sign PIN", "Address PIN" }; struct sc_pin_cmd_data pin_cmd_data; struct sc_pkcs15_auth_info *pin_info = (sc_pkcs15_auth_info_t *) p15_obj->data; strlcpy(p15_obj->label, pteid_pin_names[pin_info->auth_id.value[0]-1], sizeof(p15_obj->label)); pin_info->attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING; pin_info->tries_left = -1; pin_info->max_tries = 3; pin_info->auth_method = SC_AC_CHV; memset(&pin_cmd_data, 0, sizeof(pin_cmd_data)); pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO; pin_cmd_data.pin_type = pin_info->attrs.pin.type; pin_cmd_data.pin_reference = pin_info->attrs.pin.reference; rv = sc_pin_cmd(p15card->card, &pin_cmd_data, NULL); if (rv == SC_SUCCESS) { pin_info->tries_left = pin_cmd_data.pin1.tries_left; pin_info->logged_in = pin_cmd_data.pin1.logged_in; } } /* Remove found public keys as cannot be read_binary()'d */ if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) { sc_pkcs15_object_t *puk = p15_obj; p15_obj = p15_obj->next; sc_pkcs15_remove_object(p15card, puk); sc_pkcs15_free_object(puk); } else { p15_obj = p15_obj->next; } } /* Add data objects */ for (i = 0; i < 5; i++) { static const char *object_labels[5] = { "Trace", "Citizen Data", "Citizen Address Data", "SOd", "Citizen Notepad", }; static const char *object_authids[5] = {NULL, NULL, "3", NULL, NULL}; static const char *object_paths[5] = { "3f000003", "3f005f00ef02", "3f005f00ef05", "3f005f00ef06", "3f005f00ef07", }; static const int object_flags[5] = { 0, 0, SC_PKCS15_CO_FLAG_PRIVATE, 0, 0, }; struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_format_path(object_paths[i], &obj_info.path); strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); if (object_authids[i] != NULL) sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id); strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); obj_obj.flags = object_flags[i]; rv = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (rv != SC_SUCCESS){ sc_log(ctx, "Object add failed: %d", rv); break; } } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) { /* The cert objects will return all the data */ /* Note: pkcs11 objects do not have CK_ID values */ static const objdata objects[] = { {"1", "Card Capability Container", "2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0}, {"2", "Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0}, {"3", "Unsigned Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0}, {"4", "X.509 Certificate for PIV Authentication", "2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0}, {"5", "Cardholder Fingerprints", "2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE}, {"6", "Printed Information", "2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE}, {"7", "Cardholder Facial Image", "2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE}, {"8", "X.509 Certificate for Digital Signature", "2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0}, {"9", "X.509 Certificate for Key Management", "2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0}, {"10","X.509 Certificate for Card Authentication", "2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0}, {"11", "Security Object", "2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0}, {"12", "Discovery Object", "2.16.840.1.101.3.7.2.96.80", NULL, "6050", 0}, {"13", "Key History Object", "2.16.840.1.101.3.7.2.96.96", NULL, "6060", 0}, {"14", "Cardholder Iris Image", "2.16.840.1.101.3.7.2.16.21", NULL, "1015", SC_PKCS15_CO_FLAG_PRIVATE}, {"15", "Retired X.509 Certificate for Key Management 1", "2.16.840.1.101.3.7.2.16.1", NULL, "1001", 0}, {"16", "Retired X.509 Certificate for Key Management 2", "2.16.840.1.101.3.7.2.16.2", NULL, "1002", 0}, {"17", "Retired X.509 Certificate for Key Management 3", "2.16.840.1.101.3.7.2.16.3", NULL, "1003", 0}, {"18", "Retired X.509 Certificate for Key Management 4", "2.16.840.1.101.3.7.2.16.4", NULL, "1004", 0}, {"19", "Retired X.509 Certificate for Key Management 5", "2.16.840.1.101.3.7.2.16.5", NULL, "1005", 0}, {"20", "Retired X.509 Certificate for Key Management 6", "2.16.840.1.101.3.7.2.16.6", NULL, "1006", 0}, {"21", "Retired X.509 Certificate for Key Management 7", "2.16.840.1.101.3.7.2.16.7", NULL, "1007", 0}, {"22", "Retired X.509 Certificate for Key Management 8", "2.16.840.1.101.3.7.2.16.8", NULL, "1008", 0}, {"23", "Retired X.509 Certificate for Key Management 9", "2.16.840.1.101.3.7.2.16.9", NULL, "1009", 0}, {"24", "Retired X.509 Certificate for Key Management 10", "2.16.840.1.101.3.7.2.16.10", NULL, "100A", 0}, {"25", "Retired X.509 Certificate for Key Management 11", "2.16.840.1.101.3.7.2.16.11", NULL, "100B", 0}, {"26", "Retired X.509 Certificate for Key Management 12", "2.16.840.1.101.3.7.2.16.12", NULL, "100C", 0}, {"27", "Retired X.509 Certificate for Key Management 13", "2.16.840.1.101.3.7.2.16.13", NULL, "100D", 0}, {"28", "Retired X.509 Certificate for Key Management 14", "2.16.840.1.101.3.7.2.16.14", NULL, "100E", 0}, {"29", "Retired X.509 Certificate for Key Management 15", "2.16.840.1.101.3.7.2.16.15", NULL, "100F", 0}, {"30", "Retired X.509 Certificate for Key Management 16", "2.16.840.1.101.3.7.2.16.16", NULL, "1010", 0}, {"31", "Retired X.509 Certificate for Key Management 17", "2.16.840.1.101.3.7.2.16.17", NULL, "1011", 0}, {"32", "Retired X.509 Certificate for Key Management 18", "2.16.840.1.101.3.7.2.16.18", NULL, "1012", 0}, {"33", "Retired X.509 Certificate for Key Management 19", "2.16.840.1.101.3.7.2.16.19", NULL, "1013", 0}, {"34", "Retired X.509 Certificate for Key Management 20", "2.16.840.1.101.3.7.2.16.20", NULL, "1014", 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * NIST 800-73-1 lifted the restriction on * requering pin protected certs. Thus the default is to * not require this. */ /* certs will be pulled out from the cert objects */ /* the number of cert, pubkey and prkey triplets */ #define PIV_NUM_CERTS_AND_KEYS 24 static const cdata certs[PIV_NUM_CERTS_AND_KEYS] = { {"1", "Certificate for PIV Authentication", 0, "0101cece", 0}, {"2", "Certificate for Digital Signature", 0, "0100cece", 0}, {"3", "Certificate for Key Management", 0, "0102cece", 0}, {"4", "Certificate for Card Authentication", 0, "0500cece", 0}, {"5", "Retired Certificate for Key Management 1", 0, "1001cece", 0}, {"6", "Retired Certificate for Key Management 2", 0, "1002cece", 0}, {"7", "Retired Certificate for Key Management 3", 0, "1003cece", 0}, {"8", "Retired Certificate for Key Management 4", 0, "1004cece", 0}, {"9", "Retired Certificate for Key Management 5", 0, "1005cece", 0}, {"10", "Retired Certificate for Key Management 6", 0, "1006cece", 0}, {"11", "Retired Certificate for Key Management 7", 0, "1007cece", 0}, {"12", "Retired Certificate for Key Management 8", 0, "1008cece", 0}, {"13", "Retired Certificate for Key Management 9", 0, "1009cece", 0}, {"14", "Retired Certificate for Key Management 10", 0, "100Acece", 0}, {"15", "Retired Certificate for Key Management 11", 0, "100Bcece", 0}, {"16", "Retired Certificate for Key Management 12", 0, "100Ccece", 0}, {"17", "Retired Certificate for Key Management 13", 0, "100Dcece", 0}, {"18", "Retired Certificate for Key Management 14", 0, "100Ecece", 0}, {"19", "Retired Certificate for Key Management 15", 0, "100Fcece", 0}, {"20", "Retired Certificate for Key Management 16", 0, "1010cece", 0}, {"21", "Retired Certificate for Key Management 17", 0, "1011cece", 0}, {"22", "Retired Certificate for Key Management 18", 0, "1012cece", 0}, {"23", "Retired Certificate for Key Management 19", 0, "1013cece", 0}, {"24", "Retired Certificate for Key Management 20", 0, "1014cece", 0} }; static const pindata pins[] = { { "1", "PIV Card Holder pin", "", 0x80, /* label and ref will change if using global pin */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { "2", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from pkcs15v1_1 Table 2 * RSA and EC hav differents set of usage */ static const pubdata pubkeys[PIV_NUM_CERTS_AND_KEYS] = { { "1", "PIV AUTH pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY, "9A06", 0x9A, "1", 0, "PIV_9A_KEY"}, { "2", "SIGN pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "9C06", 0x9C, "1", 0, "PIV_9C_KEY"}, { "3", "KEY MAN pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9D06", 0x9D, "1", 0, "PIV_9D_KEY"}, { "4", "CARD AUTH pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY, "9E06", 0x9E, "0", 0, "PIV_9E_KEY"}, /* no pin, and avail in contactless */ { "5", "Retired KEY MAN 1", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8206", 0x82, "1", 0, NULL}, { "6", "Retired KEY MAN 2", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8306", 0x83, "1", 0, NULL}, { "7", "Retired KEY MAN 3", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8406", 0x84, "1", 0, NULL}, { "8", "Retired KEY MAN 4", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8506", 0x85, "1", 0, NULL}, { "9", "Retired KEY MAN 5", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8606", 0x86, "1", 0, NULL}, { "10", "Retired KEY MAN 6", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8706", 0x87, "1", 0, NULL}, { "11", "Retired KEY MAN 7", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8806", 0x88, "1", 0, NULL}, { "12", "Retired KEY MAN 8", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8906", 0x89, "1", 0, NULL}, { "13", "Retired KEY MAN 9", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8A06", 0x8A, "1", 0, NULL}, { "14", "Retired KEY MAN 10", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8B06", 0x8B, "1", 0, NULL}, { "15", "Retired KEY MAN 11", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8C06", 0x8C, "1", 0, NULL}, { "16", "Retired KEY MAN 12", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8D06", 0x8D, "1", 0, NULL}, { "17", "Retired KEY MAN 13", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8E06", 0x8E, "1", 0, NULL}, { "18", "Retired KEY MAN 14", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8F06", 0x8F, "1", 0, NULL}, { "19", "Retired KEY MAN 15", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9006", 0x90, "1", 0, NULL}, { "20", "Retired KEY MAN 16", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9106", 0x91, "1", 0, NULL}, { "21", "Retired KEY MAN 17", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9206", 0x92, "1", 0, NULL}, { "22", "Retired KEY MAN 18", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9306", 0x93, "1", 0, NULL}, { "23", "Retired KEY MAN 19", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9406", 0x94, "1", 0, NULL}, { "24", "Retired KEY MAN 20", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9506", 0x95, "1", 0, NULL} }; /* * note some of the SC_PKCS15_PRKEY values are dependent * on the key algorithm, and will be reset. */ static const prdata prkeys[PIV_NUM_CERTS_AND_KEYS] = { { "1", "PIV AUTH key", /*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN, "", 0x9A, "1", SC_PKCS15_CO_FLAG_PRIVATE, 0}, { "2", "SIGN key", /*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "", 0x9C, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "3", "KEY MAN key", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x9D, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "4", "CARD AUTH key", /*RSA*/SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN, "", 0x9E, NULL, 0, 0}, /* no PIN needed, works with wireless */ { "5", "Retired KEY MAN 1", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x82, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "6", "Retired KEY MAN 2", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x83, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "7", "Retired KEY MAN 3", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x84, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "8", "Retired KEY MAN 4", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x85, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "9", "Retired KEY MAN 5", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x86, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "10", "Retired KEY MAN 6", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x87, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "11", "Retired KEY MAN 7", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x88, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "12", "Retired KEY MAN 8", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x89, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "13", "Retired KEY MAN 9", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8A, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "14", "Retired KEY MAN 10", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8B, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "15", "Retired KEY MAN 11", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8C, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "16", "Retired KEY MAN 12", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8D, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "17", "Retired KEY MAN 13", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8E, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "18", "Retired KEY MAN 14", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8F, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "19", "Retired KEY MAN 15", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x90, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "20", "Retired KEY MAN 16", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x91, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "21", "Retired KEY MAN 17", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x92, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "22", "Retired KEY MAN 18", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x93, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "23", "Retired KEY MAN 19", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x94, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "24", "Retired KEY MAN 20", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x95, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1} }; int r, i; sc_card_t *card = p15card->card; sc_file_t *file_out = NULL; int exposed_cert[PIV_NUM_CERTS_AND_KEYS] = {1, 0, 0, 0}; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; common_key_info ckis[PIV_NUM_CERTS_AND_KEYS]; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* could read this off card if needed */ /* CSP does not like a - in the name */ p15card->tokeninfo->label = strdup("PIV_II"); p15card->tokeninfo->manufacturer_id = strdup(MANU_ID); /* * get serial number * We will use the FASC-N from the CHUID * Note we are not verifying CHUID, belongs to this card * but need serial number for Mac tokend */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"sc_card_ctl rc=%d",r); p15card->tokeninfo->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->tokeninfo->serial_number = strdup(buf); } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding objects..."); /* set other objects */ for (i = 0; objects[i].label; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(objects[i].id, &obj_info.id); sc_format_path(objects[i].path, &obj_info.path); /* See if the object can not be present on the card */ r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &obj_info.path); if (r == 1) continue; /* Not on card, do not define the object */ strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_format_oid(&obj_info.app_oid, objects[i].aoid); if (r != SC_SUCCESS) return r; if (objects[i].auth_id) sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id); strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); obj_obj.flags = objects[i].obj_flags; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* TODO * PIV keys 9C and 9D require the pin verify be done just befor any * crypto operation using these keys. * * Nss 3.12.7 does not check the CKA_ALWAYS_AUTHENTICATE attribute of a key * and will do a C_FindObjects with only CKA_VALUE looking for a certificate * it had found earlier after c_Login. The template does not add CKA_TYPE=cert. * This will cause the card-piv to read all the objects and will reset * the security status for the 9C and 9D keys. * Mozilla Bug 457025 * * We can not read all the objects, as some need the PIN! */ } /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. * If no cert, then see if pubkey (i.e. we are initilizing, * and the pubkey is in a file,) then add pubkey and privkey * If no cert and no pubkey, skip adding them. */ /* set certs */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding certs..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out; ckis[i].cert_found = 0; ckis[i].key_alg = -1; ckis[i].pubkey_found = 0; ckis[i].pubkey_len = 0; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); cert_obj.flags = certs[i].obj_flags; /* See if the cert might be present or not. */ r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &cert_info.path); if (r == 1) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cert can not be present,i=%d", i); continue; } /* use a &file_out so card-piv.c will read cert if present */ r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, &file_out); if (file_out) { sc_file_free(file_out); file_out = NULL; } if (r) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "No cert found,i=%d", i); continue; } ckis[i].cert_found = 1; /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0 || cert_out->key == NULL) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); continue; } ckis[i].key_alg = cert_out->key->algorithm; switch (cert_out->key->algorithm) { case SC_ALGORITHM_RSA: /* save pubkey_len for pub and priv */ ckis[i].pubkey_len = cert_out->key->u.rsa.modulus.len * 8; break; case SC_ALGORITHM_EC: ckis[i].pubkey_len = cert_out->key->u.ec.field_length; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported key.algorithm %d", cert_out->key->algorithm); ckis[i].pubkey_len = 0; /* set some value for now */ } sc_pkcs15_free_certificate(cert_out); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, " Failed to add cert obj r=%d",r); continue; } } /* set pins */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding pins..."); for (i = 0; pins[i].label; i++) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; const char * label; int pin_ref; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; label = pins[i].label; if (i == 0 && (card->ops->card_ctl)(card, SC_CARDCTL_PIV_PIN_PREFERENCE, &pin_ref) == 0 && pin_ref == 0x00) { /* must be 80 for PIV pin, or 00 for Global PIN */ pin_info.reference = pin_ref; label = "Global PIN"; } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } /* set public keys */ /* We may only need this during initialzation when genkey * gets the pubkey, but it can not be read from the card * at a later time. The piv-tool can stach pubkey in file */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding pub keys..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_pubkey *p15_key; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id); pubkey_info.native = 1; pubkey_info.key_reference = pubkeys[i].ref; // sc_format_path(pubkeys[i].path, &pubkey_info.path); strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pubkey_obj.flags = pubkeys[i].obj_flags; if (pubkeys[i].auth_id) sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id); /* If no cert found, piv-tool may have stached the pubkey * so we can use it when generating a certificate request * The file is a OpenSSL DER EVP_KEY, which looks like * a certificate subjectPublicKeyInfo. * */ if (ckis[i].cert_found == 0 ) { /* no cert found */ char * filename = NULL; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"No cert for this pub key i=%d",i); /* * If we used the piv-tool to generate a key, * we would have saved the public key as a file. * This code is only used while signing a request * After the certificate is loaded on the card, * the public key is extracted from the certificate. */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"DEE look for env %s", pubkeys[i].getenvname?pubkeys[i].getenvname:"NULL"); if (pubkeys[i].getenvname == NULL) continue; filename = getenv(pubkeys[i].getenvname); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"DEE look for file %s", filename?filename:"NULL"); if (filename == NULL) continue; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Adding pubkey from file %s",filename); r = sc_pkcs15_pubkey_from_spki_filename(card->ctx, filename, &p15_key); if (r < 0) continue; /* Only get here if no cert, and the the above found the * pub key file (actually the SPKI version). This only * happens when trying initializing a card and have set * env PIV_9A_KEY or 9C, 9D, 9E to point at the file. * * We will cache it using the PKCS15 emulation objects */ pubkey_info.path.len = 0; ckis[i].key_alg = p15_key->algorithm; switch (p15_key->algorithm) { case SC_ALGORITHM_RSA: /* save pubkey_len in pub and priv */ ckis[i].pubkey_len = p15_key->u.rsa.modulus.len * 8; ckis[i].pubkey_found = 1; break; case SC_ALGORITHM_EC: ckis[i].key_alg = SC_ALGORITHM_EC; ckis[i].pubkey_len = p15_key->u.ec.field_length; ckis[i].pubkey_found = 1; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Unsupported key_alg %d",p15_key->algorithm); continue; } pubkey_obj.emulated = p15_key; p15_key = NULL; } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"adding pubkey for %d keyalg=%d",i, ckis[i].key_alg); switch (ckis[i].key_alg) { case SC_ALGORITHM_RSA: pubkey_info.usage = pubkeys[i].usage_rsa; pubkey_info.modulus_length = ckis[i].pubkey_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* should not fail */ ckis[i].pubkey_found = 1; break; case SC_ALGORITHM_EC: pubkey_info.usage = pubkeys[i].usage_ec; pubkey_info.field_length = ckis[i].pubkey_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* should not fail */ ckis[i].pubkey_found = 1; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"key_alg %d not supported", ckis[i].key_alg); continue; } } /* set private keys */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding private keys..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); if (ckis[i].cert_found == 0 && ckis[i].pubkey_found == 0) continue; /* i.e. no cert or pubkey */ sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; sc_format_path(prkeys[i].path, &prkey_info.path); strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); prkey_obj.flags = prkeys[i].obj_flags; prkey_obj.user_consent = prkeys[i].user_consent; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); switch (ckis[i].key_alg) { case SC_ALGORITHM_RSA: prkey_info.usage = prkeys[i].usage_rsa; prkey_info.modulus_length= ckis[i].pubkey_len; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); break; case SC_ALGORITHM_EC: prkey_info.usage = prkeys[i].usage_ec; prkey_info.field_length = ckis[i].pubkey_len; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE added key_alg %2.2x prkey_obj.flags %8.8x", ckis[i].key_alg, prkey_obj.flags); r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key_alg %d", ckis[i].key_alg); r = 0; /* we just skip this one */ } if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int do_pin_authid(struct state *cur, int argc, char **argv) { sc_pkcs15_format_id(argv[0], &cur->pin->pin.auth_id); return 0; }
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) { /* The cert objects will return all the data */ const objdata objects[] = { {"1", "Card Capability Container", "2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0}, {"2", "Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0}, {"3", "Unsigned Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0}, {"4", "X.509 Certificate for PIV Authentication", "2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0}, {"5", "Card Holder Fingerprints", "2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE}, {"6", "Printed Information", "2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE}, {"7", "Card Holder Facial Image", "2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE}, {"8", "X.509 Certificate for Digital Signature", "2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0}, {"9", "X.509 Certificate for Key Management", "2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0}, {"10","X.509 Certificate for Card Authentication", "2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0}, {"11", "Security Object", "2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * NIST 800-73-1 is proposing to lift the restriction on * requering pin protected certs. Thus the default will be to * not require this. But there are a number of test cards * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE * to be set. */ /* certs will be pulled out from the cert objects */ cdata certs[] = { {"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0}, {"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0}, {"3", "Certificate for Key Management", 0, "0102cece", 0, 0}, {"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0}, {NULL, NULL, 0, NULL, 0, 0} }; const pindata pins[] = { { "1", "PIV Card Holder pin", "", 0x80, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { "2", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, /* there are some more key, but dont need for now */ /* The admin 9b might fall in here */ { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from pkcs15v1_1 Table 2 */ pubdata pubkeys[] = { { "1", "PIV AUTH pubkey", 0000, SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, "9A06", 0x9A, "1", 0, 0}, { "2", "SIGN pubkey", 0000, SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "9C06", 0x9C, "1", 0, 0}, { "3", "KEY MAN pubkey", 0000, SC_PKCS15_PRKEY_USAGE_WRAP, "9D06", 0x9D, "1", 0, 0}, { "4", "CARD AUTH pubkey", 0000, SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, "9E06", 0x9E, "0", 0, 0}, /* no pin, and avail in contactless */ { NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0} }; prdata prkeys[] = { { "1", "PIV AUTH key", 0000, SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, "", 0x9A, "1", 0}, { "2", "SIGN key", 0000, SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "", 0x9C, "1", 0}, { "3", "KEY MAN key", 0000, SC_PKCS15_PRKEY_USAGE_UNWRAP, "", 0x9D, "1", 0}, { "4", "CARD AUTH key", 0000, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, "", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */ { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; sc_card_t *card = p15card->card; sc_file_t *file_out = NULL; int exposed_cert[4] = {1, 0, 0, 0}; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; SC_FUNC_CALLED(card->ctx, 1); /* could read this off card if needed */ /* CSP does not like a - in the name */ p15card->label = strdup("PIV_II"); p15card->manufacturer_id = strdup(MANU_ID); /* * get serial number * We will use the FASC-N from the CHUID * Note we are not verifying CHUID, belongs to this card * but need serial number for Mac tokend */ sc_ctx_suppress_errors_on(card->ctx); r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); sc_ctx_suppress_errors_off(card->ctx); if (r < 0) { sc_debug(card->ctx,"sc_card_ctl rc=%d",r); p15card->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->serial_number = strdup(buf); } sc_debug(card->ctx, "PIV-II adding objects..."); /* set other objects */ for (i = 0; objects[i].label; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(objects[i].id, &obj_info.id); sc_format_path(objects[i].path, &obj_info.path); /* We could make sure the object is on the card */ /* But really don't need to do this now */ // sc_ctx_suppress_errors_on(card->ctx); // r = sc_select_file(card, &obj_info.path, NULL); // sc_ctx_suppress_errors_off(card->ctx); // if (r == SC_ERROR_FILE_NOT_FOUND) // continue; strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_format_oid(&obj_info.app_oid, objects[i].aoid); if (r != SC_SUCCESS) return r; if (objects[i].auth_id) sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id); strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); obj_obj.flags = objects[i].obj_flags; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); } /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. * If no cert, then see if pubkey (i.e. we are initilizing, * and the pubkey is in a file,) then add pubkey and privkey * If no cert and no pubkey, skip adding them. */ /* set certs */ sc_debug(card->ctx, "PIV-II adding certs..."); for (i = 0; certs[i].label; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); cert_obj.flags = certs[i].obj_flags; /* see if we have a cert */ /* use a &file_out so card-piv will read cert if present */ sc_ctx_suppress_errors_on(card->ctx); r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, &file_out); sc_ctx_suppress_errors_off(card->ctx); if (file_out) { sc_file_free(file_out); file_out = NULL; } if (r) { sc_debug(card->ctx, "No cert found,i=%d", i); continue; } certs[i].found = 1; /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0) { sc_debug(card->ctx, "Failed to read/parse the certificate r=%d",r); continue; } /* TODO support DSA keys */ if (cert_out->key.algorithm == SC_ALGORITHM_RSA) { /* save modulus_len in pub and priv */ pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8; prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8; } sc_pkcs15_free_certificate(cert_out); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_error(card->ctx, " Failed to add cert obj r=%d",r); continue; } } /* set pins */ sc_debug(card->ctx, "PIV-II adding pins..."); for (i = 0; pins[i].label; i++) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); } /* set public keys */ /* We may only need this during initialzation when genkey * gets the pubkey, but it can not be read from the card * at a later time. The piv-tool can stach in file */ sc_debug(card->ctx, "PIV-II adding pub keys..."); for (i = 0; pubkeys[i].label; i++) { struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_pubkey *p15_key; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id); pubkey_info.usage = pubkeys[i].usage; pubkey_info.native = 1; pubkey_info.key_reference = pubkeys[i].ref; sc_format_path(pubkeys[i].path, &pubkey_info.path); strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pubkey_obj.flags = pubkeys[i].obj_flags; if (pubkeys[i].auth_id) sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id); if (certs[i].found == 0) { /* no cert found */ sc_debug(card->ctx,"No cert for this pub key i=%d",i); /* TODO DSA */ pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA; pubkey_obj.data = &pubkey_info; sc_ctx_suppress_errors_on(card->ctx); r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key); sc_ctx_suppress_errors_off(card->ctx); pubkey_obj.data = NULL; sc_debug(card->ctx," READING PUB KEY r=%d",r); if (r < 0 ) { continue; } /* Only get here if no cert, and the card-piv.c found * there is a pub key file. This only happens when trying * initializing a card and have set env to point at file */ if (p15_key->algorithm == SC_ALGORITHM_RSA) { /* save modulus_len in pub and priv */ pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8; prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8; pubkeys[i].found = 1; } } pubkey_info.modulus_length = pubkeys[i].modulus_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); /* TODO DSA keys */ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); /* should not fail */ pubkeys[i].found = 1; } /* set private keys */ sc_debug(card->ctx, "PIV-II adding private keys..."); for (i = 0; prkeys[i].label; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); if (certs[i].found == 0 && pubkeys[i].found == 0) continue; /* i.e. no cert or pubkey */ sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; /* The cert or pubkey should have filled modulus_len */ /* TODO DSA keys */ sc_format_path(prkeys[i].path, &prkey_info.path); strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); prkey_obj.flags = prkeys[i].obj_flags; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); } SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); }
static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) { static const pindata pins[] = { { "1", "PIN", "", 0x00, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_INITIALIZED , -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* oid for key usage */ static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }}; unsigned int usage; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from certificate key usage extension. */ int r, i; sc_card_t *card = p15card->card; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; int count; char *token_name = NULL; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); memset(&serial, 0, sizeof(serial)); /* could read this off card if needed */ p15card->tokeninfo->label = strdup(cac_get_name(card->type)); p15card->tokeninfo->manufacturer_id = strdup(MANU_ID); /* * get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r < 0) { sc_log(card->ctx, "sc_card_ctl rc=%d",r); p15card->tokeninfo->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->tokeninfo->serial_number = strdup(buf); } /* set pins */ /* TODO we should not create PIN objects if it is not initialized * (opensc-tool -s 0020000000 returns 0x6A 0x88) */ sc_log(card->ctx, "CAC adding pins..."); for (i = 0; pins[i].id; i++) { struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; const char * label; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.attrs.pin.reference = pins[i].ref; pin_info.attrs.pin.flags = pins[i].flags; pin_info.attrs.pin.type = pins[i].type; pin_info.attrs.pin.min_length = pins[i].minlen; pin_info.attrs.pin.stored_length = pins[i].storedlen; pin_info.attrs.pin.max_length = pins[i].maxlen; pin_info.attrs.pin.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; label = pins[i].label; sc_log(card->ctx, "CAC Adding pin %d label=%s",i, label); strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; /* get the ACA path in case it needs to be selected before PIN verify */ r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path); if (r < 0) { LOG_FUNC_RETURN(card->ctx, r); } r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); } /* set other objects */ r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not initiate generic objects."); for (i = 0; i < count; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_GENERIC_OBJECT, &obj_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); memset(&obj_obj, 0, sizeof(obj_obj)); memcpy(obj_obj.label, obj_info.app_label, sizeof(obj_obj.label)); r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); } r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not finalize generic objects."); /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. */ sc_log(card->ctx, "CAC adding certs, pub and priv keys..."); r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not initiate cert objects."); for (i = 0; i < count; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object cert_obj; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_object prkey_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out = NULL; r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, &obj_info); LOG_TEST_RET(card->ctx, r, "Can not get next object"); memset(&cert_info, 0, sizeof(cert_info)); memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&prkey_info, 0, sizeof(prkey_info)); memset(&cert_obj, 0, sizeof(cert_obj)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); memset(&prkey_obj, 0, sizeof(prkey_obj)); cert_info.id = obj_info.id; pubkey_info.id = obj_info.id; prkey_info.id = obj_info.id; cert_info.path = obj_info.path; prkey_info.path = obj_info.path; /* Add 0x3f00 to the front of prkey_info.path to make sc_key_file happy */ /* only do this if our path.len is 1 or 2 */ if (prkey_info.path.len && prkey_info.path.len <= 2) { prkey_info.path.value[2] = prkey_info.path.value[0]; prkey_info.path.value[3] = prkey_info.path.value[1]; prkey_info.path.value[0] = 0x3f; prkey_info.path.value[1] = 0x00; prkey_info.path.len += 2; } pubkey_info.native = 1; pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; prkey_info.native = 1; memcpy(cert_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); memcpy(pubkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); memcpy(prkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; sc_pkcs15_format_id(pins[0].id, &prkey_obj.auth_id); r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len); if (r) { sc_log(card->ctx, "No cert found,i=%d", i); continue; } cert_info.path.count = cert_der.len; sc_log(card->ctx, "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n", cert_der.len, cert_info.path.count, r); sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len); /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0 || cert_out->key == NULL) { sc_log(card->ctx, "Failed to read/parse the certificate r=%d",r); if (cert_out != NULL) sc_pkcs15_free_certificate(cert_out); continue; } r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_log(card->ctx, " Failed to add cert obj r=%d",r); sc_pkcs15_free_certificate(cert_out); continue; } /* set the token name to the name of the CN of the first certificate */ if (!token_name) { u8 * cn_name = NULL; size_t cn_len = 0; static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject, cert_out->subject_len, &cn_oid, &cn_name, &cn_len); if (r == SC_SUCCESS) { token_name = malloc (cn_len+1); if (!token_name) { free(cn_name); r = SC_ERROR_OUT_OF_MEMORY; goto fail; } memcpy(token_name, cn_name, cn_len); free(cn_name); token_name[cn_len] = 0; free(p15card->tokeninfo->label); p15card->tokeninfo->label = token_name; } } r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); if (r < 0) goto fail; pubkey_obj.emulated = cert_out->key; r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); if (r < 0) { usage = 0xd9ULL; /* basic default usage */ } cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", sc_dump_hex(cert_info.id.value, cert_info.id.len), usage, pubkey_info.usage, prkey_info.usage); if (cert_out->key->algorithm != SC_ALGORITHM_RSA) { sc_log(card->ctx, "unsupported key.algorithm %d", cert_out->key->algorithm); sc_pkcs15_free_certificate(cert_out); continue; } else { pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); if (r < 0) goto fail; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); } cert_out->key = NULL; fail: sc_pkcs15_free_certificate(cert_out); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); /* should not fail */ } r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not finalize cert objects."); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) { const char *fn_name = "sc_pkcs15emu_gemsafe_init"; int r, i; int key_ref = 0x03; struct sc_path path; struct sc_file *file = NULL; struct sc_card *card = p15card->card; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; char * endptr; float version=0.0; sc_debug(p15card->card->ctx, "%s: Setting pkcs15 parameters\n", fn_name); if (p15card->label) free(p15card->label); p15card->label = malloc(strlen(APPLET_NAME) + 1); if (!p15card->label) return SC_ERROR_INTERNAL; strcpy(p15card->label, APPLET_NAME); if (p15card->serial_number) free(p15card->serial_number); p15card->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1); if (!p15card->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->serial_number, DRIVER_SERIAL_NUMBER); /* the GemSAFE applet version number */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03); apdu.cla = 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); /* Manual says Le=0x05, but should be 0x08 to return full version numer */ apdu.le = 0x08; apdu.lc = 0; apdu.datalen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) return SC_ERROR_INTERNAL; if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; endptr = (char *)(apdu.resp + apdu.resplen); version = strtod( (const char *)(apdu.resp + 4), &endptr); sc_debug(p15card->card->ctx, "%s: version (float): %f, version (int): %d\n", fn_name, version, (int)version); p15card->version = (int)version; /* the manufacturer ID, in this case GemPlus */ if (p15card->manufacturer_id) free(p15card->manufacturer_id); p15card->manufacturer_id = malloc(strlen(MANU_ID) + 1); if (!p15card->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->manufacturer_id, MANU_ID); /* set certs */ sc_debug(p15card->card->ctx, "%s: Setting certificate\n", fn_name); for (i = 0; gemsafe_cert[i].label; i++) { struct sc_pkcs15_id p15Id; sc_format_path(gemsafe_cert[i].path, &path); if (!gemsafe_get_cert_len(card, &path, &key_ref)) /* skip errors */ continue; sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id); sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, gemsafe_cert[i].authority, &path, &p15Id, gemsafe_cert[i].label, gemsafe_cert[i].obj_flags); } /* set gemsafe_pin */ sc_debug(p15card->card->ctx, "%s: Setting PIN\n", fn_name); for (i = 0; gemsafe_pin[i].label; i++) { struct sc_pkcs15_id p15Id; sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id); sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label, &path, gemsafe_pin[i].ref, gemsafe_pin[i].type, gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen, gemsafe_pin[i].flags, gemsafe_pin[i].tries_left, gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags); } /* set private keys */ sc_debug(p15card->card->ctx, "%s: Setting private key\n", fn_name); for (i = 0; gemsafe_prkeys[i].label; i++) { struct sc_pkcs15_id p15Id, authId, *pauthId; sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id); if (gemsafe_prkeys[i].auth_id) { sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId); pauthId = &authId; } else pauthId = NULL; /* * the key ref may be different for different sites * by adding flags=n where the low order 4 bits can be * the key ref we can force it. */ if ( p15card->card->flags & 0x0F) { key_ref = p15card->card->flags & 0x0F; sc_debug(p15card->card->ctx, "Overriding key_ref with %d\n", key_ref); } sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label, SC_PKCS15_TYPE_PRKEY_RSA, gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage, &path, key_ref, pauthId, gemsafe_prkeys[i].obj_flags); } /* select the application DF */ sc_debug(p15card->card->ctx,"%s: Selecting application DF\n", fn_name); sc_format_path("3F001600", &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; }