/* * 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; }
/* * 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 = (sc_card_find_rsa_alg(p15card->card, 2048) != NULL) ? 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; }
/* * 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; }