/* * Add a key and the key description in PKCS#15 format to the framework */ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { sc_card_t *card = p15card->card; sc_pkcs15_cert_info_t cert_info; sc_pkcs15_object_t cert_obj; struct sc_pkcs15_object prkd; sc_pkcs15_prkey_info_t *key_info; sc_path_t path; u8 fid[2]; u8 efbin[512]; u8 *ptr; size_t len; int r; fid[0] = PRKD_PREFIX; fid[1] = keyid; /* Try to select a related EF containing the PKCS#15 description of the key */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) { return SC_SUCCESS; } r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read EF.PRKD"); memset(&prkd, 0, sizeof(prkd)); ptr = efbin; len = r; r = sc_pkcs15_decode_prkdf_entry(p15card, &prkd, (const u8 **)&ptr, &len); LOG_TEST_RET(card->ctx, r, "Could not decode EF.PRKD"); /* All keys require user PIN authentication */ prkd.auth_id.len = 1; prkd.auth_id.value[0] = 1; /* * Set private key flag as all keys are private anyway */ prkd.flags |= SC_PKCS15_CO_FLAG_PRIVATE; key_info = (sc_pkcs15_prkey_info_t *)prkd.data; key_info->key_reference = keyid; if (prkd.type == SC_PKCS15_TYPE_PRKEY_RSA) { r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkd, key_info); } else { r = sc_pkcs15emu_add_ec_prkey(p15card, &prkd, key_info); } LOG_TEST_RET(card->ctx, r, "Could not add private key to framework"); /* Check if we also have a certificate for the private key */ fid[0] = EE_CERTIFICATE_PREFIX; sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) { return SC_SUCCESS; } /* Check if the certificate is a X.509 certificate */ r = sc_read_binary(p15card->card, 0, efbin, 1, 0); if (r < 0) { return SC_SUCCESS; } if (efbin[0] == 0x67) { /* Decode CSR and create public key object */ sc_pkcs15emu_sc_hsm_add_pubkey(p15card, key_info, prkd.label); return SC_SUCCESS; /* Ignore any errors */ } if (efbin[0] != 0x30) { return SC_SUCCESS; } memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); cert_info.id = key_info->id; cert_info.path = path; cert_info.path.count = -1; strlcpy(cert_obj.label, prkd.label, sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); LOG_TEST_RET(card->ctx, r, "Could not add certificate"); return SC_SUCCESS; }
int do_genkey(sc_card_t *card, u8 in_key_id, const char *keytype) { int r; sc_cardctl_openpgp_keygen_info_t key_info; u8 fingerprints[60]; sc_path_t path; sc_file_t *file; /* validate in_key_id */ if (in_key_id < 1 || in_key_id > 3) { util_error("unknown key ID %d", in_key_id); return SC_ERROR_INVALID_ARGUMENTS; } /* fall back to RSA 2048 if keytype is not given */ if (!keytype) keytype = "RSA2048"; memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t)); /* generate key depending on keytype passed */ if (strncasecmp("RSA", keytype, strlen("RSA")) == 0) { size_t keylen = 2048; /* default length for RSA keys */ const char *keylen_ptr = keytype + strlen("RSA"); /* try to get key length from keytype, e.g. "rsa3072" -> 3072 */ if (strlen(keylen_ptr) > 0) { if (strspn(keylen_ptr, "0123456789") == strlen(keylen_ptr) && atol(keylen_ptr) >= 1024 && atol(keylen_ptr) <= 4096) { keylen = atol(keylen_ptr); } else { util_error("illegal key type: %s", keytype); return EXIT_FAILURE; } } /* set key_info */ key_info.key_id = in_key_id; key_info.algorithm = SC_OPENPGP_KEYALGO_RSA; key_info.u.rsa.modulus_len = keylen; key_info.u.rsa.modulus = malloc(BYTES4BITS(keylen)); r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); free(key_info.u.rsa.modulus); if (r < 0) { util_error("failed to generate key: %s", sc_strerror(r)); return EXIT_FAILURE; } } else { //TODO: deal with EC keys util_error("Generating non-RSA keys is not yet implemented"); return EXIT_FAILURE; } sc_format_path("006E007300C5", &path); r = sc_select_file(card, &path, &file); if (r < 0) { util_error("failed to retrieve fingerprints: %s", sc_strerror(r)); return EXIT_FAILURE; } r = sc_read_binary(card, 0, fingerprints, 60, 0); if (r < 0) { util_error("failed to retrieve fingerprints: %s", sc_strerror(r)); return EXIT_FAILURE; } printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(in_key_id - 1), 20)); return EXIT_SUCCESS; }
static int sc_pkcs15emu_oberthur_init(struct sc_pkcs15_card * p15card) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info auth_info; struct sc_pkcs15_object obj; struct sc_card *card = p15card->card; struct sc_path path; int rv, ii, tries_left; char serial[0x10]; unsigned char sopin_reference = 0x04; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial, sizeof(serial), 0); p15card->tokeninfo->serial_number = strdup(serial); p15card->ops.parse_df = sc_awp_parse_df; p15card->ops.clear = sc_awp_clear; sc_log(ctx, "Oberthur init: serial %s", p15card->tokeninfo->serial_number); sc_format_path(AWP_PIN_DF, &path); rv = sc_select_file(card, &path, NULL); LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot select PIN dir"); tries_left = -1; rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left); if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT) { sopin_reference = 0x84; rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left); } if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT) LOG_TEST_RET(ctx, rv, "Invalid state of SO-PIN"); /* add PIN */ memset(&auth_info, 0, sizeof(auth_info)); memset(&obj, 0, sizeof(obj)); auth_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; auth_info.auth_method = SC_AC_CHV; auth_info.auth_id.len = 1; auth_info.auth_id.value[0] = 0xFF; auth_info.attrs.pin.min_length = 4; auth_info.attrs.pin.max_length = 64; auth_info.attrs.pin.stored_length = 64; auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; auth_info.attrs.pin.reference = sopin_reference; auth_info.attrs.pin.pad_char = 0xFF; auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_SO_PIN; auth_info.tries_left = tries_left; auth_info.logged_in = SC_PIN_STATE_UNKNOWN; strncpy(obj.label, "SO PIN", SC_PKCS15_MAX_LABEL_SIZE-1); obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label, sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference); rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info); LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object"); tries_left = -1; rv = sc_verify(card, SC_AC_CHV, 0x81, (unsigned char *)"", 0, &tries_left); if (rv == SC_ERROR_PIN_CODE_INCORRECT) { /* add PIN */ memset(&auth_info, 0, sizeof(auth_info)); memset(&obj, 0, sizeof(obj)); auth_info.auth_id.len = sizeof(PinDomainID) > sizeof(auth_info.auth_id.value) ? sizeof(auth_info.auth_id.value) : sizeof(PinDomainID); memcpy(auth_info.auth_id.value, PinDomainID, auth_info.auth_id.len); auth_info.auth_method = SC_AC_CHV; auth_info.attrs.pin.min_length = 4; auth_info.attrs.pin.max_length = 64; auth_info.attrs.pin.stored_length = 64; auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; auth_info.attrs.pin.reference = 0x81; auth_info.attrs.pin.pad_char = 0xFF; auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL; auth_info.tries_left = tries_left; strncpy(obj.label, PIN_DOMAIN_LABEL, SC_PKCS15_MAX_LABEL_SIZE-1); obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; if (sopin_reference == 0x84) { /* * auth_pin_reset_oberthur_style() in card-oberthur.c * always uses PUK with reference 0x84 for * unblocking of User PIN */ obj.auth_id.len = 1; obj.auth_id.value[0] = 0xFF; } sc_format_path(AWP_PIN_DF, &auth_info.path); auth_info.path.type = SC_PATH_TYPE_PATH; sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label, sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference); rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info); LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot add PIN object"); } else if (rv != SC_ERROR_DATA_OBJECT_NOT_FOUND) { LOG_TEST_RET(ctx, rv, "Oberthur init failed: cannot verify PIN"); } for (ii=0; oberthur_infos[ii].name; ii++) { sc_log(ctx, "Oberthur init: read %s file", oberthur_infos[ii].name); rv = sc_oberthur_read_file(p15card, oberthur_infos[ii].path, &oberthur_infos[ii].content, &oberthur_infos[ii].len, 1); LOG_TEST_RET(ctx, rv, "Oberthur init failed: read oberthur file error"); sc_log(ctx, "Oberthur init: parse %s file, content length %"SC_FORMAT_LEN_SIZE_T"u", oberthur_infos[ii].name, oberthur_infos[ii].len); rv = oberthur_infos[ii].parser(p15card, oberthur_infos[ii].content, oberthur_infos[ii].len, oberthur_infos[ii].postpone_allowed); LOG_TEST_RET(ctx, rv, "Oberthur init failed: parse error"); } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
int main(int argc, char * const argv[]) { int r, c, long_optind = 0, err = 0; char *line; int cargc; char *cargv[260]; sc_context_param_t ctx_param; int lcycle = SC_CARDCTRL_LIFECYCLE_ADMIN; FILE *script = stdin; printf("OpenSC Explorer version %s\n", sc_get_version()); while (1) { c = getopt_long(argc, argv, "r:c:vwm:", options, &long_optind); if (c == -1) break; if (c == '?') util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]"); switch (c) { case 'r': opt_reader = optarg; break; case 'c': opt_driver = optarg; break; case 'w': opt_wait = 1; break; case 'v': verbose++; break; case 'm': opt_startfile = optarg; break; } } memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 0; ctx_param.app_name = app_name; r = sc_context_create(&ctx, &ctx_param); if (r) { fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER; if (verbose > 1) { ctx->debug = verbose; ctx->debug_file = stderr; } if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); err = 1; goto end; } } err = util_connect_card(ctx, &card, opt_reader, opt_wait, 0); if (err) goto end; if (opt_startfile) { if(*opt_startfile) { char startpath[1024]; char *args[] = { startpath }; strncpy(startpath, opt_startfile, sizeof(startpath)-1); r = do_cd(1, args); if (r) { printf("unable to select file %s: %s\n", opt_startfile, sc_strerror(r)); return -1; } } } else { sc_format_path("3F00", ¤t_path); r = sc_select_file(card, ¤t_path, ¤t_file); if (r) { printf("unable to select MF: %s\n", sc_strerror(r)); return 1; } } r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle); if (r && r != SC_ERROR_NOT_SUPPORTED) printf("unable to change lifecycle: %s\n", sc_strerror(r)); switch (argc - optind) { default: util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]"); break; case 0: script = stdin; break; case 1: if (strcmp(argv[optind], "-") == 0) { script = stdin; } else if ((script = fopen(argv[optind], "r")) == NULL) { util_print_usage_and_die(app_name, options, option_help, "[SCRIPT]"); } break; } while (!feof(script)) { struct command *cmd; char prompt[3*SC_MAX_PATH_STRING_SIZE]; sprintf(prompt, "OpenSC [%s]> ", path_to_filename(¤t_path, '/')); line = read_cmdline(script, prompt); if (line == NULL) break; cargc = parse_cmdline(line, cargv, DIM(cargv)); if ((cargc < 1) || (*cargv[0] == '#')) continue; for (r=cargc; r < (int)DIM(cargv); r++) cargv[r] = ""; cmd = ambiguous_match(cmds, cargv[0]); if (cmd == NULL) { do_help(0, NULL); } else { cmd->func(cargc-1, cargv+1); } } end: die(err); return 0; /* not reached */ }
static int do_cat(int argc, char **argv) { int r, err = 1; sc_path_t path; sc_file_t *file = NULL; int not_current = 1; int sfi = 0; if (argc > 1) return usage(do_cat); if (!argc) { path = current_path; file = current_file; not_current = 0; } else { const char sfi_prefix[] = "sfi:"; if (strncasecmp(argv[0], sfi_prefix, strlen(sfi_prefix)) == 0) { const char *sfi_n = argv[0] + strlen(sfi_prefix); if(!current_file) { printf("A DF must be selected to read by SFI\n"); goto err; } path = current_path; file = current_file; not_current = 0; sfi = atoi(sfi_n); if ((sfi < 1) || (sfi > 30)) { printf("Invalid SFI: %s\n", sfi_n); return usage(do_cat); } } else { if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_cat); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } } } if (file->type != SC_FILE_TYPE_WORKING_EF && !(file->type == SC_FILE_TYPE_DF && sfi)) { printf("only working EFs may be read\n"); goto err; } if (file->ef_structure == SC_FILE_EF_TRANSPARENT && !sfi) read_and_util_print_binary_file(file); else read_and_print_record_file(file, sfi); err = 0; err: if (not_current) { if (file != NULL) sc_file_free(file); select_current_path_or_die(); } return -err; }
/* * Key generation */ static int incrypto34_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; sc_card_t *card = p15card->card; struct sc_pkcs15_prkey_rsa key_obj; struct sc_cardctl_incrypto34_genkey_info args; struct sc_file *temp; u8 abignum[RSAKEY_MAX_SIZE]; unsigned int keybits; int algorithm, r, delete_it = 0; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Incrypto34 supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } if (incrypto34_key_algorithm(key_info->usage, &algorithm) < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Incrypto34 does not support keys " "that can both sign _and_ decrypt."); return SC_ERROR_NOT_SUPPORTED; } keybits = key_info->modulus_length & ~7UL; if (keybits > RSAKEY_MAX_BITS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to generate key, max size is %d", RSAKEY_MAX_BITS); return SC_ERROR_INVALID_ARGUMENTS; } if (sc_profile_get_file(profile, "tempfile", &temp) < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Profile doesn't define temporary file " "for key generation."); return SC_ERROR_NOT_SUPPORTED; } memset(pubkey, 0, sizeof(*pubkey)); if ((r = sc_pkcs15init_create_file(profile, p15card, temp)) < 0) goto out; delete_it = 1; /* Create a key object, initializing components to 0xff */ memset(&key_obj, 0, sizeof(key_obj)); memset(abignum, 0xFF, sizeof(abignum)); key_obj.modulus.data = abignum; key_obj.modulus.len = keybits >> 3; key_obj.d.data = abignum; key_obj.d.len = keybits >> 3; r = incrypto34_put_key(profile, p15card, algorithm, key_info, &key_obj); if (r < 0) goto out; memset(&args, 0, sizeof(args)); args.key_id = key_info->key_reference; args.key_bits = keybits; args.fid = temp->id; r = sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_GENERATE_KEY, &args); if (r < 0) goto out; /* extract public key from file and delete it */ if ((r = sc_select_file(card, &temp->path, NULL)) < 0) goto out; r = incrypto34_extract_pubkey(card, 1, 0x10, &pubkey->u.rsa.modulus); if (r < 0) goto out; r = incrypto34_extract_pubkey(card, 2, 0x11, &pubkey->u.rsa.exponent); if (r < 0) goto out; pubkey->algorithm = SC_ALGORITHM_RSA; out: if (delete_it) { sc_pkcs15init_rmdir(p15card, profile, temp); } sc_file_free(temp); if (r < 0) { if (pubkey->u.rsa.modulus.data) free (pubkey->u.rsa.modulus.data); if (pubkey->u.rsa.exponent.data) free (pubkey->u.rsa.exponent.data); } return r; }
static int do_put(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; const char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_put); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_put); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = fopen(filename, "rb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = fread(buf, 1, c, outf); if (r < 0) { perror("fread"); goto err; } if (r != c) count = c = r; r = sc_update_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "update failed", file); goto err; } if (r != c) { printf("expecting %d, wrote only %d bytes.\n", c, r); goto err; } idx += c; count -= c; } printf("Total of %d bytes written.\n", idx); err = 0; err: if (file) sc_file_free(file); if (outf) fclose(outf); select_current_path_or_die(); return -err; }
static int detect_netkey( sc_pkcs15_card_t *p15card ){ sc_card_t *card=p15card->card; sc_path_t p; sc_file_t *f; int keylen; char dir[10]; const char *c_auth; /* NKS-Applikation ? */ memset(&p, 0, sizeof(sc_path_t)); p.type=SC_PATH_TYPE_DF_NAME; memcpy(p.value, "\xD2\x76\x00\x00\x03\x01\x02", p.len=7); if (sc_select_file(card,&p,&f)!=SC_SUCCESS) return 1; sprintf(dir,"%04X", f->id); sc_file_free(f); p15card->tokeninfo->manufacturer_id = strdup("TeleSec GmbH"); p15card->tokeninfo->label = strdup(card->type==SC_CARD_TYPE_TCOS_V3 ? "NetKey V3 Card" : "NetKey Card"); keylen= card->type==SC_CARD_TYPE_TCOS_V3 ? 2048 : 1024; c_auth= card->type==SC_CARD_TYPE_TCOS_V3 ? "C500" : "C100"; insert_cert(p15card, dirpath(dir,"4331"), 0x45, 1, "Signatur Zertifikat 1"); insert_cert(p15card, dirpath(dir,"4332"), 0x45, 1, "Signatur Zertifikat 2"); insert_cert(p15card, dirpath(dir,"C000"), 0x45, 0, "Telesec Signatur Zertifikat"); insert_cert(p15card, dirpath(dir,"43B1"), 0x46, 1, "Verschluesselungs Zertifikat 1"); insert_cert(p15card, dirpath(dir,"43B2"), 0x46, 1, "Verschluesselungs Zertifikat 2"); insert_cert(p15card, dirpath(dir,"C200"), 0x46, 0, "Telesec Verschluesselungs Zertifikat"); insert_cert(p15card, dirpath(dir,"4371"), 0x47, 1, "Authentifizierungs Zertifikat 1"); insert_cert(p15card, dirpath(dir,"4372"), 0x47, 1, "Authentifizierungs Zertifikat 2"); insert_cert(p15card, dirpath(dir,c_auth), 0x47, 0, "Telesec Authentifizierungs Zertifikat"); insert_cert(p15card, dirpath(dir,"C201"), 0x48, 0, "Telesec 1024bit Zertifikat"); insert_key(p15card, dirpath(dir,"5331"), 0x45, 0x80, keylen, 4, "Signatur Schluessel"); insert_key(p15card, dirpath(dir,"53B1"), 0x46, 0x81, keylen, 3, "Verschluesselungs Schluessel"); insert_key(p15card, dirpath(dir,"5371"), 0x47, 0x82, keylen, 3, "Authentifizierungs Schluessel"); insert_key(p15card, dirpath(dir,"0000"), 0x48, 0x83, 1024, 3, "1024bit Schluessel"); insert_pin(p15card, "5000", 1, 2, 0x00, 6, "PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED ); insert_pin(p15card, "5001", 2, 0, 0x01, 8, "PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN ); if(card->type==SC_CARD_TYPE_TCOS_V3){ insert_pin(p15card, dirpath(dir,"0000"), 3, 1, 0x83, 6, "NetKey PIN2", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED ); } else { insert_pin(p15card, dirpath(dir,"5080"), 3, 1, 0x80, 6, "NetKey PIN0", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED ); } insert_pin(p15card, dirpath(dir,"5081"), 4, 1, 0x81, 6, "NetKey PIN1", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED ); /* SigG-Applikation */ p.len=7; p.type=SC_PATH_TYPE_DF_NAME; memcpy(p.value, "\xD2\x76\x00\x00\x66\x01", p.len=6); if (sc_select_file(card,&p,&f)==SC_SUCCESS){ sprintf(dir,"%04X", f->id); sc_file_free(f); insert_cert(p15card, dirpath(dir,"C000"), 0x49, 1, "SigG Zertifikat 1"); insert_cert(p15card, dirpath(dir,"4331"), 0x49, 1, "SigG Zertifikat 2"); insert_cert(p15card, dirpath(dir,"4332"), 0x49, 1, "SigG Zertifikat 3"); if(card->type==SC_CARD_TYPE_TCOS_V3){ insert_key(p15card, dirpath(dir,"0000"), 0x49, 0x84, 2048, 5, "SigG Schluessel"); } else { insert_key(p15card, dirpath(dir,"5331"), 0x49, 0x80, 1024, 5, "SigG Schluessel"); } insert_pin(p15card, dirpath(dir,"5081"), 5, 0, 0x81, 6, "SigG PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED ); if(card->type==SC_CARD_TYPE_TCOS_V3){ insert_pin(p15card, dirpath(dir,"0000"), 6, 0, 0x83, 8, "SigG PIN2", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED ); } } return 0; }
static int insert_key( sc_pkcs15_card_t *p15card, const char *path, unsigned char id, unsigned char key_reference, int key_length, unsigned char auth_id, const char *label ){ sc_card_t *card=p15card->card; sc_context_t *ctx=p15card->card->ctx; sc_file_t *f; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; int r, can_sign, can_crypt; memset(&prkey_info, 0, sizeof(prkey_info)); prkey_info.id.len = 1; prkey_info.id.value[0] = id; prkey_info.native = 1; prkey_info.key_reference = key_reference; prkey_info.modulus_length = key_length; sc_format_path(path, &prkey_info.path); memset(&prkey_obj, 0, sizeof(prkey_obj)); strlcpy(prkey_obj.label, 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] = auth_id; can_sign=can_crypt=0; if(card->type==SC_CARD_TYPE_TCOS_V3){ unsigned char buf[256]; int i, rec_no=0; if(prkey_info.path.len>=2) prkey_info.path.len-=2; sc_append_file_id(&prkey_info.path, 0x5349); if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&prkey_info.path)); return 1; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Searching for Key-Ref %02X\n", key_reference); while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){ int found=0; if(buf[0]!=0xA0) continue; for(i=2;i<buf[1]+2;i+=2+buf[i+1]){ if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==key_reference) ++found; } if(found) break; } if(r<=0){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_KEYD-Record found\n"); return 1; } for(i=0;i<r;i+=2+buf[i+1]){ if(buf[i]==0xB6) can_sign++; if(buf[i]==0xB8) can_crypt++; } } else { if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&prkey_info.path)); return 1; } if (f->prop_attr[1] & 0x04) can_crypt=1; if (f->prop_attr[1] & 0x08) can_sign=1; sc_file_free(f); } prkey_info.usage= SC_PKCS15_PRKEY_USAGE_SIGN; if(can_crypt) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT|SC_PKCS15_PRKEY_USAGE_DECRYPT; if(can_sign) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; r=sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if(r!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", path); return 4; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK%s%s\n", path, can_sign ? ", Sign" : "", can_crypt ? ", Crypt" : ""); return 0; }
/* * On-board key generation. */ static int gpk_generate_key(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { struct sc_cardctl_gpk_genkey args; sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; unsigned int keybits; sc_file_t *keyfile; int r, n; if (card->ctx->debug >= 1) { char pbuf[SC_MAX_PATH_STRING_SIZE]; r = sc_path_print(pbuf, sizeof(pbuf), &key_info->path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(card->ctx, "path=%s, %d bits\n", pbuf, key_info->modulus_length); } if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_error(card->ctx, "GPK supports generating only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } /* The caller is supposed to have chosen a key file path for us */ if (key_info->path.len == 0 || key_info->modulus_length == 0) return SC_ERROR_INVALID_ARGUMENTS; keybits = key_info->modulus_length; if ((r = sc_select_file(card, &key_info->path, &keyfile)) < 0) return r; #ifndef PK_INIT_IMMEDIATELY r = gpk_pkfile_init_public(profile, card, keyfile, SC_ALGORITHM_RSA, keybits, key_info->usage); if (r < 0) { sc_file_free(keyfile); return r; } if ((r = gpk_pkfile_init_private(card, keyfile, 5 * ((3 + keybits / 16 + 7) & ~7UL))) < 0) { sc_file_free(keyfile); return r; } #endif sc_file_free(keyfile); memset(&args, 0, sizeof(args)); /*args.exponent = 0x10001;*/ n = key_info->path.len; args.fid = (key_info->path.value[n-2] << 8) | key_info->path.value[n-1]; args.privlen = keybits; r = sc_card_ctl(card, SC_CARDCTL_GPK_GENERATE_KEY, &args); if (r < 0) return r; /* This is fairly weird. The GENERATE RSA KEY command returns * immediately, but obviously it needs more time to complete. * This is why we sleep here. */ sleep(20); pubkey->algorithm = SC_ALGORITHM_RSA; return gpk_read_rsa_key(card, &pubkey->u.rsa); }
static int insert_pin( sc_pkcs15_card_t *p15card, const char *path, unsigned char id, unsigned char auth_id, unsigned char pin_reference, int min_length, const char *label, int pin_flags ){ sc_card_t *card=p15card->card; sc_context_t *ctx=p15card->card->ctx; sc_file_t *f; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; int r; memset(&pin_info, 0, sizeof(pin_info)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = id; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = pin_reference; pin_info.attrs.pin.flags = pin_flags; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = min_length; pin_info.attrs.pin.stored_length = 16; pin_info.attrs.pin.max_length = 16; pin_info.attrs.pin.pad_char = '\0'; sc_format_path(path, &pin_info.path); memset(&pin_obj, 0, sizeof(pin_obj)); strlcpy(pin_obj.label, label, sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; pin_obj.auth_id.len = auth_id ? 0 : 1; pin_obj.auth_id.value[0] = auth_id; if(card->type==SC_CARD_TYPE_TCOS_V3){ unsigned char buf[256]; int i, rec_no=0; if(pin_info.path.len>=2) pin_info.path.len-=2; sc_append_file_id(&pin_info.path, 0x5049); if(sc_select_file(card, &pin_info.path, NULL)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&pin_info.path)); return 1; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Searching for PIN-Ref %02X\n", pin_reference); while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){ int found=0, fbz=-1; if(buf[0]!=0xA0) continue; for(i=2;i<buf[1]+2;i+=2+buf[i+1]){ if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==pin_reference) ++found; if(buf[i]==0x90) fbz=buf[i+1+buf[i+1]]; } if(found) pin_info.tries_left=fbz; if(found) break; } if(r<=0){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_PWDD-Record found\n"); return 1; } } else { if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path); return 1; } pin_info.tries_left=f->prop_attr[3]; sc_file_free(f); } r=sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if(r!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_pin_obj(%s) failed\n", path); return 4; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK, FBZ=%d\n", path, pin_info.tries_left); return 0; }
/* * Initialize pin file */ static int gpk_init_pinfile(struct sc_profile *profile, sc_card_t *card, sc_file_t *file) { const sc_acl_entry_t *acl; unsigned char buffer[GPK_MAX_PINS * 8], *blk; struct sc_file *pinfile; unsigned int so_attempts[2], user_attempts[2]; unsigned int npins, i, j, cks; int r; /* Set defaults */ so_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PIN); so_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PUK); user_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PIN); user_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PUK); sc_file_dup(&pinfile, file); if (pinfile == NULL) return SC_ERROR_OUT_OF_MEMORY; /* Create the PIN file. */ acl = sc_file_get_acl_entry(pinfile, SC_AC_OP_WRITE); if (acl->method != SC_AC_NEVER) { sc_error(card->ctx, "PIN file most be protected by WRITE=NEVER"); sc_file_free(pinfile); return SC_ERROR_INVALID_ARGUMENTS; } sc_file_add_acl_entry(pinfile, SC_AC_OP_WRITE, SC_AC_NONE, 0); if (pinfile->size == 0) pinfile->size = GPK_MAX_PINS * 8; /* Now create the file */ if ((r = sc_pkcs15init_create_file(profile, card, pinfile)) < 0 || (r = sc_select_file(card, &pinfile->path, NULL)) < 0) goto out; /* Set up the PIN file contents. * We assume the file will contain pairs of PINs/PUKs */ npins = pinfile->size / 8; memset(buffer, 0, sizeof(buffer)); for (i = 0, blk = buffer; i < npins; blk += 8, i += 1) { /* Determine the number of PIN/PUK presentation * attempts. If the profile defines a SO PIN, * it will be stored in the first PIN/PUK pair. */ blk[0] = user_attempts[i & 1]; if (i < 2 && so_attempts[0]) blk[0] = so_attempts[i & 1]; if ((i & 1) == 0) { /* This is a PIN. If there's room in the file, * the next will be a PUK so take note of the * unlock code */ if (i + 1 < npins) blk[2] = GPK_PIN_SCOPE | (i + 1); } /* Compute the CKS */ for (j = 0, cks = 0; j < 8; j++) cks ^= blk[j]; blk[3] = ~cks; } r = sc_write_binary(card, 0, buffer, npins * 8, 0); if (r >= 0) r = gpk_lock_pinfile(profile, card, pinfile); out: sc_file_free(pinfile); return r; }
/* * Store a PIN */ static int gpk_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df, sc_pkcs15_object_t *pin_obj, const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len) { sc_pkcs15_pin_info_t *pin_info = (sc_pkcs15_pin_info_t *) pin_obj->data; u8 nulpin[8]; int r, type; if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { type = SC_PKCS15INIT_SO_PIN; /* SO PIN reference must be 0 */ if (pin_info->reference != (GPK_PIN_SCOPE | 0)) return SC_ERROR_INVALID_ARGUMENTS; } else { type = SC_PKCS15INIT_USER_PIN; /* PIN references must be even numbers * (the odd numbered PIN entries contain the * PUKs). * Returning SC_ERROR_INVALID_PIN_REFERENCE will * tell the caller to pick a different value. */ if ((pin_info->reference & 1) || !(pin_info->reference & GPK_PIN_SCOPE)) return SC_ERROR_INVALID_PIN_REFERENCE; if (pin_info->reference >= (GPK_PIN_SCOPE + GPK_MAX_PINS)) return SC_ERROR_TOO_MANY_OBJECTS; } /* No PUK given, but the PIN file specifies an unblock * PIN for every PIN. * Use the same value for the PUK for now. * Alternatively, we could leave the unblock PIN at the default * value, but deliberately block it. */ if (puk == NULL || puk_len == 0) { puk = pin; puk_len = pin_len; } r = sc_select_file(card, &df->path, NULL); if (r < 0) return r; /* Current PIN is 00:00:00:00:00:00:00:00 */ memset(nulpin, 0, sizeof(nulpin)); r = sc_change_reference_data(card, SC_AC_CHV, pin_info->reference, nulpin, sizeof(nulpin), pin, pin_len, NULL); if (r < 0) return r; /* Current PUK is 00:00:00:00:00:00:00:00 */ r = sc_change_reference_data(card, SC_AC_CHV, pin_info->reference + 1, nulpin, sizeof(nulpin), puk, puk_len, NULL); if (r < 0) return r; sc_keycache_set_pin_name(&df->path, pin_info->reference, type); return r; }
/* * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects * */ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_file_t *file = NULL; sc_path_t path; u8 filelist[MAX_EXT_APDU_LENGTH]; int filelistlength; int r, i; sc_cvc_t devcert; struct sc_app_info *appinfo; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; u8 efbin[512]; u8 *ptr; size_t len; LOG_FUNC_CALLED(card->ctx); appinfo = calloc(1, sizeof(struct sc_app_info)); if (appinfo == NULL) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } appinfo->aid = sc_hsm_aid; appinfo->ddo.aid = sc_hsm_aid; p15card->app = appinfo; sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); r = sc_select_file(card, &path, &file); LOG_TEST_RET(card->ctx, r, "Could not select SmartCard-HSM application"); p15card->card->version.hw_major = 24; /* JCOP 2.4.1r3 */ p15card->card->version.hw_minor = 13; p15card->card->version.fw_major = file->prop_attr[file->prop_attr_len - 2]; p15card->card->version.fw_minor = file->prop_attr[file->prop_attr_len - 1]; sc_file_free(file); /* Read device certificate to determine serial number */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, (u8 *) "\x2F\x02", 2, 0, 0); r = sc_select_file(card, &path, NULL); LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut"); r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read EF.C_DevAut"); ptr = efbin; len = r; memset(&devcert, 0 ,sizeof(devcert)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert); LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut"); sc_pkcs15emu_sc_hsm_read_tokeninfo(p15card); if (p15card->tokeninfo->label == NULL) { p15card->tokeninfo->label = strdup("SmartCard-HSM"); if (p15card->tokeninfo->label == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) { free(p15card->tokeninfo->manufacturer_id); p15card->tokeninfo->manufacturer_id = NULL; } if (p15card->tokeninfo->manufacturer_id == NULL) { p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de"); if (p15card->tokeninfo->manufacturer_id == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } appinfo->label = strdup(p15card->tokeninfo->label); if (appinfo->label == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); len = strnlen(devcert.chr, sizeof devcert.chr); /* Strip last 5 digit sequence number from CHR */ assert(len >= 8); len -= 5; p15card->tokeninfo->serial_number = calloc(len + 1, 1); if (p15card->tokeninfo->serial_number == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(p15card->tokeninfo->serial_number, devcert.chr, len); *(p15card->tokeninfo->serial_number + len) = 0; sc_hsm_set_serialnr(card, p15card->tokeninfo->serial_number); sc_pkcs15emu_sc_hsm_free_cvc(&devcert); memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = 1; pin_info.path.aid = sc_hsm_aid; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = 0x81; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = 6; pin_info.attrs.pin.stored_length = 0; pin_info.attrs.pin.max_length = 15; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = 3; pin_info.max_tries = 3; strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = 2; pin_info.path.aid = sc_hsm_aid; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = 0x88; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED|SC_PKCS15_PIN_FLAG_SO_PIN; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_BCD; pin_info.attrs.pin.min_length = 16; pin_info.attrs.pin.stored_length = 0; pin_info.attrs.pin.max_length = 16; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = 15; pin_info.max_tries = 15; strlcpy(pin_obj.label, "SOPIN", sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); filelistlength = sc_list_files(card, filelist, sizeof(filelist)); LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); for (i = 0; i < filelistlength; i += 2) { switch(filelist[i]) { case KEY_PREFIX: r = sc_pkcs15emu_sc_hsm_add_prkd(p15card, filelist[i + 1]); break; case DCOD_PREFIX: r = sc_pkcs15emu_sc_hsm_add_dcod(p15card, filelist[i + 1]); break; case CD_PREFIX: r = sc_pkcs15emu_sc_hsm_add_cd(p15card, filelist[i + 1]); break; } if (r != SC_SUCCESS) { sc_log(card->ctx, "Error %d adding elements to framework", r); } } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_pubkey *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r; size_t keybits = key_info->modulus_length; unsigned char raw_pubkey[256]; LOG_FUNC_CALLED(ctx); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA && object->type != SC_PKCS15_TYPE_PRKEY_EC) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Generate key failed: only RSA and EC supported"); /* Check that the card supports the requested modulus length */ switch (object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); if(key_info->field_length != 0) keybits = key_info->field_length; else key_info->field_length = keybits; break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); break; } sc_log(ctx, "Generate key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(card, &key_info->path, &file); LOG_TEST_RET(ctx, r, "Cannot generate key: failed to select key file"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE); LOG_TEST_RET(ctx, r, "No authorisation to generate private key"); /* Fill in data structure */ memset(&args, 0, sizeof (args)); args.key_len_bits = keybits; args.op_type = OP_TYPE_GENERATE; if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) { args.key_type = SC_CARDCTL_MYEID_KEY_RSA; args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; args.pubexp = MYEID_DEFAULT_PUBKEY; } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { args.key_type = SC_CARDCTL_MYEID_KEY_EC; } /* Generate RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); /* Keypair generation -> collect public key info */ if (pubkey != NULL) { struct sc_cardctl_myeid_data_obj data_obj; if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) { pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->u.rsa.modulus.len = (keybits + 7) / 8; pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len); pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN; pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN); memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN); /* Get public key modulus */ r = sc_select_file(card, &file->path, NULL); LOG_TEST_RET(ctx, r, "Cannot get key modulus: select key file failed"); data_obj.P1 = 0x01; data_obj.P2 = 0x01; data_obj.Data = raw_pubkey; data_obj.DataLen = sizeof (raw_pubkey); r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); LOG_TEST_RET(ctx, r, "Cannot get RSA key modulus: 'MYEID_GETDATA' failed"); if ((data_obj.DataLen * 8) != key_info->modulus_length) LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Cannot get RSA key modulus: invalid key-size"); memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { pubkey->algorithm = SC_ALGORITHM_EC; r = sc_select_file(card, &file->path, NULL); LOG_TEST_RET(ctx, r, "Cannot get public key: select key file failed"); data_obj.P1 = 0x01; data_obj.P2 = 0x86; /* Get public EC key (Q) */ data_obj.Data = raw_pubkey; data_obj.DataLen = sizeof (raw_pubkey); r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed"); pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2); pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; pubkey->data.value = malloc(data_obj.DataLen); pubkey->data.len = data_obj.DataLen; pubkey->u.ec.params.field_length = keybits; /* Omit the first 2 bytes (0x86??) */ memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2); memcpy(pubkey->data.value, data_obj.Data, data_obj.DataLen); } } if (file) sc_file_free(file); LOG_FUNC_RETURN(ctx, r); }
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; }
static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_path_t path; sc_pkcs15_id_t id, auth_id; unsigned char serial_buf[13], *serial; int flags; int r; #ifdef ENABLE_ZLIB int i = 0, j = 0; const char *certLabel[] = { "User Non-repudiation Certificate", /* "User Non-repudiation Certificate" */ "TSA Certificate", "CA Certificate" }; const char *certPath[] = { "3F00300060006002", "3F00300060006003", "3F00300060006004" }; #endif const char *keyPath = "3F00300040000008"; const char *pinDfName = "05040200"; /* 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; const char *authPIN = "Authentication PIN"; /* const char *nonrepPIN = "Non-repudiation PIN"; */ const char *authPRKEY = "Authentication Key"; /* const char *nonrepPRKEY = "Non repudiation Key"; */ p15card->opts.use_file_cache = 1; /* Get Serial number */ sc_format_path("3F0030000001", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_read_binary(card, 0xC3, serial_buf, 12, 0); serial = serial_buf; /* * The serial number is 8 characters long. Later versions of the * card have the serial number at a different offset, after 4 more * bytes. */ if (serial[0] != 'H') { if (serial[4] == 'H') serial = &serial_buf[4]; else return SC_ERROR_WRONG_CARD; } serial[8] = '\0'; /* Controllo che il serial number inizi per "H" */ if( serial[0] != 'H' ) return SC_ERROR_WRONG_CARD; set_string(&p15card->tokeninfo->label, "Actalis"); set_string(&p15card->tokeninfo->manufacturer_id, "Actalis"); set_string(&p15card->tokeninfo->serial_number, (char *)serial); #ifdef ENABLE_ZLIB for (i = 0; i < 3; i++) { sc_path_t cpath; sc_format_path(certPath[i], &cpath); if (sc_select_file(card, &cpath, NULL) == SC_SUCCESS) { unsigned char *compCert = NULL, *cert = NULL, size[2]; unsigned int compLen, len; sc_pkcs15_cert_info_t cert_info; sc_pkcs15_object_t cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_read_binary(card, 2, size, 2, 0); compLen = (size[0] << 8) + size[1]; compCert = malloc(compLen * sizeof(unsigned char)); len = 3 * compLen; /*Approximation of the uncompressed size */ cert = malloc(len * sizeof(unsigned char)); sc_read_binary(card, 4, compCert, compLen, 0); if (uncompress(cert, (unsigned long int *) &len, compCert, compLen) != Z_OK) return SC_ERROR_INTERNAL; cpath.index = 0; cpath.count = len; sc_pkcs15_cache_file(p15card, &cpath, cert, len); id.value[0] = j + 1; id.len = 1; cert_info.id = id; cert_info.path = cpath; cert_info.authority = (j>0); strlcpy(cert_obj.label, certLabel[j], sizeof(cert_obj.label)); j++; cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); } } #endif /* adding PINs & private keys */ flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; sc_format_path(pinDfName, &path); path.type = SC_PATH_TYPE_DF_NAME; id.value[0] = 1; id.len = 1; sc_pkcs15emu_add_pin(p15card, &id, authPIN, &path, 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); sc_format_path(keyPath, &path); id.value[0] = 1; id.len = 1; 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, 0x08, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); /* return to MF */ sc_format_path("3F00", &path); sc_select_file(card, &path, NULL); { /* 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; }
/* * Generate a keypair */ static int jcop_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; struct sc_cardctl_jcop_genkey args; sc_file_t *temppubfile=NULL, *keyfile=NULL; unsigned char *keybuf=NULL; size_t mod_len, exp_len, pub_len, keybits; int r,delete_ok=0; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } r=sc_profile_get_file(profile, "temp-pubkey", &temppubfile); if (r < 0) goto out; r = sc_select_file(p15card->card, &key_info->path, &keyfile); if (r < 0) goto out; mod_len = key_info->modulus_length / 8; exp_len = 4; pub_len = 2 + mod_len + exp_len; temppubfile->size = pub_len; r = sc_pkcs15init_fixup_file(profile, p15card, temppubfile); if (r < 0) goto out; r = sc_pkcs15init_create_file(profile, p15card, temppubfile); if (r < 0) goto out; delete_ok=1; r = sc_pkcs15init_authenticate(profile, p15card, temppubfile, SC_AC_OP_UPDATE); if (r < 0) goto out; r = sc_pkcs15init_authenticate(profile, p15card, keyfile, SC_AC_OP_UPDATE); if (r < 0) goto out; keybits = key_info->modulus_length; /* generate key */ /* keysize is _not_ passed to the card at any point. it appears to infer it from the file size */ memset(&args, 0, sizeof(args)); args.exponent = 0x10001; sc_append_file_id(&args.pub_file_ref, temppubfile->id); sc_append_file_id(&args.pri_file_ref, keyfile->id); keybuf = malloc(keybits / 8); if (!keybuf) { r=SC_ERROR_OUT_OF_MEMORY; goto out; } args.pubkey = keybuf; args.pubkey_len = keybits / 8; r = sc_card_ctl(p15card->card, SC_CARDCTL_JCOP_GENERATE_KEY, (void *)&args); if (r < 0) goto out; /* extract public key */ pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->u.rsa.modulus.len = keybits / 8; pubkey->u.rsa.modulus.data = keybuf; pubkey->u.rsa.exponent.len = 3; pubkey->u.rsa.exponent.data = malloc(3); if (!pubkey->u.rsa.exponent.data) { pubkey->u.rsa.modulus.data = NULL; r=SC_ERROR_OUT_OF_MEMORY; goto out; } memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3); out: if (r < 0 && keybuf) free(keybuf); if (delete_ok) sc_pkcs15init_rmdir(p15card, profile, temppubfile); if (keyfile) sc_file_free(keyfile); if (temppubfile) sc_file_free(temppubfile); return r; }
static int do_get(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_get); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_get); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = (strcmp(filename, "-") == 0) ? stdout : fopen(filename, "wb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } count = file->size; while (count) { /* FIXME sc_read_binary does this kind of fetching in a loop already */ int c = count > sizeof(buf) ? sizeof(buf) : count; r = sc_read_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((r != c) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { printf("expecting %d, got only %d bytes.\n", c, r); goto err; } if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID)) break; fwrite(buf, r, 1, outf); idx += r; count -= r; } if (outf == stdout) { fwrite("\n", 1, 1, outf); } else { printf("Total of %d bytes read from %s and saved to %s.\n", idx, argv[0], filename); } err = 0; err: if (file) sc_file_free(file); if (outf != NULL && outf != stdout) fclose(outf); select_current_path_or_die(); return -err; }
static void do_esteid(sc_card_t *card) { sc_path_t path; int r, i; unsigned char buff[512]; if (stats) { int key_used[4]; sc_format_path("3f00eeee0013", &path); r = sc_select_file(card, &path, NULL); if (r) { fprintf(stderr, "Failed to select key counters: %s\n", sc_strerror(r)); goto out; } /* print the counters */ for (i = 1; i <= 4; i++) { r = sc_read_record(card, i, buff, 128, SC_RECORD_BY_REC_NR); if (r < 0) goto out; key_used[i - 1] = 0xffffff - ((unsigned char) buff[0xc] * 65536 + (unsigned char) buff[0xd] * 256 + (unsigned char) buff[0xe]); } for (i = 0; i < 2; i++) { printf("Key generation #%d usage:\n\tsign: %d\n\tauth: %d\n", i, key_used[i], key_used[i + 2]); } exit_status = EXIT_SUCCESS; goto out; } /* Or just read the datafile */ sc_format_path("3f00eeee5044", &path); r = sc_select_file(card, &path, NULL); if (r) { fprintf(stderr, "Failed to select DF: %s\n", sc_strerror(r)); goto out; } for (i = 0; esteid_data[i].recno != 0; i++) { r = sc_read_record(card, esteid_data[i].recno, buff, 50, SC_RECORD_BY_REC_NR); if (r < 0) { fprintf (stderr, "Failed to read record %d from card: %s\n", esteid_data[i].recno, sc_strerror (r)); goto out; } buff[r] = '\0'; if (exec_program) { unsigned char * cp; cp = malloc(strlen(esteid_data[i].env_name) + strlen((char *) buff) + 2); if (cp) { strcpy((char *) cp,esteid_data[i].env_name); strcat((char *) cp,"="); strcat((char *) cp,(char *) buff); putenv((char *) cp); } } else { printf("%s: %s\n", esteid_data[i].name, buff); } } exit_status = EXIT_SUCCESS; out: return; }
static int do_asn1(int argc, char **argv) { int r, err = 1; sc_path_t path; sc_file_t *file = NULL; int not_current = 1; size_t len; unsigned char *buf = NULL; if (argc > 1) return usage(do_asn1); /* select file */ if (argc) { if (arg_to_path(argv[0], &path, 0) != 0) { puts("Invalid file path"); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } } else { path = current_path; file = current_file; not_current = 0; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } /* read */ if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("only transparent file type is supported at the moment\n"); goto err; } len = file->size; buf = calloc(1, len); if (!buf) { goto err; } r = sc_read_binary(card, 0, buf, len, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((size_t)r != len) { printf("WARNING: expecting %lu, got %d bytes.\n", (unsigned long) len, r); /* some cards return a bogus value for file length. As * long as the actual length is not higher than the expected * length, continue */ if(r > (signed)len) { goto err; } } /* asn1 dump */ sc_asn1_print_tags(buf, r); err = 0; err: if (buf) free(buf); if (not_current) { if (file) sc_file_free(file); select_current_path_or_die(); } return -err; }
static int gemsafe_get_cert_len(sc_card_t *card) { int r; u8 ibuf[GEMSAFE_MAX_OBJLEN]; u8 *iptr; struct sc_path path; struct sc_file *file; size_t objlen, certlen; unsigned int ind, i=0; sc_format_path(GEMSAFE_PATH, &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* Initial read */ r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); if (r < 0) return SC_ERROR_INTERNAL; /* Actual stored object size is encoded in first 2 bytes * (allocated EF space is much greater!) */ objlen = (((size_t) ibuf[0]) << 8) | ibuf[1]; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Stored object is of size: %d\n", objlen); if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid object size: %d\n", objlen); return SC_ERROR_INTERNAL; } /* It looks like the first thing in the block is a table of * which keys are allocated. The table is small and is in the * first 248 bytes. Example for a card with 10 key containers: * 01 f0 00 03 03 b0 00 03 <= 1st key unallocated * 01 f0 00 04 03 b0 00 04 <= 2nd key unallocated * 01 fe 14 00 05 03 b0 00 05 <= 3rd key allocated * 01 fe 14 01 06 03 b0 00 06 <= 4th key allocated * 01 f0 00 07 03 b0 00 07 <= 5th key unallocated * ... * 01 f0 00 0c 03 b0 00 0c <= 10th key unallocated * For allocated keys, the fourth byte seems to indicate the * default key and the fifth byte indicates the key_ref of * the private key. */ ind = 2; /* skip length */ while (ibuf[ind] == 0x01) { if (ibuf[ind+1] == 0xFE) { gemsafe_prkeys[i].ref = ibuf[ind+4]; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Key container %d is allocated and uses key_ref %d\n", i+1, gemsafe_prkeys[i].ref); ind += 9; } else { gemsafe_prkeys[i].label = NULL; gemsafe_cert[i].label = NULL; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Key container %d is unallocated\n", i+1); ind += 8; } i++; } /* Delete additional key containers from the data structures if * this card can't accomodate them. */ for (; i < gemsafe_cert_max; i++) { gemsafe_prkeys[i].label = NULL; gemsafe_cert[i].label = NULL; } /* Read entire file, then dissect in memory. * Gemalto ClassicClient seems to do it the same way. */ iptr = ibuf + GEMSAFE_READ_QUANTUM; while ((size_t)(iptr - ibuf) < objlen) { r = sc_read_binary(card, iptr - ibuf, iptr, MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Could not read cert object\n"); return SC_ERROR_INTERNAL; } iptr += GEMSAFE_READ_QUANTUM; } /* Search buffer for certificates, they start with 0x3082. */ i = 0; while (ind < objlen - 1) { if (ibuf[ind] == 0x30 && ibuf[ind+1] == 0x82) { /* Find next allocated key container */ while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL) i++; if (i == gemsafe_cert_max) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Warning: Found orphaned certificate at offset %d\n", ind); return SC_SUCCESS; } /* DER cert len is encoded this way */ certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Found certificate of key container %d at offset %d, len %d\n", i+1, ind, certlen); gemsafe_cert[i].index = ind; gemsafe_cert[i].count = certlen; ind += certlen; i++; } else ind++; } /* Delete additional key containers from the data structures if * they're missing on the card. */ for (; i < gemsafe_cert_max; i++) { if (gemsafe_cert[i].label) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Warning: Certificate of key container %d is missing\n", i+1); gemsafe_prkeys[i].label = NULL; gemsafe_cert[i].label = NULL; } } return SC_SUCCESS; }
static int do_find(int argc, char **argv) { u8 fid[2], end[2]; sc_path_t path; int r; fid[0] = 0; fid[1] = 0; end[0] = 0xFF; end[1] = 0xFF; switch (argc) { case 2: if (arg_to_fid(argv[1], end) != 0) return usage(do_find); /* fall through */ case 1: if (arg_to_fid(argv[0], fid) != 0) return usage(do_find); /* fall through */ case 0: break; default: return usage(do_find); } printf("FileID\tType Size\n"); while (1) { sc_file_t *file = NULL; printf("(%02X%02X)\r", fid[0], fid[1]); fflush(stdout); if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; sc_append_path_id(&path, fid, sizeof fid); } else { if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0) != SC_SUCCESS) { printf("unable to set path.\n"); die(1); } } r = sc_select_file(card, &path, &file); switch (r) { case SC_SUCCESS: file->id = (fid[0] << 8) | fid[1]; print_file(file); sc_file_free(file); select_current_path_or_die(); break; case SC_ERROR_NOT_ALLOWED: case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED: printf("(%02X%02X)\t%s\n", fid[0], fid[1], sc_strerror(r)); break; } if (fid[0] == end[0] && fid[1] == end[1]) break; fid[1] = fid[1] + 1; if (fid[1] == 0) fid[0] = fid[0] + 1; } return 0; }
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 do_info(int argc, char **argv) { sc_file_t *file; sc_path_t path; size_t i; const char *st = NULL; int r, not_current = 1; const id2str_t *ac_ops = NULL; if (!argc) { path = current_path; file = current_file; not_current = 0; } else if (argc == 1) { if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_info); r = sc_select_file(card, &path, &file); if (r) { printf("unable to select file: %s\n", sc_strerror(r)); return -1; } } else return usage(do_info); if(!file->type_attr_len) st = "Unknown File"; switch (file->type) { case SC_FILE_TYPE_WORKING_EF: case SC_FILE_TYPE_INTERNAL_EF: st = "Elementary File"; break; case SC_FILE_TYPE_DF: st = "Dedicated File"; break; } if (st == NULL) printf("\nFile type [%02x] ID %04X", *file->type_attr, file->id); else printf("\n%s ID %04X", st, file->id); if (file->sid) printf(", SFI %02X", file->sid); printf("\n\n%-15s%s\n", "File path:", path_to_filename(&path, '/')); printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size); if (file->type == SC_FILE_TYPE_DF) { static const id2str_t ac_ops_df[] = { { SC_AC_OP_SELECT, "SELECT" }, { SC_AC_OP_LOCK, "LOCK" }, { SC_AC_OP_DELETE, "DELETE" }, { SC_AC_OP_CREATE, "CREATE" }, { SC_AC_OP_REHABILITATE, "REHABILITATE" }, { SC_AC_OP_INVALIDATE, "INVALIDATE" }, { SC_AC_OP_LIST_FILES, "LIST FILES" }, { SC_AC_OP_CRYPTO, "CRYPTO" }, { SC_AC_OP_DELETE_SELF, "DELETE SELF" }, { 0, NULL } }; if (file->namelen) { printf("%-15s", "DF name:"); util_print_binary(stdout, file->name, file->namelen); printf("\n"); } ac_ops = ac_ops_df; } else { static const id2str_t ac_ops_ef[] = { { SC_AC_OP_READ, "READ" }, { SC_AC_OP_UPDATE, "UPDATE" }, { SC_AC_OP_DELETE, "DELETE" }, { SC_AC_OP_WRITE, "WRITE" }, { SC_AC_OP_REHABILITATE, "REHABILITATE" }, { SC_AC_OP_INVALIDATE, "INVALIDATE" }, { SC_AC_OP_LIST_FILES, "LIST FILES" }, { SC_AC_OP_CRYPTO, "CRYPTO" }, { 0, NULL } }; const id2str_t ef_type_name[] = { { SC_FILE_EF_TRANSPARENT, "Transparent" }, { SC_FILE_EF_LINEAR_FIXED, "Linear fixed" }, { SC_FILE_EF_LINEAR_FIXED_TLV, "Linear fixed, SIMPLE-TLV" }, { SC_FILE_EF_LINEAR_VARIABLE, "Linear variable" }, { SC_FILE_EF_LINEAR_VARIABLE_TLV, "Linear variable, SIMPLE-TLV" }, { SC_FILE_EF_CYCLIC, "Cyclic" }, { SC_FILE_EF_CYCLIC_TLV, "Cyclic, SIMPLE-TLV" }, { 0, NULL } }; const char *ef_type = "Unknown"; for (i = 0; ef_type_name[i].str != NULL; i++) if (file->ef_structure == ef_type_name[i].id) ef_type = ef_type_name[i].str; printf("%-15s%s\n", "EF structure:", ef_type); ac_ops = ac_ops_ef; } for (i = 0; ac_ops != NULL && ac_ops[i].str != NULL; i++) { int len = strlen(ac_ops[i].str); printf("ACL for %s:%*s %s\n", ac_ops[i].str, (12 > len) ? (12 - len) : 0, "", util_acl_to_str(sc_file_get_acl_entry(file, ac_ops[i].id))); } if (file->prop_attr_len) { printf("%-25s", "Proprietary attributes:"); util_hex_dump(stdout, file->prop_attr, file->prop_attr_len, " "); printf("\n"); } if (file->sec_attr_len) { printf("%-25s", "Security attributes:"); util_hex_dump(stdout, file->sec_attr, file->sec_attr_len, " "); printf("\n"); } printf("\n"); if (not_current) { sc_file_free(file); select_current_path_or_die(); } return 0; }
int sc_enum_apps(sc_card_t *card) { struct sc_context *ctx = card->ctx; sc_path_t path; int ef_structure; size_t file_size, jj; int r, ii, idx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); if (card->app_count < 0) card->app_count = 0; sc_format_path("3F002F00", &path); if (card->ef_dir != NULL) { sc_file_free(card->ef_dir); card->ef_dir = NULL; } r = sc_select_file(card, &path, &card->ef_dir); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select EF.DIR file"); if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) { sc_file_free(card->ef_dir); card->ef_dir = NULL; SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD, "EF(DIR) is not a working EF."); } ef_structure = card->ef_dir->ef_structure; file_size = card->ef_dir->size; if (file_size == 0) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 0); if (ef_structure == SC_FILE_EF_TRANSPARENT) { u8 *buf = NULL, *p; size_t bufsize; buf = malloc(file_size); if (buf == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); p = buf; r = sc_read_binary(card, 0, buf, file_size, 0); if (r < 0) { free(buf); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_read_binary() failed"); } bufsize = r; while (bufsize > 0) { if (card->app_count == SC_MAX_CARD_APPS) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card"); break; } r = parse_dir_record(card, &p, &bufsize, -1); if (r) break; } if (buf) free(buf); } else { /* record structure */ u8 buf[256], *p; unsigned int rec_nr; size_t rec_size; for (rec_nr = 1; ; rec_nr++) { r = sc_read_record(card, rec_nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r == SC_ERROR_RECORD_NOT_FOUND) break; SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read_record() failed"); if (card->app_count == SC_MAX_CARD_APPS) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many applications on card"); break; } rec_size = r; p = buf; parse_dir_record(card, &p, &rec_size, (int)rec_nr); } } /* Move known PKCS#15 applications to the head of the list */ for (ii=0, idx=0; ii<card->app_count; ii++) { for (jj=0; jj < sizeof(apps)/sizeof(apps[0]); jj++) { if (apps[jj].aid_len != card->app[ii]->aid.len) continue; if (memcmp(apps[jj].aid, card->app[ii]->aid.value, apps[jj].aid_len)) continue; break; } if (ii != idx && jj < sizeof(apps)/sizeof(apps[0])) { struct sc_app_info *tmp = card->app[idx]; card->app[idx] = card->app[ii]; card->app[ii] = tmp; idx++; } } SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, unsigned char **out, size_t *out_len, int verify_pin) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_file *file = NULL; struct sc_path path; size_t sz; int rv; LOG_FUNC_CALLED(ctx); if (!in_path || !out || !out_len) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file"); sc_log(ctx, "read file '%s'; verify_pin:%i", in_path, verify_pin); *out = NULL; *out_len = 0; sc_format_path(in_path, &path); rv = sc_select_file(card, &path, &file); LOG_TEST_RET(ctx, rv, "Cannot select oberthur file to read"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) sz = file->size; else sz = (file->record_length + 2) * file->record_count; *out = calloc(sz, 1); if (*out == NULL) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot read oberthur file"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { rv = sc_read_binary(card, 0, *out, sz, 0); } else { int rec; int offs = 0; int rec_len = file->record_length; for (rec = 1; ; rec++) { rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR); if (rv == SC_ERROR_RECORD_NOT_FOUND) { rv = 0; break; } else if (rv < 0) { break; } rec_len = rv; *(*out + offs) = 'R'; *(*out + offs + 1) = rv; offs += rv + 2; } sz = offs; } sc_log(ctx, "read oberthur file result %i", rv); if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL; const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ); int ii; rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10); LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error"); for (ii=0; ii<rv; ii++) { struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data; sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i", auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method); if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) { pin_obj = objs[ii]; break; } } if (!pin_obj || !pin_obj->content.value) { rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } else { rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len); if (!rv) rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0); } }; sc_file_free(file); if (rv < 0) { free(*out); *out = NULL; *out_len = 0; } *out_len = sz; LOG_FUNC_RETURN(ctx, rv); }
/* * Store a private key */ static int myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r, keybits = key_info->modulus_length; LOG_FUNC_CALLED(ctx); switch (object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); if(key_info->field_length != 0) keybits = key_info->field_length; else key_info->field_length = keybits; break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); break; } sc_log(ctx, "store MyEID key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(card, &key_info->path, &file); LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); LOG_TEST_RET(ctx, r, "No authorisation to store MyEID private key"); if (file) sc_file_free(file); /* Fill in data structure */ memset(&args, 0, sizeof (args)); args.op_type = OP_TYPE_STORE; if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) { //args.key_len_bits = keybits; args.key_type = SC_CARDCTL_MYEID_KEY_RSA; args.pubexp_len = prkey->u.rsa.exponent.len; args.pubexp = prkey->u.rsa.exponent.data; args.primep_len = prkey->u.rsa.p.len; args.primep = prkey->u.rsa.p.data; args.primeq_len = prkey->u.rsa.q.len; args.primeq = prkey->u.rsa.q.data; args.dp1_len = prkey->u.rsa.dmp1.len; args.dp1 = prkey->u.rsa.dmp1.data; args.dq1_len = prkey->u.rsa.dmq1.len; args.dq1 = prkey->u.rsa.dmq1.data; args.invq_len = prkey->u.rsa.iqmp.len; args.invq = prkey->u.rsa.iqmp.data; args.key_len_bits = prkey->u.rsa.modulus.len; args.mod = prkey->u.rsa.modulus.data; } else { args.key_type = SC_CARDCTL_MYEID_KEY_EC; args.d = prkey->u.ec.privateD.data; args.d_len = prkey->u.ec.privateD.len; args.ecpublic_point = prkey->u.ec.ecpointQ.value; args.ecpublic_point_len = prkey->u.ec.ecpointQ.len; args.key_len_bits = prkey->u.ec.params.field_length; } /* Store RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); LOG_FUNC_RETURN(ctx, r); }
/* * Verify a PIN. * * If the code given to us has zero length, this means we * should ask the card reader to obtain the PIN from the * reader's PIN pad */ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const unsigned char *pincode, size_t pinlen) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; int r; sc_card_t *card; struct sc_pin_cmd_data data; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN(%p;len:%i)", pincode, pinlen); /* TODO: verify other authentication objects */ if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_NOT_SUPPORTED; r = _validate_pin(p15card, auth_info, pinlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "PIN value do not conforms the PIN policy"); card = p15card->card; r = sc_lock(card); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (auth_info->path.len > 0) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } /* Initialize arguments */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = auth_info->auth_method; data.pin_reference = auth_info->attrs.pin.reference; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.data = pincode; data.pin1.len = pinlen; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; default: /* assume/hope the card driver knows how to encode the pin */ data.pin1.encoding = 0; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { if (!pincode && !pinlen) data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) data.pin1.prompt = "Please enter SO PIN"; else data.pin1.prompt = "Please enter PIN"; } r = sc_pin_cmd(card, &data, &auth_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen); out: sc_unlock(card); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; unsigned char buff[128]; int r, i; sc_path_t tmppath; set_string (&p15card->tokeninfo->label, "ID-kaart"); set_string (&p15card->tokeninfo->manufacturer_id, "AS Sertifitseerimiskeskus"); /* Select application directory */ sc_format_path ("3f00eeee5044", &tmppath); r = sc_select_file (card, &tmppath, NULL); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "select esteid PD failed"); /* read the serial (document number) */ r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed"); buff[r] = '\0'; set_string (&p15card->tokeninfo->serial_number, (const char *) buff); p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* add certificates */ for (i = 0; i < 2; i++) { static const char *esteid_cert_names[2] = { "Isikutuvastus", "Allkirjastamine"}; static char const *esteid_cert_paths[2] = { "3f00eeeeaace", "3f00eeeeddce"}; static int esteid_cert_ids[2] = {1, 2}; 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] = esteid_cert_ids[i]; cert_info.id.len = 1; sc_format_path(esteid_cert_paths[i], &cert_info.path); strlcpy(cert_obj.label, esteid_cert_names[i], sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; #ifdef ENABLE_OPENSSL if (i == 0) { BIO *mem = NULL; X509 *x509 = NULL; sc_pkcs15_cert_t *cert; char cardholder_name[64]; unsigned char *tmp = NULL; r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert); if (r == SC_SUCCESS) { mem = BIO_new_mem_buf(cert->data.value, cert->data.len); if (!mem) { sc_pkcs15_free_certificate(cert); return SC_ERROR_INTERNAL; } x509 = d2i_X509_bio(mem, NULL); BIO_free(mem); sc_pkcs15_free_certificate(cert); if (!x509) return SC_ERROR_INTERNAL; r = X509_NAME_get_index_by_NID(X509_get_subject_name(x509), NID_commonName, -1); if (r >= 0) { X509_NAME_ENTRY *ne; ASN1_STRING *a_str; ne = X509_NAME_get_entry(X509_get_subject_name(x509), r); if (!ne) { X509_free(x509); return SC_ERROR_INTERNAL; } a_str = X509_NAME_ENTRY_get_data(ne); if (!a_str) { X509_free(x509); return SC_ERROR_INTERNAL; } r = ASN1_STRING_to_UTF8(&tmp, a_str); if (r > 0) { if ((unsigned)r > sizeof(cardholder_name) - 1) r = sizeof(cardholder_name) -1; memcpy(cardholder_name, tmp, r); cardholder_name[r] = '\0'; set_string(&p15card->tokeninfo->label, cardholder_name); OPENSSL_free(tmp); } } X509_free(x509); } } #endif } /* the file with key pin info (tries left) */ sc_format_path ("3f000016", &tmppath); r = sc_select_file (card, &tmppath, NULL); if (r < 0) return SC_ERROR_INTERNAL; /* add pins */ for (i = 0; i < 3; i++) { unsigned char tries_left; static const char *esteid_pin_names[3] = { "PIN1", "PIN2", "PUK" }; static const int esteid_pin_min[3] = {4, 5, 8}; static const int esteid_pin_ref[3] = {1, 2, 0}; static const int esteid_pin_authid[3] = {1, 2, 3}; static const int esteid_pin_flags[3] = {0, 0, SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN}; 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)); /* read the number of tries left for the PIN */ r = sc_read_record (card, i + 1, buff, sizeof(buff), SC_RECORD_BY_REC_NR); if (r < 0) return SC_ERROR_INTERNAL; tries_left = buff[5]; pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = esteid_pin_authid[i]; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = esteid_pin_ref[i]; pin_info.attrs.pin.flags = esteid_pin_flags[i]; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = esteid_pin_min[i]; pin_info.attrs.pin.stored_length = 12; pin_info.attrs.pin.max_length = 12; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = (int)tries_left; pin_info.max_tries = 3; strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label)); pin_obj.flags = esteid_pin_flags[i]; /* Link normal PINs with PUK */ if (i < 2) { pin_obj.auth_id.len = 1; pin_obj.auth_id.value[0] = 3; } r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* add private keys */ for (i = 0; i < 2; i++) { static int prkey_pin[2] = {1, 2}; static int prkey_usage[2] = { SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION}; static const char *prkey_name[2] = { "Isikutuvastus", "Allkirjastamine"}; 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] = prkey_pin[i]; prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = i + 1; if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) prkey_info.modulus_length = 2048; else prkey_info.modulus_length = 1024; strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = prkey_pin[i]; prkey_obj.user_consent = 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } return SC_SUCCESS; }