int sc_asn1_decode_algorithm_id(struct sc_context *ctx, const unsigned char *in, size_t len, struct sc_algorithm_id *id, int depth) { struct sc_asn1_pkcs15_algorithm_info *alg_info = NULL; struct sc_asn1_entry asn1_alg_id[3]; int r; LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); sc_format_asn1_entry(asn1_alg_id + 0, &id->oid, NULL, 0); memset(id, 0, sizeof(*id)); r = _sc_asn1_decode(ctx, asn1_alg_id, in, len, &in, &len, 0, depth + 1); LOG_TEST_RET(ctx, r, "ASN.1 parsing of algo ID failed"); sc_log(ctx, "decoded OID '%s'", sc_dump_oid(&(id->oid))); /* See if we understand the algorithm, and if we do, check * whether we know how to decode any additional parameters */ id->algorithm = (unsigned int ) -1; alg_info = sc_asn1_get_algorithm_info(id); if (alg_info != NULL) { id->algorithm = alg_info->id; if (alg_info->decode) { if (asn1_alg_id[1].flags & SC_ASN1_PRESENT) { sc_log(ctx, "SC_ASN1_PRESENT was set, so invalid"); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT); } r = alg_info->decode(ctx, &id->params, in, len, depth); } } 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); }
int sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len, const struct sc_algorithm_id *id, int depth) { struct sc_asn1_pkcs15_algorithm_info *alg_info; struct sc_algorithm_id temp_id; struct sc_asn1_entry asn1_alg_id[3]; u8 *obj = NULL; size_t obj_len = 0; int r; u8 *tmp; LOG_FUNC_CALLED(ctx); sc_log(ctx, "type of algorithm to encode: %i", id->algorithm); alg_info = sc_asn1_get_algorithm_info(id); if (alg_info == NULL) { sc_log(ctx, "Cannot encode unknown algorithm %u", id->algorithm); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); } /* Set the oid if not yet given */ if (!sc_valid_oid(&id->oid)) { temp_id = *id; temp_id.oid = alg_info->oid; id = &temp_id; } sc_log(ctx, "encode algo %s", sc_dump_oid(&(id->oid))); sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1); /* no parameters, write NULL tag */ if (!id->params || !alg_info->encode) asn1_alg_id[1].flags |= SC_ASN1_PRESENT; r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1); LOG_TEST_RET(ctx, r, "ASN.1 encode of algorithm failed"); /* Encode any parameters */ if (id->params && alg_info->encode) { r = alg_info->encode(ctx, id->params, &obj, &obj_len, depth+1); if (r < 0) { if (obj) free(obj); LOG_FUNC_RETURN(ctx, r); } } if (obj_len) { tmp = (u8 *) realloc(*buf, *len + obj_len); if (!tmp) { free(*buf); *buf = NULL; free(obj); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); } *buf = tmp; memcpy(*buf + *len, obj, obj_len); *len += obj_len; free(obj); } sc_log(ctx, "return encoded algorithm ID: %s", sc_dump_hex(*buf, *len)); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }