static int incrypto34_put_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, int algorithm, sc_pkcs15_prkey_info_t *key_info, struct sc_pkcs15_prkey_rsa *key) { int r, key_id, pin_id; key_id = key_info->key_reference; pin_id = sc_pkcs15init_get_pin_reference(p15card, profile, SC_AC_SYMBOLIC, SC_PKCS15INIT_USER_PIN); if (pin_id < 0) pin_id = 0; r = incrypto34_store_key_component(p15card->card, algorithm, key_id, pin_id, 0, key->modulus.data, key->modulus.len, 0); if (r >= 0) { r = incrypto34_store_key_component(p15card->card, algorithm, key_id, pin_id, 1, key->d.data, key->d.len, 1); } if (SC_ERROR_FILE_ALREADY_EXISTS == r || r >=0) { r = incrypto34_change_key_data(p15card->card, 0x80|key_id, 0x20, key->modulus.data, key->modulus.len); if (r < 0) return r; r = incrypto34_change_key_data(p15card->card, 0x80|key_id, 0x21, key->d.data, key->d.len); } return r; }
static int cardos_put_key(sc_profile_t *profile, struct sc_pkcs15_card *p15card, int algorithm, sc_pkcs15_prkey_info_t *key_info, struct sc_pkcs15_prkey_rsa *key) { struct sc_card *card = p15card->card; int r, key_id, pin_id; pin_id = sc_pkcs15init_get_pin_reference(p15card, profile, SC_AC_SYMBOLIC, SC_PKCS15INIT_USER_PIN); if (pin_id < 0) pin_id = 0; key_id = key_info->key_reference; if (key_info->modulus_length > 1024 && (card->type == SC_CARD_TYPE_CARDOS_M4_2 || card->type == SC_CARD_TYPE_CARDOS_M4_3 ||card->type == SC_CARD_TYPE_CARDOS_M4_2B || card->type == SC_CARD_TYPE_CARDOS_M4_2C ||card->type == SC_CARD_TYPE_CARDOS_M4_4)) { r = cardos_store_key_component(card, algorithm, key_id, pin_id, 0, key->p.data, key->p.len, 0, 0); if (r != SC_SUCCESS) return r; r = cardos_store_key_component(card, algorithm, key_id, pin_id, 1, key->q.data, key->q.len, 0, 0); if (r != SC_SUCCESS) return r; r = cardos_store_key_component(card, algorithm, key_id, pin_id, 2, key->dmp1.data, key->dmp1.len, 0, 0); if (r != SC_SUCCESS) return r; r = cardos_store_key_component(card, algorithm, key_id, pin_id, 3, key->dmq1.data, key->dmq1.len, 0, 0); if (r != SC_SUCCESS) return r; r = cardos_store_key_component(card, algorithm, key_id, pin_id, 4, key->iqmp.data, key->iqmp.len, 1, 0); } else { r = cardos_store_key_component(card, algorithm, key_id, pin_id, 0, key->modulus.data, key->modulus.len, 0, 1); if (r != SC_SUCCESS) return r; r = cardos_store_key_component(card, algorithm, key_id, pin_id, 1, key->d.data, key->d.len, 1, 1); } return r; }
/* * Key generation */ static int cardos_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (sc_pkcs15_prkey_info_t *) obj->data; struct sc_pkcs15_prkey_rsa key_obj; struct sc_cardctl_cardos_genkey_info args; struct sc_file *temp; u8 abignum[256]; int algorithm = 0, r, delete_it = 0, use_ext_rsa = 0; size_t keybits, rsa_max_size; int pin_id = -1; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) return SC_ERROR_NOT_SUPPORTED; rsa_max_size = (p15card->card->caps & SC_CARD_CAP_RSA_2048) ? 2048 : 1024; keybits = key_info->modulus_length & ~7UL; if (keybits > rsa_max_size) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to generate key, max size is %lu", (unsigned long) rsa_max_size); return SC_ERROR_INVALID_ARGUMENTS; } if (keybits > 1024) use_ext_rsa = 1; if (cardos_key_algorithm(key_info->usage, keybits, &algorithm) < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "CardOS does not support keys " "that can both sign _and_ decrypt."); return SC_ERROR_NOT_SUPPORTED; } if (sc_profile_get_file(profile, "tempfile", &temp) < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Profile doesn't define temporary file " "for key generation."); return SC_ERROR_NOT_SUPPORTED; } pin_id = sc_pkcs15init_get_pin_reference(p15card, profile, SC_AC_SYMBOLIC, SC_PKCS15INIT_USER_PIN); if (pin_id >= 0) { r = sc_pkcs15init_verify_secret(profile, p15card, NULL, SC_AC_CHV, pin_id); if (r < 0) return r; } if (use_ext_rsa == 0) temp->ef_structure = SC_FILE_EF_LINEAR_VARIABLE_TLV; else temp->ef_structure = SC_FILE_EF_TRANSPARENT; if ((r = sc_pkcs15init_create_file(profile, p15card, temp)) < 0) goto out; delete_it = 1; init_key_object(&key_obj, abignum, keybits >> 3); r = cardos_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(p15card->card, SC_CARDCTL_CARDOS_GENERATE_KEY, &args); if (r < 0) goto out; r = cardos_extract_pubkey(p15card->card, pubkey, temp, use_ext_rsa); out: if (delete_it != 0) 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; }