int sc_pkcs15_encode_dodf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize) { struct sc_asn1_entry asn1_com_data_attr[4], asn1_type_data_attr[2], asn1_data[2]; struct sc_pkcs15_data_info *info; struct sc_asn1_pkcs15_object data_obj = { (struct sc_pkcs15_object *) obj, asn1_com_data_attr, NULL, asn1_type_data_attr }; size_t label_len; info = (struct sc_pkcs15_data_info *) obj->data; label_len = strlen(info->app_label); sc_copy_asn1_entry(c_asn1_com_data_attr, asn1_com_data_attr); sc_copy_asn1_entry(c_asn1_type_data_attr, asn1_type_data_attr); sc_copy_asn1_entry(c_asn1_data, asn1_data); if (label_len) sc_format_asn1_entry(asn1_com_data_attr + 0, &info->app_label, &label_len, 1); if (sc_valid_oid(&info->app_oid)) sc_format_asn1_entry(asn1_com_data_attr + 1, &info->app_oid, NULL, 1); sc_format_asn1_entry(asn1_type_data_attr + 0, &info->path, NULL, 1); sc_format_asn1_entry(asn1_data + 0, &data_obj, NULL, 1); return sc_asn1_encode(ctx, asn1_data, buf, bufsize); }
int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_pkcs15_ec_parameters *ecparams) { int rv, ii; LOG_FUNC_CALLED(ctx); /* In PKCS#11 EC parameters arrives in DER encoded form */ if (ecparams->der.value && ecparams->der.len) { for (ii=0; ec_curve_infos[ii].name; ii++) { struct sc_object_id id; unsigned char *buf = NULL; size_t len = 0; sc_format_oid(&id, ec_curve_infos[ii].oid_str); sc_encode_oid (ctx, &id, &buf, &len); if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { free(buf); break; } free(buf); } /* TODO: support of explicit EC parameters form */ if (!ec_curve_infos[ii].name) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); sc_log(ctx, "Found known curve '%s'", ec_curve_infos[ii].name); if (!ecparams->named_curve) { ecparams->named_curve = strdup(ec_curve_infos[ii].name); if (!ecparams->named_curve) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); sc_log(ctx, "Curve name: '%s'", ecparams->named_curve); } if (!sc_valid_oid(&ecparams->id)) sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; sc_log(ctx, "Curve length %i", ecparams->field_length); } else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ for (ii=0; ec_curve_infos[ii].name; ii++) { if (!strcmp(ec_curve_infos[ii].name, ecparams->named_curve)) break; if (!strcmp(ec_curve_infos[ii].oid_str, ecparams->named_curve)) break; } if (!ec_curve_infos[ii].name) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); rv = sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); LOG_TEST_RET(ctx, rv, "Invalid OID format"); ecparams->field_length = ec_curve_infos[ii].size; if (!ecparams->der.value || !ecparams->der.len) { rv = sc_encode_oid (ctx, &ecparams->id, &ecparams->der.value, &ecparams->der.len); LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); } } else if (sc_valid_oid(&ecparams->id)) { LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "EC parameters has to be presented as a named curve or explicit data"); } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
/* * Store a private key */ static int myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r, keybits = key_info->modulus_length; LOG_FUNC_CALLED(ctx); switch (object->type) { case SC_PKCS15_TYPE_PRKEY_RSA: if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: if (!sc_valid_oid(&prkey->u.ec.params.id)) if (sc_pkcs15_fix_ec_parameters(ctx, &prkey->u.ec.params)) LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID); if (sc_card_find_ec_alg(p15card->card, keybits, &prkey->u.ec.params.id) == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported algorithm or key size"); if(key_info->field_length != 0) keybits = key_info->field_length; else key_info->field_length = keybits; break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); break; } sc_log(ctx, "store MyEID key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(card, &key_info->path, &file); LOG_TEST_RET(ctx, r, "Cannot store MyEID key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); LOG_TEST_RET(ctx, r, "No authorisation to store MyEID private key"); if (file) sc_file_free(file); /* Fill in data structure */ memset(&args, 0, sizeof (args)); args.op_type = OP_TYPE_STORE; if(object->type == SC_PKCS15_TYPE_PRKEY_RSA) { //args.key_len_bits = keybits; args.key_type = SC_CARDCTL_MYEID_KEY_RSA; args.pubexp_len = prkey->u.rsa.exponent.len; args.pubexp = prkey->u.rsa.exponent.data; args.primep_len = prkey->u.rsa.p.len; args.primep = prkey->u.rsa.p.data; args.primeq_len = prkey->u.rsa.q.len; args.primeq = prkey->u.rsa.q.data; args.dp1_len = prkey->u.rsa.dmp1.len; args.dp1 = prkey->u.rsa.dmp1.data; args.dq1_len = prkey->u.rsa.dmq1.len; args.dq1 = prkey->u.rsa.dmq1.data; args.invq_len = prkey->u.rsa.iqmp.len; args.invq = prkey->u.rsa.iqmp.data; args.key_len_bits = prkey->u.rsa.modulus.len; args.mod = prkey->u.rsa.modulus.data; } else { args.key_type = SC_CARDCTL_MYEID_KEY_EC; args.d = prkey->u.ec.privateD.data; args.d_len = prkey->u.ec.privateD.len; args.ecpublic_point = prkey->u.ec.ecpointQ.value; args.ecpublic_point_len = prkey->u.ec.ecpointQ.len; args.key_len_bits = prkey->u.ec.params.field_length; } /* Store RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); LOG_TEST_RET(ctx, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); LOG_FUNC_RETURN(ctx, r); }
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); }