static int starcert_detect_card(sc_pkcs15_card_t *p15card) { int r; u8 buf[128]; sc_path_t path; sc_card_t *card = p15card->card; /* check if we have the correct card OS */ if (strcmp(card->name, "STARCOS SPK 2.3")) return SC_ERROR_WRONG_CARD; /* read EF_Info file */ sc_format_path("3F00FE13", &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; r = sc_read_binary(card, 0, buf, 64, 0); if (r != 64) return SC_ERROR_WRONG_CARD; if (memcmp(buf + 24, STARCERT, strlen(STARCERT))) return SC_ERROR_WRONG_CARD; return SC_SUCCESS; }
static int gpk_read_rsa_key(sc_card_t *card, struct sc_pkcs15_pubkey_rsa *rsa) { int n, r; /* Read modulus and exponent */ for (n = 2; ; n++) { sc_pkcs15_bignum_t *bn; u8 buffer[256]; size_t m; sc_ctx_suppress_errors_on(card->ctx); r = sc_read_record(card, n, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); sc_ctx_suppress_errors_off(card->ctx); if (r < 1) break; if (buffer[0] == 0x01) bn = &rsa->modulus; else if (buffer[0] == 0x07) bn = &rsa->exponent; else continue; bn->len = r - 1; bn->data = (u8 *) malloc(bn->len); for (m = 0; m < bn->len; m++) bn->data[m] = buffer[bn->len - m]; } return 0; }
static int atrust_acos_logout(struct sc_card *card) { int r; struct sc_apdu apdu; const u8 mf_buf[2] = {0x3f, 0x00}; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x0C); apdu.le = 0; apdu.lc = 2; apdu.data = mf_buf; apdu.datalen = 2; apdu.resplen = 0; sc_ctx_suppress_errors_on(card->ctx); r = sc_transmit_apdu(card, &apdu); sc_ctx_suppress_errors_off(card->ctx); SC_TEST_RET(card->ctx, r, "APDU re-transmit failed"); if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85) /* the only possible reason for this error here is, afaik, * that no MF exists, but then there's no need to logout * => return SC_SUCCESS */ return SC_SUCCESS; return sc_check_sw(card, apdu.sw1, apdu.sw2); }
/* * Create the PK file * XXX: Handle the UPDATE ACL = NEVER case just like for EFsc files */ static int gpk_pkfile_create(sc_profile_t *profile, sc_card_t *card, sc_file_t *file) { struct sc_file *found = NULL; int r; sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &file->path, &found); sc_ctx_suppress_errors_off(card->ctx); if (r == SC_ERROR_FILE_NOT_FOUND) { r = sc_pkcs15init_create_file(profile, card, file); if (r >= 0) r = sc_select_file(card, &file->path, &found); } else { /* XXX: make sure the file has correct type and size? */ } if (r >= 0) r = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_UPDATE); if (found) sc_file_free(found); return r; }
static int dump_unusedspace(void) { u8 *buf = NULL; size_t buf_len; sc_path_t path; sc_pkcs15_unusedspace_t *us; int r; if (p15card->file_unusedspace != NULL) path = p15card->file_unusedspace->path; else { path = p15card->file_app->path; sc_append_path_id(&path, (const u8 *) "\x50\x33", 2); } path.count = -1; sc_ctx_suppress_errors_on(p15card->card->ctx); r = sc_pkcs15_read_file(p15card, &path, &buf, &buf_len, NULL); sc_ctx_suppress_errors_off(p15card->card->ctx); if (r < 0) { if (r == SC_ERROR_FILE_NOT_FOUND) { printf("\nNo EF(UnusedSpace) file\n"); r = 0; } else printf("\nError reading file \"%s\": %s\n", sc_print_path(&path), sc_strerror(r)); goto err; } r = sc_pkcs15_parse_unusedspace(buf, buf_len, p15card); if (r != 0) { printf("\nError parsing EF(UnusedSpace): %s\n", sc_strerror(r)); goto err; } if (p15card->unusedspace_list == NULL) printf("\nEF(UnusedSpace) file is empty\n"); else { printf("\nContents of EF(UnusedSpace):\n"); for (us = p15card->unusedspace_list; us != NULL; us = us->next) printf(" - path=%s, index=%d, length=%d -- auth_id = %s\n", sc_print_path(&us->path), us->path.index, us->path.count, us->auth_id.len == 0 ? "<empty>" : sc_pkcs15_print_id(&us->auth_id)); } err: if (buf != NULL) free(buf); return r; }
static int acos_detect_card(sc_pkcs15_card_t *p15card) { int r; u8 buf[128]; sc_path_t path; sc_card_t *card = p15card->card; /* check if we have the correct card OS */ if (strncmp(card->name, "A-TRUST ACOS", strlen("A-TRUST ACOS"))) return SC_ERROR_WRONG_CARD; /* read EF_CIN_CSN file */ sc_format_path("DF71D001", &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; r = sc_read_binary(card, 0, buf, 8, 0); if (r != 8) return SC_ERROR_WRONG_CARD; 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_pkcs15_bind_internal(sc_pkcs15_card_t *p15card) { unsigned char *buf = NULL; int err, ok = 0; size_t len; sc_path_t tmppath; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; sc_pkcs15_tokeninfo_t tokeninfo; if (ctx->debug > 4) sc_debug(ctx, "trying normal pkcs15 processing\n"); /* Enumerate apps now */ if (card->app_count < 0) { err = sc_enum_apps(card); if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) { sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err)); goto end; } } p15card->file_app = sc_file_new(); if (p15card->file_app == NULL) { err = SC_ERROR_OUT_OF_MEMORY; goto end; } sc_format_path("3F005015", &p15card->file_app->path); if (card->app_count > 0) { const sc_app_info_t *info; info = sc_find_pkcs15_app(card); if (info != NULL) { if (info->path.len) p15card->file_app->path = info->path; if (info->ddo != NULL) parse_ddo(p15card, info->ddo, info->ddo_len); } } /* Check if pkcs15 directory exists */ sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &p15card->file_app->path, NULL); #if 1 /* If the above test failed on cards without EF(DIR), * try to continue read ODF from 3F005031. -aet */ if ((err == SC_ERROR_FILE_NOT_FOUND) && (card->app_count < 1)) { sc_format_path("3F00", &p15card->file_app->path); err = SC_NO_ERROR; } #endif sc_ctx_suppress_errors_off(card->ctx); if (err < 0) goto end; if (p15card->file_odf == NULL) { /* check if an ODF is present; suppress errors as we * don't know yet whether we have a pkcs15 card */ tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2); sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &tmppath, &p15card->file_odf); sc_ctx_suppress_errors_off(card->ctx); } else { tmppath = p15card->file_odf->path; sc_file_free(p15card->file_odf); p15card->file_odf = NULL; err = sc_select_file(card, &tmppath, &p15card->file_odf); } if (err != SC_SUCCESS) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &tmppath); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(ctx, "EF(ODF) not found in '%s'\n", pbuf); goto end; } if ((len = p15card->file_odf->size) == 0) { sc_error(card->ctx, "EF(ODF) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err < 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } len = err; if (parse_odf(buf, len, p15card)) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; sc_error(card->ctx, "Unable to parse ODF\n"); goto end; } free(buf); buf = NULL; if (card->ctx->debug) { sc_pkcs15_df_t *df; sc_debug(card->ctx, "The following DFs were found:\n"); for (df = p15card->df_list; df; df = df->next) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &df->path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(card->ctx, " DF type %u, path %s, index %u, count %d\n", df->type, pbuf, df->path.index, df->path.count); } } if (p15card->file_tokeninfo == NULL) { tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x32", 2); } else { tmppath = p15card->file_tokeninfo->path; sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo); if (err) goto end; if ((len = p15card->file_tokeninfo->size) == 0) { sc_error(card->ctx, "EF(TokenInfo) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err <= 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } memset(&tokeninfo, 0, sizeof(tokeninfo)); err = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t)err); if (err != SC_SUCCESS) goto end; p15card->version = tokeninfo.version; p15card->label = tokeninfo.label; p15card->serial_number = tokeninfo.serial_number; p15card->manufacturer_id = tokeninfo.manufacturer_id; p15card->last_update = tokeninfo.last_update; p15card->flags = tokeninfo.flags; p15card->preferred_language = tokeninfo.preferred_language; p15card->seInfo = tokeninfo.seInfo; p15card->num_seInfo = tokeninfo.num_seInfo; /* for cardos cards initialized by Siemens: sign with decrypt */ if (strcmp(p15card->card->driver->short_name,"cardos") == 0 && ( strcmp(p15card->manufacturer_id,"Siemens AG (C)") == 0 || strcmp(p15card->manufacturer_id,"Prime") == 0 )) p15card->flags |= SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; ok = 1; end: if(buf != NULL) free(buf); if (!ok) { sc_pkcs15_card_clear(p15card); return err; } return SC_SUCCESS; }
/** atrust_acos_set_security_env * sets the security enviroment * \param card pointer to the sc_card object * \param env pointer to a sc_security_env object * \param se_num not used here * \return SC_SUCCESS on success or an error code * * This function sets the security enviroment (using the * command MANAGE SECURITY ENVIROMENT). In case a COMPUTE SIGNATURE * operation is requested , this function tries to detect whether * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE must be used for signature * calculation. */ static int atrust_acos_set_security_env(struct sc_card *card, const struct sc_security_env *env, int se_num) { u8 *p, *pp, keyID; int r, operation = env->operation; struct sc_apdu apdu; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; atrust_acos_ex_data *ex_data = (atrust_acos_ex_data *)card->drv_data; p = sbuf; keyID = env->key_ref[0]; /* copy key reference, if present */ if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) *p++ = 0x83; else *p++ = 0x84; *p++ = env->key_ref_len; memcpy(p, env->key_ref, env->key_ref_len); p += env->key_ref_len; } pp = p; if (operation == SC_SEC_OPERATION_DECIPHER){ if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { *p++ = 0x80; *p++ = 0x01; *p++ = 0x02; } else return SC_ERROR_INVALID_ARGUMENTS; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xb8); apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); return SC_SUCCESS; } /* try COMPUTE SIGNATURE */ if (operation == SC_SEC_OPERATION_SIGN && ( env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 || env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)) { if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) { *p++ = 0x80; *p++ = 0x01; *p++ = env->algorithm_ref & 0xFF; } else if (env->flags & SC_SEC_ENV_ALG_PRESENT && env->algorithm == SC_ALGORITHM_RSA) { /* set the method to use based on the algorithm_flags */ *p++ = 0x80; *p++ = 0x01; if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) *p++ = 0x12; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) *p++ = 0x22; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5) *p++ = 0x32; else { /* can't use COMPUTE SIGNATURE => * try INTERNAL AUTHENTICATE */ p = pp; operation = SC_SEC_OPERATION_AUTHENTICATE; goto try_authenticate; } } else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796) { if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) *p++ = 0x11; else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) *p++ = 0x21; else return SC_ERROR_INVALID_ARGUMENTS; } else return SC_ERROR_INVALID_ARGUMENTS; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xb6); apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; apdu.le = 0; /* suppress errors, as don't know whether to use * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */ sc_ctx_suppress_errors_on(card->ctx); r = sc_transmit_apdu(card, &apdu); sc_ctx_suppress_errors_off(card->ctx); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { ex_data->fix_digestInfo = 0; ex_data->sec_ops = SC_SEC_OPERATION_SIGN; return SC_SUCCESS; } /* reset pointer */ p = pp; /* doesn't work => try next op */ operation = SC_SEC_OPERATION_AUTHENTICATE; } try_authenticate: /* try INTERNAL AUTHENTICATE */ if (operation == SC_SEC_OPERATION_AUTHENTICATE && env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { *p++ = 0x80; *p++ = 0x01; *p++ = 0x01; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xa4); apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2)); ex_data->fix_digestInfo = env->algorithm_flags; ex_data->sec_ops = SC_SEC_OPERATION_AUTHENTICATE; return SC_SUCCESS; } return SC_ERROR_INVALID_ARGUMENTS; }
static int gpk_pkfile_update_public(struct sc_profile *profile, sc_card_t *card, struct pkpart *part) { struct pkcomp *pe; unsigned char buffer[256]; unsigned int m, n, tag; int r = 0, found; if (card->ctx->debug > 1) sc_debug(card->ctx, "Updating public key elements\n"); /* If we've been given a key with public parts, write them now */ for (n = 2; n < 256; n++) { sc_ctx_suppress_errors_on(card->ctx); r = sc_read_record(card, n, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); sc_ctx_suppress_errors_off(card->ctx); if (r < 0) { r = 0; break; } /* Check for bad record */ if (r < 2) { sc_error(card->ctx, "key file format error: " "record %u too small (%u bytes)\n", n, r); return SC_ERROR_OBJECT_NOT_VALID; } tag = buffer[0]; for (m = 0, found = 0; m < part->count; m++) { pe = part->components + m; if (pe->tag == tag) { r = sc_update_record(card, n, pe->data, pe->size, SC_RECORD_BY_REC_NR); if (r < 0) return r; pe->tag = 0; /* mark as stored */ found++; break; } } if (!found && card->ctx->debug) sc_debug(card->ctx, "GPK unknown PK tag %u\n", tag); } /* Write all remaining elements */ for (m = 0; r >= 0 && m < part->count; m++) { pe = part->components + m; if (pe->tag != 0) r = sc_append_record(card, pe->data, pe->size, 0); } return r; }
/* * Set up the public key record for a signature only public key */ static int gpk_pkfile_init_public(sc_profile_t *profile, sc_card_t *card, sc_file_t *file, unsigned int algo, unsigned int bits, unsigned int usage) { const sc_acl_entry_t *acl; sc_file_t *tmp = NULL; u8 sysrec[7], buffer[256]; unsigned int n, npins; int r, card_type; /* Find out what sort of GPK we're using */ if ((r = sc_card_ctl(card, SC_CARDCTL_GPK_VARIANT, &card_type)) < 0) return r; /* Set up the system record */ memset(sysrec, 0, sizeof(sysrec)); /* Mapping keyUsage to sysrec[2]: * 0x00 sign & unwrap * 0x10 sign only * 0x20 unwrap only * 0x30 CA key * * We start with a value of 0x30. * If the key allows decryption, clear the sign only bit. * Likewise, if it allows signing, clear the unwrap only bit. */ sysrec[2] = 0x30; if (usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)) sysrec[2] &= ~0x10; if (usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)) sysrec[2] &= ~0x20; if (sysrec[2] == 0x30) { sc_error(card->ctx, "Key usage should specify at least one of sign or decipher"); return SC_ERROR_INVALID_ARGUMENTS; } /* Set the key size and algorithm */ if ((r = gpk_pkfile_keybits(bits, &sysrec[1])) < 0 || (r = gpk_pkfile_keyalgo(algo, &sysrec[5])) < 0) return r; /* Set PIN protection if requested. * As the crypto ACLs are stored inside the file, * we have to get them from the profile here. */ r = sc_profile_get_file_by_path(profile, &file->path, &tmp); if (r < 0) return r; /* Fix up PIN references in file ACL */ if ((r = sc_pkcs15init_fixup_file(profile, tmp)) < 0) goto out; acl = sc_file_get_acl_entry(tmp, SC_AC_OP_CRYPTO); for (npins = 0; acl; acl = acl->next) { if (acl->method == SC_AC_NONE || acl->method == SC_AC_NEVER) continue; if (acl->method != SC_AC_CHV) { sc_error(card->ctx, "Authentication method not " "supported for private key files.\n"); r = SC_ERROR_NOT_SUPPORTED; goto out; } if (++npins >= 2) { sc_error(card->ctx, "Too many pins for PrKEY file!\n"); r = SC_ERROR_NOT_SUPPORTED; goto out; } sysrec[2] += 0x40; sysrec[3] >>= 4; sysrec[3] |= acl->key_ref << 4; } /* compute checksum - yet another slightly different * checksum algorithm courtesy of Gemplus */ if (card_type >= SC_CARD_TYPE_GPK_GPK8000) { /* This is according to the gpk reference manual */ sysrec[6] = 0xA5; } else { /* And this is what you have to use for the GPK4000 */ sysrec[6] = 0xFF; } for (n = 0; n < 6; n++) sysrec[6] ^= sysrec[n]; sc_ctx_suppress_errors_on(card->ctx); r = sc_read_record(card, 1, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); sc_ctx_suppress_errors_off(card->ctx); if (r >= 0) { if (r != 7 || buffer[0] != 0) { sc_error(card->ctx, "first record of public key file is not Lsys0"); return SC_ERROR_OBJECT_NOT_VALID; } r = sc_update_record(card, 1, sysrec, sizeof(sysrec), SC_RECORD_BY_REC_NR); } else { r = sc_append_record(card, sysrec, sizeof(sysrec), 0); } out: if (tmp) sc_file_free(tmp); return r; }
int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opts) { static const struct { const char *card, *manufacturer; } cardlist[]= { {"Netkey E4 Card", "TeleSec GmbH"}, {"SignTrust Card", "Deutsche Post"}, {"DATEV classic", "DATEV"}, {"Smartkey Card TypA", "Kobil GmbH"}, {"Smartkey Card TypB", "Kobil GmbH"}, {"Chipkarte JLU Giessen", "Kobil GmbH"} }; static struct { int flags; const int type, id, writable; const char *path; const char *label; } certlist[]= { {0, 1, 0x45, 0, "DF01C000", "Telesec Signatur Zertifikat"}, {3, 1, 0x45, 1, "DF014331", "Signatur Zertifikat 1"}, {3, 1, 0x45, 1, "DF014332", "Signatur Zertifikat 2"}, {1, 1, 0x46, 0, "DF01C100", "Telesec Authentifizierungs Zertifikat"}, {3, 1, 0x46, 1, "DF014371", "Authentifizierungs Zertifikat 1"}, {3, 1, 0x46, 1, "DF014372", "Authentifizierungs Zertifikat 2"}, {1, 1, 0x47, 0, "DF01C200", "Telesec Verschluesselungs Zertifikat"}, {3, 1, 0x47, 1, "DF0143B1", "Verschluesselungs Zertifikat 1"}, {3, 1, 0x47, 1, "DF0143B2", "Verschluesselungs Zertifikat 2"}, {1, 1, 0x48, 1, "DF06C000", "SigG Zertifikat 1"}, {1, 1, 0x48, 1, "DF064331", "SigG Zertifikat 2"}, {1, 1, 0x48, 1, "DF064332", "SigG Zertifikat 3"}, {1, 1, 0x49, 1, "41014352", "W2K Logon Zertifikat"}, {0, 2, 0x45, 1, "8000DF01C000", "SignTrust Signatur Zertifikat"}, {1, 2, 0x46, 1, "800082008220", "SignTrust Verschluesselungs Zertifikat"}, {1, 2, 0x47, 1, "800083008320", "SignTrust Authentifizierungs Zertifikat"}, {0, 3, 0x45, 0, "3000C500", "DATEV Signatur Zertifikat"}, {1, 3, 0x46, 0, "DF02C200", "DATEV Verschluesselungs Zertifikat"}, {1, 3, 0x47, 0, "DF02C500", "DATEV Authentifizierungs Zertifikat"}, {0, 4, 0x45, 1, "41004352", "Smartkey Zertifikat 1"}, {0, 4, 0x46, 1, "41004353", "Smartkey Zertifikat 2"}, {0, 5, 0x45, 1, "41014352", "Smartkey Zertifikat 1"}, {0, 5, 0x46, 1, "41014353", "Smartkey Zertifikat 2"}, {0, 6, 0x45, 1, "41004352", "UniCard Giessen Zertifikat"}, {0, 0, 0, 0, NULL, NULL} }; static const struct { int type, id, auth_id; const char *path; unsigned char key_reference; const char *label; } keylist[]= { {1, 0x45, 4, "DF015331", 0x80, "Signatur Schluessel"}, {1, 0x46, 3, "DF015371", 0x82, "Authentifizierungs Schluessel"}, {1, 0x47, 3, "DF0153B1", 0x81, "Verschluesselungs Schluessel"}, {1, 0x48, 5, "DF065331", 0x80, "SigG Schluessel"}, {1, 0x49, 1, "41015103", 0x83, "W2K Logon Schluessel"}, {2, 0x45, 1, "8000DF015331", 0x80, "Signatur Schluessel"}, {2, 0x46, 2, "800082008210", 0x80, "Verschluesselungs Schluessel"}, {2, 0x47, 3, "800083008310", 0x80, "Authentifizierungs Schluessel"}, {3, 0x45, 1, "30005371", 0x82, "Signatur Schluessel"}, {3, 0x46, 1, "DF0253B1", 0x81, "Verschluesselungs Schluessel"}, {3, 0x47, 1, "DF025371", 0x82, "Authentifizierung Schluessel"}, {4, 0x45, 1, "41005103", 0x83, "Smartkey Schluessel 1"}, {4, 0x46, 1, "41005104", 0x84, "Smartkey Schluessel 2"}, {5, 0x45, 1, "41015103", 0x83, "Smartkey Schluessel 1"}, {5, 0x46, 1, "41015104", 0x84, "Smartkey Schluessel 2"}, {6, 0x45, 1, "3F004100", 0x83, "UniCard Giessen Schluessel"}, {0, 0, 0, NULL, 0, NULL} }; static const struct { int type, id, auth_id, min_length; unsigned char reference; const char *path; const char *label; int flags; } pinlist[]= { { 1, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 1, 2, 0, 8, 0x01, "5001", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 1, 3, 1, 6, 0x80, "DF015080", "Netkey PIN0", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 1, 4, 1, 6, 0x81, "DF015081", "Netkey PIN1", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 1, 5, 0, 6, 0x81, "DF065081", "SigG PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 1, 0, 6, 0x81, "8000DF010000", "Signatur PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 2, 0, 6, 0x81, "800082000040", "Verschluesselungs PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 3, 0, 6, 0x81, "800083000040", "Authentifizierungs PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 3, 1, 0, 6, 0x01, "5001", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 4, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 4, 2, 0, 8, 0x01, "5008", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 5, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 5, 2, 0, 8, 0x01, "5008", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 6, 1, 0, 6, 0x00, "4100", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED }, {0, 0, 0, 0, 0, NULL, NULL, 0} }; sc_card_t *card = p15card->card; sc_context_t *ctx = p15card->card->ctx; sc_path_t path; sc_file_t *file; sc_serial_number_t serialnr; char serial[30]; int i, j, found, r, usage, cardtype; /* check if we have the correct card OS unless SC_PKCS15EMU_FLAGS_NO_CHECK */ i=(opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK); if (!i && strcmp(card->name, "TCOS")) return SC_ERROR_WRONG_CARD; /* get the card serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr); if (r < 0) { sc_debug(ctx, "unable to get ICCSN\n"); r = SC_ERROR_WRONG_CARD; goto failed; } sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0); serial[19] = '\0'; set_string(&p15card->serial_number, serial); /* detect cardtype and certificates */ cardtype=0; for(i=0; certlist[i].id; ++i) { if(cardtype && certlist[i].type!=cardtype) continue; if(!cardtype && (certlist[i].flags&1)) continue; if(!cardtype && ctx->debug>=2) sc_debug(ctx, "Testing %s\n",cardlist[certlist[i].type-1].card); if(ctx->debug>=2) sc_debug(ctx, "Testing Cert %s, %s\n", certlist[i].path, certlist[i].label); sc_format_path(certlist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(ctx); if(r<0) continue; cardtype=certlist[i].type; certlist[i].flags |= 4; } if(ctx->debug >= 1) sc_debug(ctx, "Cardtype=%d, %s\n", cardtype, cardlist[cardtype-1].card); if(cardtype<1 || cardtype>(int)(sizeof(cardlist)/sizeof(cardlist[0]))) { r = SC_ERROR_WRONG_CARD; goto failed; } set_string(&p15card->label, cardlist[cardtype-1].card); set_string(&p15card->manufacturer_id, cardlist[cardtype-1].manufacturer); /* insert certificates */ for(found=1; found;) { for(i=found=0; certlist[i].id && !found; ++i) if(certlist[i].flags&4) found=certlist[i].id; for(j=0; j<2; ++j) for(i=0; certlist[i].id; ++i) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; unsigned char cert[20]; if(certlist[i].id!=found) continue; if((certlist[i].flags&2) == 2*j) continue; if(!(certlist[i].flags&4)) continue; certlist[i].flags-=4; sc_format_path(certlist[i].path, &path); if(sc_select_file(card, &path, NULL)<0) continue; /* read first 20 bytes of certificate, first two bytes * must be 0x30 0x82, otherwise this is an empty cert-file */ r = sc_read_binary(card, 0, cert, sizeof(cert), 0); if(r<0 || cert[0]!=0x30 || cert[1]!=0x82) continue; if(ctx->debug>=1) { sc_debug(ctx,"Cert %02X %s, %s\n",certlist[i].id,certlist[i].path,certlist[i].label); } /* Telesec-Certificates are prefixed by an OID, * for example 06:03:55:04:24. so use appropriate offset */ if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82) { path.index=6+cert[5]; path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4; } else { path.index=0; path.count=(cert[2]<<8) + cert[3] + 4; } memset(&cert_info, 0, sizeof(cert_info)); cert_info.id.len = 1; cert_info.id.value[0] = certlist[i].id; cert_info.authority = 0; cert_info.path = path; memset(&cert_obj, 0, sizeof(cert_obj)); strlcpy(cert_obj.label, certlist[i].label, sizeof(cert_obj.label)); cert_obj.flags = certlist[i].writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", certlist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } } for(i=0; keylist[i].id; ++i) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if(keylist[i].type!=cardtype) continue; sc_format_path(keylist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; if(ctx->debug >= 1) sc_debug(ctx,"Key %02X %s, %s\n",keylist[i].id,keylist[i].path,keylist[i].label); usage = SC_PKCS15_PRKEY_USAGE_SIGN; if (file->prop_attr[1] & 0x04) usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; if (file->prop_attr[1] & 0x08) usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; memset(&prkey_info, 0, sizeof(prkey_info)); prkey_info.id.len = 1; prkey_info.id.value[0] = keylist[i].id; prkey_info.usage = usage; prkey_info.native = 1; prkey_info.key_reference = keylist[i].key_reference; prkey_info.modulus_length = 1024; sc_format_path(keylist[i].path, &prkey_info.path); memset(&prkey_obj, 0, sizeof(prkey_obj)); strlcpy(prkey_obj.label, keylist[i].label, sizeof(prkey_obj.label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = keylist[i].auth_id; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); sc_file_free(file); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", keylist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } for(i=0; pinlist[i].id; ++i) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; if(pinlist[i].type && pinlist[i].type!=cardtype) continue; sc_format_path(pinlist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; if(ctx->debug >= 1) sc_debug(ctx, "PIN %02X %s, %s\n", pinlist[i].id,pinlist[i].path,pinlist[i].label); memset(&pin_info, 0, sizeof(pin_info)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = pinlist[i].id; pin_info.reference = pinlist[i].reference; pin_info.flags = pinlist[i].flags; pin_info.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.min_length = pinlist[i].min_length; pin_info.stored_length = 16; pin_info.max_length = 16; pin_info.pad_char = '\0'; pin_info.tries_left = file->prop_attr[3]; sc_format_path(pinlist[i].path, &pin_info.path); memset(&pin_obj, 0, sizeof(pin_obj)); strlcpy(pin_obj.label, pinlist[i].label, sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; pin_obj.auth_id.len = pinlist[i].auth_id ? 0 : 1; pin_obj.auth_id.value[0] = pinlist[i].auth_id; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); sc_file_free(file); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_pin_obj(%s) failed\n", pinlist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); failed: if (r < 0) sc_debug(ctx, "PKCS15-emulation for TCOS based preformatted failed: %s\n", sc_strerror(r)); return r; }
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_atrust_acos_init(sc_pkcs15_card_t *p15card) { const cdata certs[] = { {"C.CH.EKEY", 0, "DF71C001","1", 0},/* Decryption Certificate */ #if 0 {"C.CH.DS", 0, "DF70C002","2", 0},/* Signature Certificate */ #endif {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 }, #if 0 { "02", "PIN.SIG", "3F00DF70", 0x81, /* Signature PIN */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 6, 6, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, { "03", "PIN.INF", "3F00DF71", 0x83, /* Infobox 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 }, #endif { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const prdata prkeys[] = { { "1", "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}, #if 0 { "2", "SK.CH.DS", 192, SC_PKCS15_PRKEY_USAGE_SIGN, "", /* do not specify file here to prevent reset of security state */ 0x88, "02", SC_PKCS15_CO_FLAG_PRIVATE}, #endif { 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); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); 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->serial_number) free(p15card->serial_number); p15card->serial_number = (char *) malloc(strlen(buf2) + 1); if (!p15card->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->serial_number, buf2); /* the TokenInfo version number */ p15card->version = 0; /* manufacturer ID */ 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); /* card label */ if (p15card->label) free(p15card->label); p15card->label = (char *) malloc(strlen(CARD_LABEL) + 1); if (!p15card->label) return SC_ERROR_INTERNAL; strcpy(p15card->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_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("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; }