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; }
/* * Store a private key */ static int myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object) { 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_file *file = NULL; int keybits = key_info->modulus_length, r; LOG_FUNC_CALLED(card->ctx); /* 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: /* Here the information about curve is not available, that's why algorithm is checked without curve OID. */ if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); break; } sc_log(ctx, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id)); /* Get the private key file */ r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file); LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file"); if (!file || !file->path.len) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine private key file"); sc_log(ctx, "Key file size %d", keybits); file->size = keybits; if (object->type == SC_PKCS15_TYPE_PRKEY_RSA) file->ef_structure = SC_CARDCTL_MYEID_KEY_RSA; else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) file->ef_structure = SC_CARDCTL_MYEID_KEY_EC; memcpy(&key_info->path.value, &file->path.value, file->path.len); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; sc_log(ctx, "Path of MyEID private key file to create %s", sc_print_path(&file->path)); /* Now create the key file */ r = sc_pkcs15init_create_file(profile, p15card, file); sc_file_free(file); LOG_TEST_RET(ctx, r, "Cannot create MyEID private key file"); LOG_FUNC_RETURN(ctx, r); }
int iasecc_sm_sdo_update(struct sc_card *card, unsigned se_num, struct iasecc_sdo_update *update) { struct sc_context *ctx = card->ctx; #ifdef ENABLE_SM struct sm_info *sm_info = &card->sm_ctx.info; struct sc_remote_data rdata; int rv; LOG_FUNC_CALLED(ctx); sc_log(ctx, "iasecc_sm_sdo_update() SE#%i, SDO(class:0x%X,ref:%i)", se_num, update->sdo_class, update->sdo_ref); rv = iasecc_sm_initialize(card, se_num, SM_CMD_SDO_UPDATE); LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM INITIALIZE failed"); sc_log(ctx, "current DF '%s'", sc_print_path(&sm_info->current_path_df)); sm_info->cmd_data = update; sc_remote_data_init(&rdata); rv = iasecc_sm_cmd(card, &rdata); LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM 'SDO UPDATE' failed"); rv = sm_release (card, &rdata, NULL, 0); LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM release failed"); rdata.free(&rdata); LOG_FUNC_RETURN(ctx, rv); #else LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging"); return SC_ERROR_NOT_SUPPORTED; #endif }
static void print_cert_info(const struct sc_pkcs15_object *obj) { struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) obj->data; struct sc_pkcs15_cert *cert_parsed = NULL; char guid[39]; int rv; printf("X.509 Certificate [%s]\n", obj->label); print_common_flags(obj); printf("\tAuthority : %s\n", cert_info->authority ? "yes" : "no"); printf("\tPath : %s\n", sc_print_path(&cert_info->path)); printf("\tID : %s\n", sc_pkcs15_print_id(&cert_info->id)); rv = sc_pkcs15_get_guid(p15card, obj, guid, sizeof(guid)); if (!rv) printf("\tGUID : %s\n", guid); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); rv = sc_pkcs15_read_certificate(p15card, cert_info, &cert_parsed); if (rv >= 0 && cert_parsed) { printf("\tEncoded serial : %02X %02X ", *(cert_parsed->serial), *(cert_parsed->serial + 1)); util_hex_dump(stdout, cert_parsed->serial + 2, cert_parsed->serial_len - 2, ""); printf("\n"); sc_pkcs15_free_certificate(cert_parsed); } }
/* * On-board key generation. */ static int gpk_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, 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; sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "path=%s, %d bits\n", sc_print_path(&key_info->path), key_info->modulus_length); if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "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(p15card->card, &key_info->path, &keyfile)) < 0) return r; #ifndef PK_INIT_IMMEDIATELY r = gpk_pkfile_init_public(profile, p15card, keyfile, SC_ALGORITHM_RSA, keybits, key_info->usage); if (r < 0) { sc_file_free(keyfile); return r; } if ((r = gpk_pkfile_init_private(p15card->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(p15card->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(p15card->card, &pubkey->u.rsa); }
/* * Store a private key */ static int miocos_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *key) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_pkcs15_prkey_rsa *rsa; struct sc_file *file = NULL; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA || key->algorithm != SC_ALGORITHM_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); rsa = &key->u.rsa; if (rsa->modulus.len != 128) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(p15card->card, &key_info->path, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store private key"); r = miocos_update_private_key(profile, p15card->card, rsa); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
/* * 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; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); /* Check that the card supports the requested modulus length */ if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "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); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store MyEID key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store MyEID private key"); if (file) sc_file_free(file); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; args.op_type = OP_TYPE_STORE; 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.mod_len = prkey->u.rsa.modulus.len; args.mod = prkey->u.rsa.modulus.data; /* Store RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
void sc_print_cache(struct sc_card *card) { struct sc_context *ctx = NULL; assert(card != NULL); ctx = card->ctx; if (!card->cache.valid || (!card->cache.current_ef && !card->cache.current_df)) { sc_log(ctx, "card cache invalid"); return; } if (card->cache.current_ef) sc_log(ctx, "current_ef(type=%i) %s", card->cache.current_ef->path.type, sc_print_path(&card->cache.current_ef->path)); if (card->cache.current_df) sc_log(ctx, "current_df(type=%i, aid_len=%i) %s", card->cache.current_df->path.type, card->cache.current_df->path.aid.len, sc_print_path(&card->cache.current_df->path)); }
/* * Create a new PIN */ static int setcos_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df, sc_pkcs15_object_t *pin_obj, const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len) { struct sc_context *ctx = p15card->card->ctx; sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data; sc_file_t *pinfile = NULL; int r, ignore_ac = 0; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; /* Create the global pin file if it doesn't exist yet */ r = sc_profile_get_file(profile, "pinfile", &pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No 'pinfile' template in profile"); r = sc_select_file(p15card->card, &pinfile->path, &pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select 'pinfile'"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "pinfile->status:%X", pinfile->status); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create PIN with reference:%X, flags:%X, path:%s", auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, sc_print_path(&auth_info->path)); if (pinfile->status == SC_FILE_STATUS_CREATION) ignore_ac = 1; r = setcos_create_pin_internal(profile, p15card, ignore_ac, auth_info, pin, pin_len, puk, puk_len); /* If pinfile is in 'Creation' state and SOPIN has been created, * change status of MF and 'pinfile' to 'Operational:Activated' */ if (ignore_ac && (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)) { sc_file_t *mf = profile->mf_info->file; r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_ACTIVATE_FILE, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot set 'pinfile' into the activated state"); r = sc_select_file(p15card->card, &mf->path, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select MF"); r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_ACTIVATE_FILE, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot set MF into the activated state"); } sc_file_free(pinfile); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static void print_prkey_info(const struct sc_pkcs15_object *obj) { unsigned int i; struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; const char *types[] = { "", "RSA", "DSA", "GOSTR3410", "EC", "", "", "" }; const char *usages[] = { "encrypt", "decrypt", "sign", "signRecover", "wrap", "unwrap", "verify", "verifyRecover", "derive", "nonRepudiation" }; const size_t usage_count = NELEMENTS(usages); const char *access_flags[] = { "sensitive", "extract", "alwaysSensitive", "neverExtract", "local" }; const unsigned int af_count = NELEMENTS(access_flags); char guid[39]; printf("Private %s Key [%s]\n", types[7 & obj->type], obj->label); print_common_flags(obj); printf("\tUsage : [0x%X]", prkey->usage); for (i = 0; i < usage_count; i++) if (prkey->usage & (1 << i)) { printf(", %s", usages[i]); } printf("\n"); printf("\tAccess Flags : [0x%X]", prkey->access_flags); for (i = 0; i < af_count; i++) if (prkey->access_flags & (1 << i)) printf(", %s", access_flags[i]); printf("\n"); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); if (prkey->modulus_length) printf("\tModLength : %lu\n", (unsigned long)prkey->modulus_length); else printf("\tFieldLength : %lu\n", (unsigned long)prkey->field_length); printf("\tKey ref : %d (0x%X)\n", prkey->key_reference, prkey->key_reference); printf("\tNative : %s\n", prkey->native ? "yes" : "no"); if (prkey->path.len || prkey->path.aid.len) printf("\tPath : %s\n", sc_print_path(&prkey->path)); if (obj->auth_id.len != 0) printf("\tAuth ID : %s\n", sc_pkcs15_print_id(&obj->auth_id)); printf("\tID : %s\n", sc_pkcs15_print_id(&prkey->id)); if (!sc_pkcs15_get_guid(p15card, obj, guid, sizeof(guid))) printf("\tGUID : %s\n", guid); }
/* * Delete object * * Applied to private key: used to delete public part internal file */ static int rtecp_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const struct sc_path *path) { sc_context_t *ctx; sc_file_t *df; sc_path_t pubkey_path; int key_ref; int r; if (!profile || !p15card || !p15card->card || !p15card->card->ctx) return SC_ERROR_INVALID_ARGUMENTS; ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); sc_log(ctx, "delete object: type %X, path %s", obj->type, sc_print_path(path)); if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); key_ref = ((struct sc_pkcs15_prkey_info *)obj->data)->key_reference; sc_log(ctx, "key reference %04i", key_ref); r = sc_profile_get_file(profile, "PuKey-DF", &df); LOG_TEST_RET(ctx, r, "Get PuKey-DF info failed"); pubkey_path = df->path; sc_file_free(df); r = sc_append_file_id(&pubkey_path, key_ref); LOG_TEST_RET(ctx, r, "Append ID to file failed"); sc_log(ctx, "delete pubkey file %s", sc_print_path(&pubkey_path)); r = sc_pkcs15init_delete_by_path(profile, p15card, &pubkey_path); if (r && r != SC_ERROR_FILE_NOT_FOUND) LOG_FUNC_RETURN(ctx, r); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); }
static int list_data_objects(void) { int r, i, count; struct sc_pkcs15_object *objs[32]; r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32); if (r < 0) { fprintf(stderr, "Data object enumeration failed: %s\n", sc_strerror(r)); return 1; } count = r; for (i = 0; i < count; i++) { int idx; struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; printf("Reading data object <%i>\n", i); printf("applicationName: %s\n", cinfo->app_label); printf("Label: %s\n", objs[i]->label); printf("applicationOID: "); if (cinfo->app_oid.value[0] >= 0) { printf("%i", cinfo->app_oid.value[0]); idx = 1; while (idx < SC_MAX_OBJECT_ID_OCTETS) { if (cinfo->app_oid.value[idx] < 0) break; printf(".%i", cinfo->app_oid.value[idx++]); } printf("\n"); } else printf("NONE\n"); printf("Path: %s\n", sc_print_path(&cinfo->path)); if (objs[i]->auth_id.len == 0) { struct sc_pkcs15_data *data_object; r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object); if (r) { fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r)); if (r == SC_ERROR_FILE_NOT_FOUND) continue; /* DEE emulation may say there is a file */ return 1; } r = list_data_object("Data Object", data_object->data, data_object->data_len); sc_pkcs15_free_data_object(data_object); } else { printf("Auth ID: %s\n", sc_pkcs15_print_id(&objs[i]->auth_id)); } } return 0; }
/* * Store a private key */ static int setcos_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_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_cardctl_setcos_gen_store_key_info args; struct sc_file *file = NULL; int r, keybits = key_info->modulus_length; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); /* Parameter check */ if ( (keybits < 512) || (keybits > 1024) || (keybits & 0x7)) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Invalid key length"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(p15card->card, &key_info->path, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store private key"); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; args.op_type = OP_TYPE_STORE; args.pubexp_len = prkey->u.rsa.exponent.len * 8; args.pubexp = prkey->u.rsa.exponent.data; args.primep_len = prkey->u.rsa.p.len * 8; args.primep = prkey->u.rsa.p.data; args.primeq_len = prkey->u.rsa.q.len * 8; args.primeq = prkey->u.rsa.q.data; /* Generate/store rsa key */ r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GENERATE_STORE_KEY, &args); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Card control 'GENERATE_STORE_KEY' failed"); if (file) sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static void print_pubkey_info(const struct sc_pkcs15_object *obj) { unsigned int i; const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data; const char *types[] = { "", "RSA", "DSA", "GOSTR3410" }; const char *usages[] = { "encrypt", "decrypt", "sign", "signRecover", "wrap", "unwrap", "verify", "verifyRecover", "derive", "nonRepudiation" }; const unsigned int usage_count = NELEMENTS(usages); const char *access_flags[] = { "sensitive", "extract", "alwaysSensitive", "neverExtract", "local" }; const unsigned int af_count = NELEMENTS(access_flags); printf("Public %s Key [%s]\n", types[3 & obj->type], obj->label); print_common_flags(obj); printf("\tUsage : [0x%X]", pubkey->usage); for (i = 0; i < usage_count; i++) if (pubkey->usage & (1 << i)) { printf(", %s", usages[i]); } printf("\n"); printf("\tAccess Flags : [0x%X]", pubkey->access_flags); for (i = 0; i < af_count; i++) { if (pubkey->access_flags & (1 << i)) { printf(", %s", access_flags[i]); } } print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); printf("\n"); printf("\tModLength : %lu\n", (unsigned long)pubkey->modulus_length); printf("\tKey ref : %d\n", pubkey->key_reference); printf("\tNative : %s\n", pubkey->native ? "yes" : "no"); printf("\tPath : %s\n", sc_print_path(&pubkey->path)); if (obj->auth_id.len != 0) printf("\tAuth ID : %s\n", sc_pkcs15_print_id(&obj->auth_id)); printf("\tID : %s\n", sc_pkcs15_print_id(&pubkey->id)); }
int sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata) { struct sc_serial_number sn = sm_info->serialnr; struct sm_gp_session *gp_session = &sm_info->session.gp; struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset; struct sc_remote_apdu *new_rapdu = NULL; struct sc_apdu *apdu = NULL; int rv; LOG_FUNC_CALLED(ctx); sc_debug(ctx, SC_LOG_DEBUG_SM, "SM GP initialize: serial:%s", sc_dump_hex(sn.value, sn.len)); sc_debug(ctx, SC_LOG_DEBUG_SM, "SM GP initialize: current_df_path %s", sc_print_path(&sm_info->current_path_df)); sc_debug(ctx, SC_LOG_DEBUG_SM, "SM GP initialize: KMC length %i", gp_keyset->kmc_len); if (!rdata || !rdata->alloc) LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); rv = rdata->alloc(rdata, &new_rapdu); LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU"); apdu = &new_rapdu->apdu; rv = RAND_bytes(gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN); if (!rv) LOG_FUNC_RETURN(ctx, SC_ERROR_SM_RAND_FAILED); apdu->cse = SC_APDU_CASE_4_SHORT; apdu->cla = 0x80; apdu->ins = 0x50; apdu->p1 = 0x0; apdu->p2 = 0x0; apdu->lc = SM_SMALL_CHALLENGE_LEN; apdu->le = 0x1C; apdu->datalen = SM_SMALL_CHALLENGE_LEN; memcpy(&new_rapdu->sbuf[0], gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
/* * Store a private key */ static int myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object) { 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_file *file = NULL; int keybits = key_info->modulus_length, r; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* Check that the card supports the requested modulus length */ if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create MyEID private key ID:%s", sc_pkcs15_print_id(&key_info->id)); /* Get the private key file */ r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get new MyEID private key file"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key file size %d", keybits); file->size = keybits; memcpy(&key_info->path.value, &file->path.value, file->path.len); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Path of MyEID private key file to create %s", sc_print_path(&file->path)); /* Now create the key file */ r = sc_pkcs15init_create_file(profile, p15card, file); sc_file_free(file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot create MyEID private key file"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card) { u8 buf[1024]; sc_pkcs15_df_t *df; sc_pkcs15_object_t *p15_obj; size_t len = sizeof(buf); int rv; sc_context_t *ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); /* Check for correct card driver (i.e. iso7816) */ if (strcmp(p15card->card->driver->short_name, "dnie") != 0) return SC_ERROR_WRONG_CARD; /* Check for correct card atr */ if (dnie_match_card(p15card->card) != 1) return SC_ERROR_WRONG_CARD; /* Set root path of this application */ p15card->file_app = sc_file_new(); sc_format_path("3F00", &p15card->file_app->path); /* Load TokenInfo */ rv = dump_ef(p15card->card, "3F0050155032", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo, buf, len); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } /* Only accept the original stuff */ if (strcmp(p15card->tokeninfo->manufacturer_id, "DGP-FNMT") != 0) LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_CARD); /* Load ODF */ rv = dump_ef(p15card->card, "3F0050155031", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } rv = parse_odf(buf, len, p15card); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } /* Decode EF.PrKDF, EF.PuKDF and EF.CDF */ for (df = p15card->df_list; df != NULL; df = df->next) { if (df->type == SC_PKCS15_PRKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PrKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_PUKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PuKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_CDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.CDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_DODF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.DODF (%s) failed: %d", sc_print_path(&df->path), rv); } } } /* Perform required fixes */ p15_obj = p15card->obj_list; while (p15_obj != NULL) { /* Add missing 'auth_id' to private objects */ if ((p15_obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) && (p15_obj->auth_id.len == 0)) { p15_obj->auth_id.value[0] = 0x01; p15_obj->auth_id.len = 1; } /* Remove found public keys as cannot be read_binary()'d */ if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) { sc_pkcs15_object_t *puk = p15_obj; p15_obj = p15_obj->next; sc_pkcs15_remove_object(p15card, puk); sc_pkcs15_free_object(puk); } else { p15_obj = p15_obj->next; } } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info info; int r; size_t flags_len = sizeof(info.attrs.pin.flags); size_t padchar_len = 1; struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; struct sc_asn1_entry asn1_pin[2]; struct sc_asn1_pkcs15_object pin_obj = { obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_ASN1); sc_copy_asn1_entry(c_asn1_pin, asn1_pin); sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr); sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr); sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr); sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 0); sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 0, &info.attrs.pin.flags, &flags_len, 0); sc_format_asn1_entry(asn1_pin_attr + 1, &info.attrs.pin.type, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 2, &info.attrs.pin.min_length, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 3, &info.attrs.pin.stored_length, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 4, &info.attrs.pin.max_length, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 5, &info.attrs.pin.reference, NULL, 0); sc_format_asn1_entry(asn1_pin_attr + 6, &info.attrs.pin.pad_char, &padchar_len, 0); /* We don't support lastPinChange yet. */ sc_format_asn1_entry(asn1_pin_attr + 8, &info.path, NULL, 0); sc_format_asn1_entry(asn1_com_ao_attr + 0, &info.auth_id, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; info.tries_left = -1; r = sc_asn1_decode(ctx, asn1_pin, *buf, *buflen, buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 decoding failed"); obj->type = SC_PKCS15_TYPE_AUTH_PIN; obj->data = malloc(sizeof(info)); if (obj->data == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); if (info.attrs.pin.max_length == 0) { if (p15card->card->max_pin_len != 0) info.attrs.pin.max_length = p15card->card->max_pin_len; else if (info.attrs.pin.stored_length != 0) info.attrs.pin.max_length = info.attrs.pin.type != SC_PKCS15_PIN_TYPE_BCD ? info.attrs.pin.stored_length : 2 * info.attrs.pin.stored_length; else info.attrs.pin.max_length = 8; /* shouldn't happen */ } /* OpenSC 0.11.4 and older encoded "pinReference" as a negative value. Fixed in 0.11.5 we need to add a hack, so old cards continue to work. The same invalid encoding has some models of the proprietary PKCS#15 cards. */ if (info.attrs.pin.reference < 0) info.attrs.pin.reference += 256; info.auth_method = SC_AC_CHV; if (info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_LOCAL) { /* In OpenSC pkcs#15 framework 'path' is mandatory for the 'Local' PINs. * If 'path' do not present in PinAttributes, * derive it from the PKCS#15 context. */ if (!info.path.len) { /* Give priority to AID defined in the application DDO */ if (p15card->app && p15card->app->ddo.aid.len) info.path.aid = p15card->app->ddo.aid; else if (p15card->file_app->path.len) info.path = p15card->file_app->path; } } sc_debug(ctx, SC_LOG_DEBUG_ASN1, "decoded PIN(ref:%X,path:%s)", info.attrs.pin.reference, sc_print_path(&info.path)); memcpy(obj->data, &info, sizeof(info)); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_SUCCESS); }
static int jpki_select_file(struct sc_card *card, const struct sc_path *path, struct sc_file **file_out) { struct jpki_private_data *drvdata = JPKI_DRVDATA(card); int rc; sc_apdu_t apdu; struct sc_file *file = NULL; LOG_FUNC_CALLED(card->ctx); sc_log(card->ctx, "jpki_select_file: path=%s, len=%"SC_FORMAT_LEN_SIZE_T"u", sc_print_path(path), path->len); if (path->len == 2 && memcmp(path->value, "\x3F\x00", 2) == 0) { drvdata->selected = SELECT_MF; if (file_out) { sc_file_dup(file_out, drvdata->mf); if (*file_out == NULL) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } } return 0; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0); switch (path->type) { case SC_PATH_TYPE_FILE_ID: apdu.p1 = 2; break; case SC_PATH_TYPE_DF_NAME: apdu.p1 = 4; break; default: LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); } apdu.p2 = 0x0C; apdu.data = path->value; apdu.datalen = path->len; apdu.lc = path->len; rc = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, rc, "APDU transmit failed"); rc = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_RET(card->ctx, rc, "SW Check failed"); if (!file_out) { LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } /* read certificate file size */ if (path->len == 2 && ( memcmp(path->value, "\x00\x0A", 2) == 0 || memcmp(path->value, "\x00\x01", 2) == 0 || memcmp(path->value, "\x00\x0B", 2) == 0 || memcmp(path->value, "\x00\x02", 2) == 0 ) ) { u8 buf[4]; rc = sc_read_binary(card, 0, buf, 4, 0); LOG_TEST_RET(card->ctx, rc, "SW Check failed"); file = sc_file_new(); if (!file) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } file->path = *path; file->size = (buf[2] << 8 | buf[3]) + 4; *file_out = file; } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int print_file(sc_card_t *in_card, const sc_file_t *file, const sc_path_t *path, int depth) { int r; const char *tmps; const char *ac_ops_df[] = { "select", "lock", "delete", "create", "rehab", "inval", "list" }; const char *ac_ops_ef[] = { "read", "update", "write", "erase", "rehab", "inval" }; for (r = 0; r < depth; r++) printf(" "); printf("%s ", sc_print_path(path)); if (file->namelen) { printf("["); print_binary(stdout, file->name, file->namelen); printf("] "); } switch (file->type) { case SC_FILE_TYPE_WORKING_EF: tmps = "wEF"; break; case SC_FILE_TYPE_INTERNAL_EF: tmps = "iEF"; break; case SC_FILE_TYPE_DF: tmps = " DF"; break; default: tmps = "unknown"; break; } printf("type: %-3s, ", tmps); if (file->type != SC_FILE_TYPE_DF) { const char *structs[] = { "unknown", "transpnt", "linrfix", "linrfix(TLV)", "linvar", "linvar(TLV)", "lincyc", "lincyc(TLV)" }; int ef_type = file->ef_structure; if (ef_type < 0 || ef_type > 7) ef_type = 0; /* invalid or unknow ef type */ printf("ef structure: %s, ", structs[ef_type]); } printf("size: %lu\n", (unsigned long) file->size); for (r = 0; r < depth; r++) printf(" "); if (file->type == SC_FILE_TYPE_DF) for (r = 0; r < (int) (sizeof(ac_ops_df)/sizeof(ac_ops_df[0])); r++) printf("%s[%s] ", ac_ops_df[r], acl_to_str(sc_file_get_acl_entry(file, r))); else for (r = 0; r < (int) (sizeof(ac_ops_ef)/sizeof(ac_ops_ef[0])); r++) printf("%s[%s] ", ac_ops_ef[r], acl_to_str(sc_file_get_acl_entry(file, r))); if (file->sec_attr_len) { printf("sec: "); /* Octets are as follows: * DF: select, lock, delete, create, rehab, inval * EF: read, update, write, erase, rehab, inval * 4 MSB's of the octet mean: * 0 = ALW, 1 = PIN1, 2 = PIN2, 4 = SYS, * 15 = NEV */ hex_dump(stdout, file->sec_attr, file->sec_attr_len, ":"); } if (file->prop_attr_len) { printf("\n"); for (r = 0; r < depth; r++) printf(" "); printf("prop: "); hex_dump(stdout, file->prop_attr, file->prop_attr_len, ":"); } printf("\n\n"); if (file->type == SC_FILE_TYPE_DF) return 0; if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { unsigned char *buf; if (!(buf = (unsigned char *) malloc(file->size))) { fprintf(stderr, "out of memory"); return 1; } r = sc_read_binary(in_card, 0, buf, file->size, 0); if (r > 0) hex_dump_asc(stdout, buf, r, 0); free(buf); } else { unsigned char buf[256]; int i; for (i=0; i < file->record_count; i++) { printf("Record %d\n", i); r = sc_read_record(in_card, i, buf, 256, 0); if (r > 0) hex_dump_asc(stdout, buf, r, 0); } } return 0; }
/* * Create private key file */ static int miocos_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_file *file; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); if (key_info->modulus_length != 1024) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "MioCOS supports only 1024-bit RSA keys."); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create private key ID:%s\n", sc_pkcs15_print_id(&key_info->id)); r = miocos_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot create key: failed to allocate new key object"); memcpy(&file->path, &key_info->path, sizeof(file->path)); file->id = file->path.value[file->path.len - 2] * 0x100 + file->path.value[file->path.len - 1]; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Path of private key file to create %s\n", sc_print_path(&file->path)); r = sc_pkcs15init_create_file(profile, p15card, file); sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
LIBOPENSC_API int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 *in, size_t inlen, u8 *out, size_t outlen) { sc_context_t *ctx = p15card->card->ctx; int r; sc_security_env_t senv; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; u8 buf[1024], *tmp; size_t modlen; unsigned long pad_flags = 0, sec_flags = 0; LOG_FUNC_CALLED(ctx); sc_log(ctx, "security operation flags 0x%X", flags); memset(&senv, 0, sizeof(senv)); /* Card driver should have the access to supported algorithms from 'tokenInfo'. So that * it can get value of card specific 'AlgorithmInfo::algRef'. */ memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos)); if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private key"); /* If the key is not native, we can't operate with it. */ if (!prkey->native) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it"); if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for signing"); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: modlen = prkey->modulus_length / 8; alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_RSA; break; case SC_PKCS15_TYPE_PRKEY_GOSTR3410: modlen = (prkey->modulus_length + 7) / 8 * 2; alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_GOSTR3410; break; case SC_PKCS15_TYPE_PRKEY_EC: modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.algorithm = SC_ALGORITHM_EC; senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT; senv.algorithm_ref = prkey->field_length; break; /* add other crypto types here */ default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported"); } /* Probably never happens, but better make sure */ if (inlen > sizeof(buf) || outlen < modlen) LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); memcpy(buf, in, inlen); /* revert data to sign when signing with the GOST key. * TODO: can it be confirmed by the GOST standard? * TODO: tested with RuTokenECP, has to be validated for RuToken. */ if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410) sc_mem_reverse(buf, inlen); tmp = buf; /* flags: the requested algo * algo_info->flags: what is supported by the card * senv.algorithm_flags: what the card will have to do */ /* if the card has SC_ALGORITHM_NEED_USAGE set, and the key is for signing and decryption, we need to emulate signing */ /* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */ sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage); if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) && ((prkey->usage & USAGE_ANY_SIGN) && (prkey->usage & USAGE_ANY_DECIPHER)) ) { size_t tmplen = sizeof(buf); if (flags & SC_ALGORITHM_RSA_RAW) { r = sc_pkcs15_decipher(p15card, obj,flags, in, inlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } if (modlen > tmplen) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!"); r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen); /* no padding needed - already done */ flags &= ~SC_ALGORITHM_RSA_PADS; /* instead use raw rsa */ flags |= SC_ALGORITHM_RSA_RAW; LOG_TEST_RET(ctx, r, "Unable to add padding"); r = sc_pkcs15_decipher(p15card, obj,flags, buf, modlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } /* If the card doesn't support the requested algorithm, see if we * can strip the input so a more restrictive algo can be used */ if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && !(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) { unsigned int algo; size_t tmplen = sizeof(buf); r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen); if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); } flags &= ~SC_ALGORITHM_RSA_HASH_NONE; flags |= algo; inlen = tmplen; } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); if (r != SC_SUCCESS) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, r); } senv.algorithm_flags = sec_flags; sc_log(ctx, "DEE flags:0x%8.8x alg_info->flags:0x%8.8x pad:0x%8.8x sec:0x%8.8x", flags, alg_info->flags, pad_flags, sec_flags); /* add the padding bytes (if necessary) */ if (pad_flags != 0) { size_t tmplen = sizeof(buf); r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding"); inlen = tmplen; } else if ( senv.algorithm == SC_ALGORITHM_RSA && (flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { /* Add zero-padding if input is shorter than the modulus */ if (inlen < modlen) { if (modlen > sizeof(buf)) return SC_ERROR_BUFFER_TOO_SMALL; memmove(tmp+modlen-inlen, tmp, inlen); memset(tmp, 0, modlen-inlen); } inlen = modlen; } senv.operation = SC_SEC_OPERATION_SIGN; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } r = sc_lock(p15card->card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); sc_log(ctx, "Private key path '%s'", sc_print_path(&prkey->path)); if (prkey->path.len != 0 || prkey->path.aid.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_set_security_env() failed"); } r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS) r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); sc_mem_clear(buf, sizeof(buf)); sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_compute_signature() failed"); LOG_FUNC_RETURN(ctx, r); }
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: /* EC is supported in MyEID v > 3.5. TODO: set correct return value if older MyEID version. */ /* Here the information about curve is not available, that's why supported algorithm is checked without curve OID. */ if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == 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) { struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; sc_log(ctx, "curve '%s', len %i, oid '%s'", ecparams->named_curve, ecparams->field_length, sc_dump_oid(&(ecparams->id))); 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"); if (pubkey->u.ec.ecpointQ.value) free(pubkey->u.ec.ecpointQ.value); pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2); if (pubkey->u.ec.ecpointQ.value == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2); pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; if (pubkey->u.ec.params.named_curve) free(pubkey->u.ec.params.named_curve); pubkey->u.ec.params.named_curve = NULL; if (pubkey->u.ec.params.der.value) free(pubkey->u.ec.params.der.value); pubkey->u.ec.params.der.value = NULL; pubkey->u.ec.params.der.len = 0; pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve); if (!pubkey->u.ec.params.named_curve) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); LOG_TEST_RET(ctx, r, "Cannot fix EC parameters"); } } if (file) sc_file_free(file); LOG_FUNC_RETURN(ctx, r); }
/* * 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: LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); 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); }
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: LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); 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"); /* * TODO DEE - this looks like a bug... * pubkey->u.ec.ecpointQ.value is just value. "04||X||Y" * pubkey->data.value should be DER OCTET STRING * but * pubkey->data.value looks like TLV with TAG if 0x86 * and single byte length. * Could call sc_pkcs15_encode_pubkey * to set pubkey->data.value */ 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) { u8 buf[1024]; sc_pkcs15_df_t *df; sc_pkcs15_object_t *p15_obj; sc_path_t path; struct sc_file *file = NULL; size_t len; int rv; int i; sc_context_t *ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); /* Check for correct card atr */ if (pteid_detect_card(p15card->card) != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_log(p15card->card->ctx, "Selecting application DF"); sc_format_path("4F00", &path); rv = sc_select_file(p15card->card, &path, &file); if (rv != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; /* Load TokenInfo */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005032", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } memset(p15card->tokeninfo, 0, sizeof(*p15card->tokeninfo)); rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo, buf, len); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* Load ODF */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005031", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } rv = parse_odf(buf, len, p15card); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } /* Decode EF.PrKDF, EF.PuKDF, EF.CDF and EF.AODF */ for (df = p15card->df_list; df != NULL; df = df->next) { if (df->type == SC_PKCS15_PRKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PrKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_PUKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PuKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_CDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.CDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_AODF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.AODF (%s) failed: %d", sc_print_path(&df->path), rv); } } } p15_obj = p15card->obj_list; while (p15_obj != NULL) { if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PRKDF) ) { struct sc_pkcs15_prkey_info *prkey_info = (sc_pkcs15_prkey_info_t *) p15_obj->data; prkey_info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_LOCAL; p15_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE; } if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_AODF) ) { static const char *pteid_pin_names[3] = { "Auth PIN", "Sign PIN", "Address PIN" }; struct sc_pin_cmd_data pin_cmd_data; struct sc_pkcs15_auth_info *pin_info = (sc_pkcs15_auth_info_t *) p15_obj->data; strlcpy(p15_obj->label, pteid_pin_names[pin_info->auth_id.value[0]-1], sizeof(p15_obj->label)); pin_info->attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING; pin_info->tries_left = -1; pin_info->max_tries = 3; pin_info->auth_method = SC_AC_CHV; memset(&pin_cmd_data, 0, sizeof(pin_cmd_data)); pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO; pin_cmd_data.pin_type = pin_info->attrs.pin.type; pin_cmd_data.pin_reference = pin_info->attrs.pin.reference; rv = sc_pin_cmd(p15card->card, &pin_cmd_data, NULL); if (rv == SC_SUCCESS) { pin_info->tries_left = pin_cmd_data.pin1.tries_left; pin_info->logged_in = pin_cmd_data.pin1.logged_in; } } /* Remove found public keys as cannot be read_binary()'d */ if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) { sc_pkcs15_object_t *puk = p15_obj; p15_obj = p15_obj->next; sc_pkcs15_remove_object(p15card, puk); sc_pkcs15_free_object(puk); } else { p15_obj = p15_obj->next; } } /* Add data objects */ for (i = 0; i < 5; i++) { static const char *object_labels[5] = { "Trace", "Citizen Data", "Citizen Address Data", "SOd", "Citizen Notepad", }; static const char *object_authids[5] = {NULL, NULL, "3", NULL, NULL}; static const char *object_paths[5] = { "3f000003", "3f005f00ef02", "3f005f00ef05", "3f005f00ef06", "3f005f00ef07", }; static const int object_flags[5] = { 0, 0, SC_PKCS15_CO_FLAG_PRIVATE, 0, 0, }; struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_format_path(object_paths[i], &obj_info.path); strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); if (object_authids[i] != NULL) sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id); strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); obj_obj.flags = object_flags[i]; rv = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (rv != SC_SUCCESS){ sc_log(ctx, "Object add failed: %d", rv); break; } } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_cert_info info; struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4], asn1_x509_cert_attr[2], asn1_type_cert_attr[2], asn1_cert[2], asn1_x509_cert_value_choice[3]; struct sc_asn1_pkcs15_object cert_obj = { obj, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; sc_pkcs15_der_t *der = &info.value; u8 id_value[128]; int id_type; size_t id_value_len = sizeof(id_value); int r; sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident); sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr); sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr); sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice); sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr); sc_copy_asn1_entry(c_asn1_cert, asn1_cert); sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0); sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0); sc_format_asn1_entry(asn1_com_cert_attr + 0, &info.id, NULL, 0); sc_format_asn1_entry(asn1_com_cert_attr + 1, &info.authority, NULL, 0); sc_format_asn1_entry(asn1_com_cert_attr + 2, asn1_cred_ident, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_attr + 0, asn1_x509_cert_value_choice, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_type_cert_attr + 0, asn1_x509_cert_attr, NULL, 0); sc_format_asn1_entry(asn1_cert + 0, &cert_obj, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); info.authority = 0; r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen); /* In case of error, trash the cert value (direct coding) */ if (r < 0 && der->value) free(der->value); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); if (!p15card->app || !p15card->app->ddo.aid.len) { r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); LOG_TEST_RET(ctx, r, "Cannot make absolute path"); } else { info.path.aid = p15card->app->ddo.aid; } sc_log(ctx, "Certificate path '%s'", sc_print_path(&info.path)); obj->type = SC_PKCS15_TYPE_CERT_X509; obj->data = malloc(sizeof(info)); if (obj->data == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); return 0; }
int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_pubkey_info info; int r, gostr3410_params[3]; struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; size_t usage_len = sizeof(info.usage); size_t af_len = sizeof(info.access_flags); struct sc_pkcs15_der *der = &obj->content; struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE]; struct sc_asn1_entry asn1_com_pubkey_attr[C_ASN1_COM_PUBKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE]; struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE]; struct sc_asn1_pkcs15_object rsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; struct sc_asn1_pkcs15_object eckey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_ec_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; struct sc_asn1_pkcs15_object gostr3410key_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_gostr3410_type_attr }; sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice); sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr); sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice); sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); sc_format_asn1_entry(asn1_com_pubkey_attr + 0, &info.subject.value, &info.subject.len, 0); sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 3, &eckey_obj, NULL, 0); sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 0); sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_rsakey_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 0); sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 0); sc_format_asn1_entry(asn1_eckey_value_choice + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_eckey_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 0); sc_format_asn1_entry(asn1_eckey_attr + 1, &info.field_length, NULL, 0); sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 0); sc_format_asn1_entry(asn1_dsakey_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &gostr3410_params[0], NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &gostr3410_params[1], NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &gostr3410_params[2], NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0); sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0); sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0); sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); info.key_reference = -1; info.native = 1; memset(gostr3410_params, 0, sizeof(gostr3410_params)); r = sc_asn1_decode(ctx, asn1_pubkey, *buf, *buflen, buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); if (asn1_pubkey_choice[0].flags & SC_ASN1_PRESENT) { obj->type = SC_PKCS15_TYPE_PUBKEY_RSA; } else if (asn1_pubkey_choice[2].flags & SC_ASN1_PRESENT) { obj->type = SC_PKCS15_TYPE_PUBKEY_GOSTR3410; assert(info.modulus_length == 0); info.modulus_length = SC_PKCS15_GOSTR3410_KEYSIZE; assert(info.params.len == 0); info.params.len = sizeof(struct sc_pkcs15_keyinfo_gostparams); info.params.data = malloc(info.params.len); if (info.params.data == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); assert(sizeof(*keyinfo_gostparams) == info.params.len); keyinfo_gostparams = info.params.data; keyinfo_gostparams->gostr3410 = (unsigned int)gostr3410_params[0]; keyinfo_gostparams->gostr3411 = (unsigned int)gostr3410_params[1]; keyinfo_gostparams->gost28147 = (unsigned int)gostr3410_params[2]; } else if (asn1_pubkey_choice[3].flags & SC_ASN1_PRESENT) { obj->type = SC_PKCS15_TYPE_PUBKEY_EC; } else { obj->type = SC_PKCS15_TYPE_PUBKEY_DSA; } if (!p15card->app || !p15card->app->ddo.aid.len) { r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); if (r < 0) { sc_pkcs15_free_key_params(&info.params); return r; } } else { info.path.aid = p15card->app->ddo.aid; } sc_log(ctx, "PubKey path '%s'", sc_print_path(&info.path)); /* OpenSC 0.11.4 and older encoded "keyReference" as a negative value. Fixed in 0.11.5 we need to add a hack, so old cards continue to work. */ if (info.key_reference < -1) info.key_reference += 256; obj->data = malloc(sizeof(info)); if (obj->data == NULL) { sc_pkcs15_free_key_params(&info.params); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); } memcpy(obj->data, &info, sizeof(info)); return 0; }
int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE]; struct sc_asn1_entry asn1_com_pubkey_attr[C_ASN1_COM_PUBKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_rsa_type_attr[C_ASN1_RSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_CHOICE_SIZE]; struct sc_asn1_entry asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_ec_type_attr[C_ASN1_EC_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_dsakey_attr[C_ASN1_DSAKEY_ATTR_SIZE]; struct sc_asn1_entry asn1_dsa_type_attr[C_ASN1_DSA_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOST3410KEY_ATTR_SIZE]; struct sc_asn1_entry asn1_gostr3410_type_attr[C_ASN1_GOST3410_TYPE_ATTR_SIZE]; struct sc_asn1_entry asn1_pubkey_choice[C_ASN1_PUBKEY_CHOICE_SIZE]; struct sc_asn1_entry asn1_pubkey[C_ASN1_PUBKEY_SIZE]; struct sc_pkcs15_pubkey_info *pubkey = (struct sc_pkcs15_pubkey_info *) obj->data; struct sc_asn1_pkcs15_object rsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; struct sc_asn1_pkcs15_object eckey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_ec_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; struct sc_asn1_pkcs15_object gostr3410key_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_gostr3410_type_attr }; struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; int r; size_t af_len, usage_len; sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice); sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_ec_type_attr, asn1_ec_type_attr); sc_copy_asn1_entry(c_asn1_eckey_value_choice, asn1_eckey_value_choice); sc_copy_asn1_entry(c_asn1_eckey_attr, asn1_eckey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); switch (obj->type) { case SC_PKCS15_TYPE_PUBKEY_RSA: sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 1); sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 1); if (pubkey->path.len || !obj->content.value) sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &pubkey->path, NULL, 1); else sc_format_asn1_entry(asn1_rsakey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1); sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 1, &pubkey->modulus_length, NULL, 1); break; case SC_PKCS15_TYPE_PUBKEY_DSA: sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 1); sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 1); sc_format_asn1_entry(asn1_dsakey_attr + 0, &pubkey->path, NULL, 1); break; case SC_PKCS15_TYPE_PUBKEY_GOSTR3410: sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 1); sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &pubkey->path, NULL, 1); if (pubkey->params.len == sizeof(*keyinfo_gostparams)) { keyinfo_gostparams = pubkey->params.data; sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &keyinfo_gostparams->gostr3410, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &keyinfo_gostparams->gostr3411, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &keyinfo_gostparams->gost28147, NULL, 1); } break; case SC_PKCS15_TYPE_PUBKEY_EC: /* MyEID is a PKCS15 card with ECC */ sc_format_asn1_entry(asn1_pubkey_choice + 3, &eckey_obj, NULL, 1); sc_format_asn1_entry(asn1_ec_type_attr + 0, asn1_eckey_attr, NULL, 1); if (pubkey->path.len || !obj->content.value) sc_format_asn1_entry(asn1_eckey_value_choice + 0, &pubkey->path, NULL, 1); else sc_format_asn1_entry(asn1_eckey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1); sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 1); sc_format_asn1_entry(asn1_eckey_attr + 1, &pubkey->field_length, NULL, 1); break; default: sc_log(ctx, "Unsupported public key type: %X", obj->type); LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); break; } sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1); usage_len = sizeof(pubkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1); if (pubkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1); if (pubkey->access_flags) { af_len = sizeof(pubkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1); } if (pubkey->key_reference >= 0) sc_format_asn1_entry(asn1_com_key_attr + 4, &pubkey->key_reference, NULL, 1); sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 1); if (pubkey->subject.value && pubkey->subject.len) sc_format_asn1_entry(asn1_com_pubkey_attr + 0, pubkey->subject.value, &pubkey->subject.len, 1); else memset(asn1_com_pubkey_attr, 0, sizeof(asn1_com_pubkey_attr)); r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen); sc_log(ctx, "Key path %s", sc_print_path(&pubkey->path)); return r; }
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]; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); /* Check that the card supports the requested modulus length */ if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "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); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store MyEID key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to generate MyEID private key"); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; args.op_type = OP_TYPE_GENERATE; args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; args.pubexp = MYEID_DEFAULT_PUBKEY; /* Generate RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); /* Keypair generation -> collect public key info */ /* FIXME: was not preset in original Aventra version. Need to be tested. (VT) */ if (pubkey != NULL) { struct sc_cardctl_myeid_data_obj data_obj; 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); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, 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); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get key modulus: 'MYEID_GETDATA' failed"); if ((data_obj.DataLen * 8) != key_info->modulus_length) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PKCS15INIT, "Cannot get key modulus: invalid key-size"); memcpy (pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } if (file) sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }