int sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, u8 **buf, size_t *buflen) { int r; int version = ti->version; size_t serial_len, mnfid_len, label_len, flags_len, last_upd_len; struct sc_asn1_entry asn1_toki[14], asn1_tokeninfo[2]; sc_copy_asn1_entry(c_asn1_toki, asn1_toki); sc_copy_asn1_entry(c_asn1_tokeninfo, asn1_tokeninfo); version--; sc_format_asn1_entry(asn1_toki + 0, &version, NULL, 1); if (ti->serial_number != NULL) { u8 serial[128]; serial_len = 0; if (strlen(ti->serial_number)/2 > sizeof(serial)) return SC_ERROR_BUFFER_TOO_SMALL; serial_len = sizeof(serial); if (sc_hex_to_bin(ti->serial_number, serial, &serial_len) < 0) return SC_ERROR_INVALID_ARGUMENTS; sc_format_asn1_entry(asn1_toki + 1, serial, &serial_len, 1); } else sc_format_asn1_entry(asn1_toki + 1, NULL, NULL, 0); if (ti->manufacturer_id != NULL) { mnfid_len = strlen(ti->manufacturer_id); sc_format_asn1_entry(asn1_toki + 2, ti->manufacturer_id, &mnfid_len, 1); } else sc_format_asn1_entry(asn1_toki + 2, NULL, NULL, 0); if (ti->label != NULL) { label_len = strlen(ti->label); sc_format_asn1_entry(asn1_toki + 3, ti->label, &label_len, 1); } else sc_format_asn1_entry(asn1_toki + 3, NULL, NULL, 0); if (ti->flags) { flags_len = sizeof(ti->flags); sc_format_asn1_entry(asn1_toki + 5, &ti->flags, &flags_len, 1); } else sc_format_asn1_entry(asn1_toki + 5, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 6, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 7, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 8, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 9, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 10, NULL, NULL, 0); if (ti->last_update != NULL) { last_upd_len = strlen(ti->last_update); sc_format_asn1_entry(asn1_toki + 11, ti->last_update, &last_upd_len, 1); } else sc_format_asn1_entry(asn1_toki + 11, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 12, NULL, NULL, 0); sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1); r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen); if (r) { sc_error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r)); return r; } return 0; }
/* * Encode a card verifiable certificate as defined in TR-03110. */ int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card, sc_cvc_t *cvc, u8 ** buf, size_t *buflen) { sc_card_t *card = p15card->card; struct sc_asn1_entry asn1_cvc[C_ASN1_CVC_SIZE]; struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE]; struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE]; struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE]; unsigned int cla,tag; size_t taglen; size_t lenchr; size_t lencar; int r; sc_copy_asn1_entry(c_asn1_cvc, asn1_cvc); sc_copy_asn1_entry(c_asn1_cvcert, asn1_cvcert); sc_copy_asn1_entry(c_asn1_cvc_body, asn1_cvc_body); sc_copy_asn1_entry(c_asn1_cvc_pubkey, asn1_cvc_pubkey); asn1_cvc_pubkey[1].flags = SC_ASN1_OPTIONAL; asn1_cvcert[1].flags = SC_ASN1_OPTIONAL; sc_format_asn1_entry(asn1_cvc_pubkey , &cvc->pukoid, NULL, 1); if (cvc->primeOrModulus && (cvc->primeOrModuluslen > 0)) { sc_format_asn1_entry(asn1_cvc_pubkey + 1, cvc->primeOrModulus, &cvc->primeOrModuluslen, 1); } sc_format_asn1_entry(asn1_cvc_pubkey + 2, cvc->coefficientAorExponent, &cvc->coefficientAorExponentlen, 1); if (cvc->coefficientB && (cvc->coefficientBlen > 0)) { sc_format_asn1_entry(asn1_cvc_pubkey + 3, cvc->coefficientB, &cvc->coefficientBlen, 1); sc_format_asn1_entry(asn1_cvc_pubkey + 4, cvc->basePointG, &cvc->basePointGlen, 1); sc_format_asn1_entry(asn1_cvc_pubkey + 5, cvc->order, &cvc->orderlen, 1); if (cvc->publicPoint && (cvc->publicPointlen > 0)) { sc_format_asn1_entry(asn1_cvc_pubkey + 6, cvc->publicPoint, &cvc->publicPointlen, 1); } sc_format_asn1_entry(asn1_cvc_pubkey + 7, cvc->cofactor, &cvc->cofactorlen, 1); } if (cvc->modulusSize > 0) { sc_format_asn1_entry(asn1_cvc_pubkey + 8, &cvc->modulusSize, NULL, 1); } sc_format_asn1_entry(asn1_cvc_body , &cvc->cpi, NULL, 1); lencar = strlen(cvc->car); sc_format_asn1_entry(asn1_cvc_body + 1, &cvc->car, &lencar, 1); sc_format_asn1_entry(asn1_cvc_body + 2, &asn1_cvc_pubkey, NULL, 1); lenchr = strlen(cvc->chr); sc_format_asn1_entry(asn1_cvc_body + 3, &cvc->chr, &lenchr, 1); sc_format_asn1_entry(asn1_cvcert , &asn1_cvc_body, NULL, 1); if (cvc->signature && (cvc->signatureLen > 0)) { sc_format_asn1_entry(asn1_cvcert + 1, cvc->signature, &cvc->signatureLen, 1); } sc_format_asn1_entry(asn1_cvc , &asn1_cvcert, NULL, 1); r = sc_asn1_encode(card->ctx, asn1_cvc, buf, buflen); LOG_TEST_RET(card->ctx, r, "Could not encode card verifiable certificate"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int encode_dir_record(sc_context_t *ctx, const sc_app_info_t *app, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2]; sc_app_info_t tapp = *app; int r; size_t label_len; sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord); sc_copy_asn1_entry(c_asn1_dir, asn1_dir); sc_format_asn1_entry(asn1_dir + 0, asn1_dirrecord, NULL, 1); sc_format_asn1_entry(asn1_dirrecord + 0, (void *) tapp.aid.value, (void *) &tapp.aid.len, 1); if (tapp.label != NULL) { label_len = strlen(tapp.label); sc_format_asn1_entry(asn1_dirrecord + 1, tapp.label, &label_len, 1); } if (tapp.path.len) sc_format_asn1_entry(asn1_dirrecord + 2, (void *) tapp.path.value, (void *) &tapp.path.len, 1); if (tapp.ddo.value != NULL && tapp.ddo.len) sc_format_asn1_entry(asn1_dirrecord + 3, (void *) tapp.ddo.value, (void *) &tapp.ddo.len, 1); r = sc_asn1_encode(ctx, asn1_dir, buf, buflen); LOG_TEST_RET(ctx, r, "Encode DIR record error"); return SC_SUCCESS; }
int sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_public_key[2]; struct sc_asn1_entry asn1_dsa_pub_coeff[5]; int r; sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coeff); sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coeff, NULL, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 0, key->pub.data, &key->pub.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 1, key->g.data, &key->g.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 2, key->p.data, &key->p.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 3, key->q.data, &key->q.len, 1); r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed"); return 0; }
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_encode_enveloped_data(sc_context_t *ctx, struct sc_pkcs15_enveloped_data *data, u8 **buf, size_t *buflen) { static struct sc_object_id oid_id_data = {{ 1, 2, 840, 113549, 1, 7, 1, -1 }}; struct sc_asn1_entry asn1_enveloped_data_attr[5], asn1_content_attr[4], asn1_encr_content[2], asn1_recipients_attr[2], asn1_kekri_attr[5], asn1_kek_attr[4]; int version2 = 2, version4 = 4, r; sc_copy_asn1_entry(c_asn1_enveloped_data_attr, asn1_enveloped_data_attr); sc_copy_asn1_entry(c_asn1_content_attr, asn1_content_attr); sc_copy_asn1_entry(c_asn1_encr_content, asn1_encr_content); sc_copy_asn1_entry(c_asn1_recipients_attr, asn1_recipients_attr); sc_copy_asn1_entry(c_asn1_kekri_attr, asn1_kekri_attr); sc_copy_asn1_entry(c_asn1_kek_attr, asn1_kek_attr); sc_format_asn1_entry(asn1_enveloped_data_attr + 0, &version2, NULL, 1); sc_format_asn1_entry(asn1_enveloped_data_attr + 2, asn1_recipients_attr, NULL, 1); sc_format_asn1_entry(asn1_enveloped_data_attr + 3, asn1_content_attr, NULL, 1); sc_format_asn1_entry(asn1_content_attr + 0, &oid_id_data, NULL, 1); sc_format_asn1_entry(asn1_content_attr + 1, &data->ce_alg, NULL, 1); sc_format_asn1_entry(asn1_content_attr + 2, asn1_encr_content, NULL, 1); sc_format_asn1_entry(asn1_encr_content + 0, data->content, &data->content_len, 1); sc_format_asn1_entry(asn1_recipients_attr + 0, asn1_kekri_attr, NULL, 1); sc_format_asn1_entry(asn1_kekri_attr + 0, &version4, NULL, 1); sc_format_asn1_entry(asn1_kekri_attr + 1, asn1_kek_attr, NULL, 1); sc_format_asn1_entry(asn1_kekri_attr + 2, &data->ke_alg, NULL, 1); sc_format_asn1_entry(asn1_kekri_attr + 3, data->key, &data->key_len, 1); sc_format_asn1_entry(asn1_kek_attr + 0, &data->id, &data->id.len, 1); memset(&data, 0, sizeof(data)); r = sc_asn1_encode(ctx, asn1_enveloped_data_attr, buf, buflen); return r; }
static int sc_pkcs15_encode_prkey_dsa(sc_context_t *ctx, struct sc_pkcs15_prkey_dsa *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_dsa_prkey_obj[2]; sc_copy_asn1_entry(c_asn1_dsa_prkey_obj, asn1_dsa_prkey_obj); sc_format_asn1_entry(asn1_dsa_prkey_obj + 0, key->priv.data, &key->priv.len, 1); return sc_asn1_encode(ctx, asn1_dsa_prkey_obj, buf, buflen); }
int sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; int r; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, key->ecpointQ.value, &key->ecpointQ.len, 1); r = sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen); LOG_TEST_RET(ctx, r, "ASN.1 encoding failed"); sc_log(ctx, "EC key->ecpointQ=%p:%d *buf=%p:%d", key->ecpointQ.value, key->ecpointQ.len, *buf, *buflen); return 0; }
int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; struct sc_asn1_entry asn1_auth_type[2]; struct sc_asn1_entry asn1_auth_type_choice[4]; struct sc_pkcs15_auth_info *info = (struct sc_pkcs15_auth_info *) obj->data; struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; int r; size_t flags_len; size_t padchar_len = 1; if (info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_NOT_SUPPORTED; sc_copy_asn1_entry(c_asn1_auth_type, asn1_auth_type); sc_copy_asn1_entry(c_asn1_auth_type_choice, asn1_auth_type_choice); 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_auth_type + 0, asn1_auth_type_choice, NULL, 1); sc_format_asn1_entry(asn1_auth_type_choice + 0, &pin_obj, NULL, 1); sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1); flags_len = sizeof(info->attrs.pin.flags); sc_format_asn1_entry(asn1_pin_attr + 0, &info->attrs.pin.flags, &flags_len, 1); sc_format_asn1_entry(asn1_pin_attr + 1, &info->attrs.pin.type, NULL, 1); sc_format_asn1_entry(asn1_pin_attr + 2, &info->attrs.pin.min_length, NULL, 1); sc_format_asn1_entry(asn1_pin_attr + 3, &info->attrs.pin.stored_length, NULL, 1); if (info->attrs.pin.max_length > 0) sc_format_asn1_entry(asn1_pin_attr + 4, &info->attrs.pin.max_length, NULL, 1); if (info->attrs.pin.reference >= 0) sc_format_asn1_entry(asn1_pin_attr + 5, &info->attrs.pin.reference, NULL, 1); /* FIXME: check if pad_char present */ sc_format_asn1_entry(asn1_pin_attr + 6, &info->attrs.pin.pad_char, &padchar_len, 1); sc_format_asn1_entry(asn1_pin_attr + 8, &info->path, NULL, info->path.len ? 1 : 0); sc_format_asn1_entry(asn1_com_ao_attr + 0, &info->auth_id, NULL, 1); r = sc_asn1_encode(ctx, asn1_auth_type, buf, buflen); return r; }
static int sc_hsm_decode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info, struct sc_pkcs15_pubkey *pubkey) { struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; struct sc_pkcs15_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)(key_info->params.data); struct sc_ec_params *ecp; u8 *buf; size_t buflen; int r; LOG_FUNC_CALLED(p15card->card->ctx); pubkey->algorithm = SC_ALGORITHM_EC; pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve); sc_pkcs15_fix_ec_parameters(p15card->card->ctx, &pubkey->u.ec.params); ecp = calloc(1, sizeof(struct sc_ec_params)); if (!ecp) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } ecp->der = malloc(ecparams->der.len); if (!ecp->der) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } ecp->der_len = ecparams->der.len; memcpy(ecp->der, ecparams->der.value, ecp->der_len); pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); if (!pubkey->alg_id) { LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); } pubkey->alg_id->algorithm = SC_ALGORITHM_EC; pubkey->alg_id->params = ecp; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, cvc->publicPoint, &cvc->publicPointlen, 1); r = sc_asn1_encode(p15card->card->ctx, asn1_ec_pointQ, &pubkey->u.ec.ecpointQ.value, &pubkey->u.ec.ecpointQ.len); LOG_TEST_RET(p15card->card->ctx, r, "ASN.1 encoding failed"); LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); }
int sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *ctx, struct sc_pkcs15_pubkey_gostr3410 *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_gostr3410_pub_coeff[C_ASN1_GOSTR3410_PUB_COEFFICIENTS_SIZE]; int r; LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_gostr3410_pub_coefficients, asn1_gostr3410_pub_coeff); sc_format_asn1_entry(asn1_gostr3410_pub_coeff + 0, key->xy.data, &key->xy.len, 1); r = sc_asn1_encode(ctx, asn1_gostr3410_pub_coeff, buf, buflen); LOG_TEST_RET(ctx, r, "ASN.1 encoding failed"); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int encode_ddo(struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_ddo[5]; int r; size_t label_len; sc_copy_asn1_entry(c_asn1_ddo, asn1_ddo); sc_format_asn1_entry(asn1_ddo + 1, &card->file_odf.path, NULL, 0); sc_format_asn1_entry(asn1_ddo + 2, &card->file_tokeninfo.path, NULL, 0); r = sc_asn1_encode(ctx, asn1_dir, buf, buflen); if (r) { sc_error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r)); return r; } return 0; }
int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { 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_pkcs15_pin_info *pin = (struct sc_pkcs15_pin_info *) obj->data; struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; int r; size_t flags_len; size_t padchar_len = 1; 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, 1); sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1); flags_len = sizeof(pin->flags); sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 1); sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 1); sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 1); sc_format_asn1_entry(asn1_pin_attr + 3, &pin->stored_length, NULL, 1); if (pin->max_length > 0) sc_format_asn1_entry(asn1_pin_attr + 4, &pin->max_length, NULL, 1); if (pin->reference >= 0) sc_format_asn1_entry(asn1_pin_attr + 5, &pin->reference, NULL, 1); /* FIXME: check if pad_char present */ sc_format_asn1_entry(asn1_pin_attr + 6, &pin->pad_char, &padchar_len, 1); sc_format_asn1_entry(asn1_pin_attr + 8, &pin->path, NULL, pin->path.len ? 1 : 0); sc_format_asn1_entry(asn1_com_ao_attr + 0, &pin->auth_id, NULL, 1); assert(pin->magic == SC_PKCS15_PIN_MAGIC); r = sc_asn1_encode(ctx, asn1_pin, buf, buflen); return r; }
int sc_pkcs15_encode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_public_key[C_ASN1_PUBLIC_KEY_SIZE]; struct sc_asn1_entry asn1_rsa_pub_coefficients[C_ASN1_RSA_PUB_COEFFICIENTS_SIZE]; int r; sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coefficients, NULL, 1); sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_pub_coefficients); sc_format_asn1_entry(asn1_rsa_pub_coefficients + 0, key->modulus.data, &key->modulus.len, 1); sc_format_asn1_entry(asn1_rsa_pub_coefficients + 1, key->exponent.data, &key->exponent.len, 1); r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); LOG_TEST_RET(ctx, r, "ASN.1 encoding failed"); return 0; }
int sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_public_key[C_ASN1_PUBLIC_KEY_SIZE]; struct sc_asn1_entry asn1_dsa_pub_coefficients[C_ASN1_DSA_PUB_COEFFICIENTS_SIZE]; int r; LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coefficients); sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coefficients, NULL, 1); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 0, key->pub.data, &key->pub.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 1, key->g.data, &key->g.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 2, key->p.data, &key->p.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 3, key->q.data, &key->q.len, 1); r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); LOG_TEST_RET(ctx, r, "ASN.1 encoding failed"); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
int sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize) { 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_pkcs15_cert_info *infop = (sc_pkcs15_cert_info_t *) obj->data; sc_pkcs15_der_t *der = &infop->value; struct sc_asn1_pkcs15_object cert_obj = { (struct sc_pkcs15_object *) obj, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; 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_com_cert_attr + 0, (void *) &infop->id, NULL, 1); if (infop->authority) sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1); if (infop->path.len || !der->value) { sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &infop->path, NULL, 1); } else { sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, der->value, &der->len, 1); } sc_format_asn1_entry(asn1_type_cert_attr + 0, &asn1_x509_cert_value_choice, NULL, 1); sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1); r = sc_asn1_encode(ctx, asn1_cert, buf, bufsize); return r; }
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; }
/* * can be used as an SC_ASN1_CALLBACK while parsing a certificate, * or can be called from the sc_pkcs15_pubkey_from_spki_filename */ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubkey, u8 *buf, size_t buflen, int depth) { int r; sc_pkcs15_pubkey_t * pubkey = NULL; sc_pkcs15_der_t pk = { NULL, 0 }; struct sc_algorithm_id pk_alg; struct sc_asn1_entry asn1_pkinfo[3]; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"sc_pkcs15_pubkey_from_spki %p:%d", buf, buflen); memset(&pk_alg, 0, sizeof(pk_alg)); pubkey = calloc(1, sizeof(sc_pkcs15_pubkey_t)); if (pubkey == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } sc_copy_asn1_entry(c_asn1_pkinfo, asn1_pkinfo); sc_format_asn1_entry(asn1_pkinfo + 0, &pk_alg, NULL, 0); sc_format_asn1_entry(asn1_pkinfo + 1, &pk.value, &pk.len, 0); r = sc_asn1_decode(ctx, asn1_pkinfo, buf, buflen, NULL, NULL); if (r < 0) goto err; pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); if (pubkey->alg_id == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id)); pubkey->algorithm = pk_alg.algorithm; sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE pk_alg.algorithm=%d",pk_alg.algorithm); /* pk.len is in bits at this point */ switch (pk_alg.algorithm) { case SC_ALGORITHM_EC: /* * For most keys, the above ASN.1 parsing of a key works, but for EC keys, * the ec_pointQ in a certificate is stored in a bitstring, but * in PKCS#11 it is an octet string and we just decoded its * contents from the bitstring in the certificate. So we need to encode it * back to an octet string so we can store it as an octet string. */ pk.len >>= 3; /* Assume it is multiple of 8 */ // pubkey->u.ec.field_length = (pk.len - 1)/2 * 8; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(&asn1_ec_pointQ[0], pk.value, &pk.len, 1); r = sc_asn1_encode(ctx, asn1_ec_pointQ, &pubkey->data.value, &pubkey->data.len); sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE r=%d data=%p:%d", r,pubkey->data.value, pubkey->data.len); break; default: pk.len >>= 3; /* convert number of bits to bytes */ pubkey->data = pk; /* save in publey */ pk.value = NULL; break; } /* Now decode what every is in pk as it depends on the key algorthim */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); if (r < 0) goto err; *outpubkey = pubkey; pubkey = NULL; return 0; err: if (pubkey) free(pubkey); if (pk.value) free(pk.value); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 parsing of subjectPubkeyInfo failed"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
int boxing_pace_output_to_buf(sc_context_t *ctx, const struct establish_pace_channel_output *output, unsigned char **asn1, size_t *asn1_len) { uint16_t status_mse_set_at = ((output->mse_set_at_sw1 & 0xff) << 8) | output->mse_set_at_sw2; size_t result_len = sizeof output->result, status_mse_set_at_len = sizeof status_mse_set_at; struct sc_asn1_entry EstablishPACEChannelOutput_data[ sizeof g_EstablishPACEChannelOutput_data/ sizeof *g_EstablishPACEChannelOutput_data]; struct sc_asn1_entry EstablishPACEChannel[ sizeof g_EstablishPACEChannel/ sizeof *g_EstablishPACEChannel]; struct sc_asn1_entry errorCode[ sizeof g_octet_string/ sizeof *g_octet_string]; struct sc_asn1_entry statusMSESetAT[ sizeof g_octet_string/ sizeof *g_octet_string]; struct sc_asn1_entry idPICC[ sizeof g_octet_string/ sizeof *g_octet_string]; struct sc_asn1_entry curCAR[ sizeof g_octet_string/ sizeof *g_octet_string]; struct sc_asn1_entry prevCAR[ sizeof g_octet_string/ sizeof *g_octet_string]; sc_copy_asn1_entry(g_EstablishPACEChannel, EstablishPACEChannel); sc_format_asn1_entry(EstablishPACEChannel, EstablishPACEChannelOutput_data, 0, 1); sc_copy_asn1_entry(g_EstablishPACEChannelOutput_data, EstablishPACEChannelOutput_data); sc_format_asn1_entry(EstablishPACEChannelOutput_data+0, errorCode, 0, 1); sc_copy_asn1_entry(g_octet_string, errorCode); sc_format_asn1_entry(errorCode, (unsigned char *) &output->result, &result_len, 1); sc_format_asn1_entry(EstablishPACEChannelOutput_data+1, statusMSESetAT, 0, 1); sc_copy_asn1_entry(g_octet_string, statusMSESetAT); sc_format_asn1_entry(statusMSESetAT, &status_mse_set_at, &status_mse_set_at_len, 1); if (output->ef_cardaccess) { sc_format_asn1_entry(EstablishPACEChannelOutput_data+2, output->ef_cardaccess, (size_t *) &output->ef_cardaccess_length, 1); } if (output->id_icc) { sc_format_asn1_entry(EstablishPACEChannelOutput_data+3, idPICC, 0, 1); sc_copy_asn1_entry(g_octet_string, idPICC); sc_format_asn1_entry(idPICC, output->id_icc, (size_t *) &output->id_icc_length, 1); } if (output->recent_car) { sc_format_asn1_entry(EstablishPACEChannelOutput_data+4, curCAR, 0, 1); sc_copy_asn1_entry(g_octet_string, curCAR); sc_format_asn1_entry(curCAR, output->recent_car, (size_t *) &output->recent_car_length, 1); } if (output->previous_car) { sc_format_asn1_entry(EstablishPACEChannelOutput_data+5, prevCAR, 0, 1); sc_copy_asn1_entry(g_octet_string, prevCAR); sc_format_asn1_entry(prevCAR, output->previous_car, (size_t *) &output->previous_car_length, 1); } return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len); }
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[6], asn1_com_pubkey_attr[1]; struct sc_asn1_entry asn1_rsakey_value_choice[3]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2]; struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2]; struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2]; struct sc_asn1_entry asn1_pubkey_choice[4]; struct sc_asn1_entry asn1_pubkey[2]; 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 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_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; default: /* TODO: -DEE Should add ECC but don't have PKCS15 card with ECC */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key type: %X\n", obj->type); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 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); r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen); return r; }
/* * Encode a pubkey as a SPKI, useful for pkcs15-tool, and for PKCS#15 files. */ int sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubkey, u8 **buf, size_t *len) { int r; struct sc_asn1_entry asn1_spki_key[2], asn1_spki_key_items[3]; struct sc_pkcs15_u8 pkey; size_t key_len; LOG_FUNC_CALLED(ctx); pkey.value = NULL; pkey.len = 0; sc_log(ctx, "Encoding public key with algorithm %i", pubkey->algorithm); if (!pubkey->alg_id) { pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); if (!pubkey->alg_id) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); sc_init_oid(&pubkey->alg_id->oid); pubkey->alg_id->algorithm = pubkey->algorithm; } /* make sure we have a der encoded value first */ if (pubkey->data.value == NULL){ r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pubkey->data.value, &pubkey->data.len); LOG_TEST_RET(ctx, r, "public key encoding failed"); } switch (pubkey->algorithm) { case SC_ALGORITHM_EC: /* * most keys, but not EC have only one encoding. * For a SPKI, the ecpoint is placed directly in the * BIT STRING */ key_len = pubkey->u.ec.ecpointQ.len * 8; pkey.value = pubkey->u.ec.ecpointQ.value; pkey.len = 0; /* flag as do not delete */ /* TODO make sure algorithm params are available*/ /* if not can we copy them from the u.ec */ r = 0; break; case SC_ALGORITHM_GOSTR3410: /* TODO is this needed? does it cause mem leak? */ pubkey->alg_id->params = &pubkey->u.gostr3410.params; r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len); key_len = pkey.len * 8; break; default: r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len); key_len = pkey.len * 8; break; } if (r == 0) { sc_copy_asn1_entry(c_asn1_spki_key, asn1_spki_key); sc_copy_asn1_entry(c_asn1_spki_key_items, asn1_spki_key_items); sc_format_asn1_entry(asn1_spki_key + 0, asn1_spki_key_items, NULL, 1); sc_format_asn1_entry(asn1_spki_key_items + 0, pubkey->alg_id, NULL, 1); sc_format_asn1_entry(asn1_spki_key_items + 1, pkey.value, &key_len, 1); r = sc_asn1_encode(ctx, asn1_spki_key, buf, len); } if (pkey.len && pkey.value) free(pkey.value); LOG_FUNC_RETURN(ctx, r); }
int sc_pkcs15_encode_odf(sc_context_t *ctx, struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen) { sc_path_t path; struct sc_asn1_entry asn1_obj_or_path[] = { { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry *asn1_paths = NULL; struct sc_asn1_entry *asn1_odf = NULL; int df_count = 0, r, c = 0; const int nr_indexes = sizeof(odf_indexes)/sizeof(odf_indexes[0]); struct sc_pkcs15_df *df; df = p15card->df_list; while (df != NULL) { df_count++; df = df->next; }; if (df_count == 0) { sc_error(ctx, "No DF's found.\n"); return SC_ERROR_OBJECT_NOT_FOUND; } asn1_odf = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count + 1)); if (asn1_odf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } asn1_paths = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (df_count * 2)); if (asn1_paths == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } for (df = p15card->df_list; df != NULL; df = df->next) { int j, type = -1; for (j = 0; j < nr_indexes; j++) if (odf_indexes[j] == df->type) { type = j; break; } if (type == -1) { sc_error(ctx, "Unsupported DF type.\n"); continue; } asn1_odf[c] = c_asn1_odf[type]; sc_format_asn1_entry(asn1_odf + c, asn1_paths + 2*c, NULL, 1); sc_copy_asn1_entry(asn1_obj_or_path, asn1_paths + 2*c); sc_format_asn1_entry(asn1_paths + 2*c, &df->path, NULL, 1); c++; } asn1_odf[c].name = NULL; r = sc_asn1_encode(ctx, asn1_odf, buf, buflen); err: if (asn1_paths != NULL) free(asn1_paths); if (asn1_odf != NULL) free(asn1_odf); return r; }
static int sm_decrypt(const struct iso_sm_ctx *ctx, sc_card_t *card, const sc_apdu_t *sm_apdu, sc_apdu_t *apdu) { int r; struct sc_asn1_entry sm_rapdu[4]; struct sc_asn1_entry my_sm_rapdu[4]; u8 sw[2], mac[8], fdata[SC_MAX_EXT_APDU_BUFFER_SIZE]; size_t sw_len = sizeof sw, mac_len = sizeof mac, fdata_len = sizeof fdata, buf_len, asn1_len; const u8 *buf; u8 *data = NULL, *mac_data = NULL, *asn1 = NULL; sc_copy_asn1_entry(c_sm_rapdu, sm_rapdu); sc_format_asn1_entry(sm_rapdu + 0, fdata, &fdata_len, 0); sc_format_asn1_entry(sm_rapdu + 1, sw, &sw_len, 0); sc_format_asn1_entry(sm_rapdu + 2, mac, &mac_len, 0); r = sc_asn1_decode(card->ctx, sm_rapdu, sm_apdu->resp, sm_apdu->resplen, &buf, &buf_len); if (r < 0) goto err; if (buf_len > 0) { r = SC_ERROR_UNKNOWN_DATA_RECEIVED; goto err; } if (sm_rapdu[2].flags & SC_ASN1_PRESENT) { /* copy from sm_apdu to my_sm_apdu, but leave mac at default */ sc_copy_asn1_entry(sm_rapdu, my_sm_rapdu); sc_copy_asn1_entry(&c_sm_rapdu[2], &my_sm_rapdu[2]); r = sc_asn1_encode(card->ctx, my_sm_rapdu, &asn1, &asn1_len); if (r < 0) goto err; r = add_padding(ctx, asn1, asn1_len, &mac_data); if (r < 0) { goto err; } r = ctx->verify_authentication(card, ctx, mac, mac_len, mac_data, r); if (r < 0) goto err; } else { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Cryptographic Checksum missing"); r = SC_ERROR_ASN1_OBJECT_NOT_FOUND; goto err; } if (sm_rapdu[0].flags & SC_ASN1_PRESENT) { if (ctx->padding_indicator != fdata[0]) { r = SC_ERROR_UNKNOWN_DATA_RECEIVED; goto err; } r = ctx->decrypt(card, ctx, fdata + 1, fdata_len - 1, &data); if (r < 0) goto err; buf_len = r; r = rm_padding(ctx->padding_indicator, data, buf_len); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not remove padding"); goto err; } if (apdu->resplen < r || (r && !apdu->resp)) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Response of SM APDU %u byte%s too long", r-apdu->resplen, r-apdu->resplen < 2 ? "" : "s"); r = SC_ERROR_OUT_OF_MEMORY; goto err; } /* Flawfinder: ignore */ memcpy(apdu->resp, data, r); apdu->resplen = r; } else { apdu->resplen = 0; } if (sm_rapdu[1].flags & SC_ASN1_PRESENT) { if (sw_len != 2) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Length of processing status bytes must be 2"); r = SC_ERROR_ASN1_END_OF_CONTENTS; goto err; } apdu->sw1 = sw[0]; apdu->sw2 = sw[1]; } else { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Authenticated status bytes are missing"); r = SC_ERROR_ASN1_OBJECT_NOT_FOUND; goto err; } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU sw1=%02x sw2=%02x", apdu->sw1, apdu->sw2); bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Decrypted APDU response data", apdu->resp, apdu->resplen); r = SC_SUCCESS; err: free(asn1); free(mac_data); if (data) { sc_mem_clear(data, buf_len); free(data); } return r; }
int boxing_pace_capabilities_to_buf(sc_context_t *ctx, const unsigned long sc_reader_t_capabilities, unsigned char **asn1, size_t *asn1_len) { int yes = 1, no = 0; struct sc_asn1_entry PACECapabilities_data[ sizeof g_PACECapabilities_data/ sizeof *g_PACECapabilities_data]; struct sc_asn1_entry PACECapabilities[ sizeof g_PACECapabilities/ sizeof *g_PACECapabilities]; struct sc_asn1_entry capabilityPACE[ sizeof g_boolean/ sizeof *g_boolean]; struct sc_asn1_entry capabilityEID[ sizeof g_boolean/ sizeof *g_boolean]; struct sc_asn1_entry capabilityESign[ sizeof g_boolean/ sizeof *g_boolean]; struct sc_asn1_entry capabilityDestroy[ sizeof g_boolean/ sizeof *g_boolean]; sc_copy_asn1_entry(g_EstablishPACEChannel, PACECapabilities); sc_format_asn1_entry(PACECapabilities, PACECapabilities_data, 0, 1); sc_copy_asn1_entry(g_PACECapabilities_data, PACECapabilities_data); sc_format_asn1_entry(PACECapabilities_data+0, &capabilityPACE, NULL, 1); sc_format_asn1_entry(PACECapabilities_data+1, &capabilityEID, NULL, 1); sc_format_asn1_entry(PACECapabilities_data+2, &capabilityESign, NULL, 1); sc_format_asn1_entry(PACECapabilities_data+3, &capabilityDestroy, NULL, 1); sc_copy_asn1_entry(g_boolean, capabilityPACE); sc_format_asn1_entry(capabilityPACE, sc_reader_t_capabilities & SC_READER_CAP_PACE_GENERIC ? &yes : &no, NULL, 1); sc_copy_asn1_entry(g_boolean, capabilityEID); sc_format_asn1_entry(capabilityEID, sc_reader_t_capabilities & SC_READER_CAP_PACE_EID ? &yes : &no, NULL, 1); sc_copy_asn1_entry(g_boolean, capabilityESign); sc_format_asn1_entry(capabilityESign, sc_reader_t_capabilities & SC_READER_CAP_PACE_ESIGN ? &yes : &no, NULL, 1); sc_copy_asn1_entry(g_boolean, capabilityDestroy); sc_format_asn1_entry(capabilityDestroy, sc_reader_t_capabilities & SC_READER_CAP_PACE_DESTROY_CHANNEL ? &yes : &no, NULL, 1); return sc_asn1_encode(ctx, PACECapabilities, asn1, asn1_len); }
int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[1]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_prk_rsa_attr[2]; struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2], asn1_dsakey_value_attr[3], asn1_dsakey_i_p_attr[2]; struct sc_asn1_entry asn1_prkey[3]; struct sc_asn1_pkcs15_object rsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_rsa_attr }; struct sc_asn1_pkcs15_object dsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_dsa_attr }; struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; int r; size_t af_len, usage_len; sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr); sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr); sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 1); sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 1); break; case SC_PKCS15_TYPE_PRKEY_DSA: sc_format_asn1_entry(asn1_prkey + 1, &dsa_prkey_obj, NULL, 1); sc_format_asn1_entry(asn1_prk_dsa_attr + 0, asn1_dsakey_value_attr, NULL, 1); if (prkey->path.type != SC_PATH_TYPE_PATH_PROT) { /* indirect: just add the path */ sc_format_asn1_entry(asn1_dsakey_value_attr + 0, &prkey->path, NULL, 1); } else { /* indirect-protected */ sc_format_asn1_entry(asn1_dsakey_value_attr + 1, asn1_dsakey_i_p_attr, NULL, 1); sc_format_asn1_entry(asn1_dsakey_i_p_attr + 0, &prkey->path, NULL, 1); } break; default: sc_error(ctx, "Invalid private key type: %X\n", obj->type); SC_FUNC_RETURN(ctx, 0, SC_ERROR_INTERNAL); break; } sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1); usage_len = sizeof(prkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1); if (prkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1); if (prkey->access_flags) { af_len = sizeof(prkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1); } if (prkey->key_reference >= 0) sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 1); r = sc_asn1_encode(ctx, asn1_prkey, buf, buflen); return r; }
int boxing_pace_input_to_buf(sc_context_t *ctx, const struct establish_pace_channel_input *input, unsigned char **asn1, size_t *asn1_len) { size_t pin_id_len = sizeof input->pin_id; struct sc_asn1_entry EstablishPACEChannelInput_data[ sizeof g_EstablishPACEChannelInput_data/ sizeof *g_EstablishPACEChannelInput_data]; struct sc_asn1_entry EstablishPACEChannel[ sizeof g_EstablishPACEChannel/ sizeof *g_EstablishPACEChannel]; struct sc_asn1_entry passwordID[ sizeof g_int_as_octet_string/ sizeof *g_int_as_octet_string]; struct sc_asn1_entry transmittedPassword[ sizeof g_numeric_string_as_octet_string/ sizeof *g_numeric_string_as_octet_string]; struct sc_asn1_entry cHAT[ sizeof g_octet_string/ sizeof *g_octet_string]; sc_copy_asn1_entry(g_EstablishPACEChannel, EstablishPACEChannel); sc_format_asn1_entry(EstablishPACEChannel, EstablishPACEChannelInput_data, 0, 1); sc_copy_asn1_entry(g_EstablishPACEChannelInput_data, EstablishPACEChannelInput_data); sc_format_asn1_entry(EstablishPACEChannelInput_data+0, passwordID, 0, 1); sc_copy_asn1_entry(g_int_as_octet_string, passwordID); sc_format_asn1_entry(passwordID, (unsigned char *) &input->pin_id, &pin_id_len, 1); if (input->pin) { sc_format_asn1_entry(EstablishPACEChannelInput_data+1, transmittedPassword, 0, 1); sc_copy_asn1_entry(g_numeric_string_as_octet_string, transmittedPassword); sc_format_asn1_entry(transmittedPassword, (unsigned char *) input->pin, (size_t *) &input->pin_length, 1); } if (input->chat) { sc_format_asn1_entry(EstablishPACEChannelInput_data+2, cHAT, 0, 1); sc_copy_asn1_entry(g_octet_string, cHAT); sc_format_asn1_entry(cHAT, (unsigned char *) input->chat, (size_t *) &input->chat_length, 1); } if (input->certificate_description) { sc_format_asn1_entry(EstablishPACEChannelInput_data+3, (unsigned char *) input->certificate_description, (size_t *) &input->certificate_description_length, 1); } return sc_asn1_encode(ctx, EstablishPACEChannel, asn1, asn1_len); }
/* * can be used as an SC_ASN1_CALLBACK while parsing a certificate, * or can be called from the sc_pkcs15_pubkey_from_spki_filename */ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubkey, u8 *buf, size_t buflen, int depth) { int r; sc_pkcs15_pubkey_t * pubkey = NULL; sc_pkcs15_der_t pk = { NULL, 0 }; struct sc_algorithm_id pk_alg; struct sc_asn1_entry asn1_pkinfo[C_ASN1_PKINFO_ATTR_SIZE]; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_log(ctx, "sc_pkcs15_pubkey_from_spki %p:%d", buf, buflen); memset(&pk_alg, 0, sizeof(pk_alg)); pubkey = calloc(1, sizeof(sc_pkcs15_pubkey_t)); if (pubkey == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } sc_copy_asn1_entry(c_asn1_pkinfo, asn1_pkinfo); sc_format_asn1_entry(asn1_pkinfo + 0, &pk_alg, NULL, 0); sc_format_asn1_entry(asn1_pkinfo + 1, &pk.value, &pk.len, 0); r = sc_asn1_decode(ctx, asn1_pkinfo, buf, buflen, NULL, NULL); if (r < 0) goto err; pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); if (pubkey->alg_id == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id)); pubkey->algorithm = pk_alg.algorithm; pk_alg.params = NULL; sc_log(ctx, "DEE pk_alg.algorithm=%d", pk_alg.algorithm); /* pk.len is in bits at this point */ switch (pk_alg.algorithm) { case SC_ALGORITHM_EC: /* * TODO we really should only have params in one place! * The alg_id may have the sc_ec_params, * we want to get the curve OID into the * u.ec.params and get the field length too. */ if (pubkey->alg_id->params) { struct sc_ec_params * ecp = (struct sc_ec_params *)pubkey->alg_id->params; pubkey->u.ec.params.der.value = malloc(ecp->der_len); if (pubkey->u.ec.params.der.value) { memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); pubkey->u.ec.params.der.len = ecp->der_len; sc_pkcs15_fix_ec_parameters(ctx,&pubkey->u.ec.params); } } /* * For most keys, the above ASN.1 parsing of a key works, but for EC keys, * the ec_pointQ in a certificate is stored in the bitstring, in its raw format. * RSA for example is stored in the bitstring, as a ASN1 DER * So we encoded the raw ecpointQ into ASN1 DER as the pubkey->data * and let the sc_pkcs15_decode_pubkey below get the ecpointQ out later. */ pk.len >>= 3; /* Assume it is multiple of 8 */ if (pubkey->u.ec.params.field_length == 0) pubkey->u.ec.params.field_length = (pk.len - 1)/2 * 8; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(&asn1_ec_pointQ[0], pk.value, &pk.len, 1); r = sc_asn1_encode(ctx, asn1_ec_pointQ, &pubkey->data.value, &pubkey->data.len); pk.value = NULL; sc_log(ctx, "DEE r=%d data=%p:%d", r, pubkey->data.value, pubkey->data.len); break; default: pk.len >>= 3; /* convert number of bits to bytes */ pubkey->data = pk; /* save in publey */ pk.value = NULL; break; } /* Now decode what every is in pk as it depends on the key algorthim */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); if (r < 0) goto err; *outpubkey = pubkey; pubkey = NULL; return 0; err: if (pubkey) free(pubkey); if (pk.value) free(pk.value); LOG_TEST_RET(ctx, r, "ASN.1 parsing of subjectPubkeyInfo failed"); LOG_FUNC_RETURN(ctx, r); }
int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[2]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_prk_rsa_attr[2]; struct sc_asn1_entry asn1_dsakey_attr[2], asn1_prk_dsa_attr[2], asn1_dsakey_value_attr[3], asn1_dsakey_i_p_attr[2]; struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_prk_gostr3410_attr[2]; struct sc_asn1_entry asn1_prkey[4]; struct sc_asn1_pkcs15_object rsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_rsa_attr }; struct sc_asn1_pkcs15_object dsa_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_dsa_attr }; struct sc_asn1_pkcs15_object gostr3410_prkey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_gostr3410_attr }; struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; int r; size_t af_len, usage_len; sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_prk_dsa_attr, asn1_prk_dsa_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_dsakey_value_attr, asn1_dsakey_value_attr); sc_copy_asn1_entry(c_asn1_dsakey_i_p_attr, asn1_dsakey_i_p_attr); sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr); sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 1); sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 1); break; case SC_PKCS15_TYPE_PRKEY_DSA: sc_format_asn1_entry(asn1_prkey + 1, &dsa_prkey_obj, NULL, 1); sc_format_asn1_entry(asn1_prk_dsa_attr + 0, asn1_dsakey_value_attr, NULL, 1); if (prkey->path.type != SC_PATH_TYPE_PATH_PROT) { /* indirect: just add the path */ sc_format_asn1_entry(asn1_dsakey_value_attr + 0, &prkey->path, NULL, 1); } else { /* indirect-protected */ sc_format_asn1_entry(asn1_dsakey_value_attr + 1, asn1_dsakey_i_p_attr, NULL, 1); sc_format_asn1_entry(asn1_dsakey_i_p_attr + 0, &prkey->path, NULL, 1); } break; case SC_PKCS15_TYPE_PRKEY_GOSTR3410: sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 1); sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &prkey->path, NULL, 1); if (prkey->params.len == sizeof(*keyinfo_gostparams)) { keyinfo_gostparams = prkey->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; default: sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Invalid private key type: %X", obj->type); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); break; } sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1); usage_len = sizeof(prkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1); if (prkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1); if (prkey->access_flags) { af_len = sizeof(prkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1); } if (prkey->key_reference >= 0) sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 1); sc_format_asn1_entry(asn1_com_prkey_attr + 0, prkey->subject.value, &prkey->subject.len, prkey->subject.len != 0); r = sc_asn1_encode(ctx, asn1_prkey, buf, buflen); return r; }
static int parse_x509_cert(sc_context_t *ctx, struct sc_pkcs15_der *der, struct sc_pkcs15_cert *cert) { int r; struct sc_algorithm_id sig_alg; struct sc_pkcs15_pubkey *pubkey = NULL; unsigned char *serial = NULL, *issuer = NULL, *subject = NULL, *buf = der->value; size_t serial_len = 0, issuer_len = 0, subject_len = 0, data_len = 0, buflen = der->len; struct sc_asn1_entry asn1_version[] = { { "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, &cert->version, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_x509v3[] = { { "certificatePolicies", SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "subjectKeyIdentifier", SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "crlDistributionPoints", SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, &cert->crl, &cert->crl_len }, { "authorityKeyIdentifier", SC_ASN1_OCTET_STRING, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "keyUsage", SC_ASN1_BOOLEAN, SC_ASN1_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_extensions[] = { { "x509v3", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_x509v3, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_tbscert[] = { { "version", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_version, NULL }, { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, &serial, &serial_len }, { "signature", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &issuer, &issuer_len }, { "validity", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &subject, &subject_len }, /* Use a callback to get the algorithm, parameters and pubkey into sc_pkcs15_pubkey */ { "subjectPublicKeyInfo",SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki, &pubkey }, { "extensions", SC_ASN1_STRUCT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_extensions, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_cert[] = { { "tbsCertificate", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert, NULL }, { "signatureAlgorithm", SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, &sig_alg, NULL }, { "signatureValue", SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_serial_number[] = { { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_subject[] = { { "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_issuer[] = { { "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; const u8 *obj; size_t objlen; memset(cert, 0, sizeof(*cert)); obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &objlen); if (obj == NULL) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found"); data_len = objlen + (obj - buf); cert->data.value = malloc(data_len); if (!cert->data.value) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(cert->data.value, buf, data_len); cert->data.len = data_len; r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL); LOG_TEST_RET(ctx, r, "ASN.1 parsing of certificate failed"); cert->version++; if (!pubkey) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert"); cert->key = pubkey; sc_asn1_clear_algorithm_id(&sig_alg); if (serial && serial_len) { sc_format_asn1_entry(asn1_serial_number + 0, serial, &serial_len, 1); r = sc_asn1_encode(ctx, asn1_serial_number, &cert->serial, &cert->serial_len); free(serial); LOG_TEST_RET(ctx, r, "ASN.1 encoding of serial failed"); } if (subject && subject_len) { sc_format_asn1_entry(asn1_subject + 0, subject, &subject_len, 1); r = sc_asn1_encode(ctx, asn1_subject, &cert->subject, &cert->subject_len); free(subject); LOG_TEST_RET(ctx, r, "ASN.1 encoding of subject"); } if (issuer && issuer_len) { sc_format_asn1_entry(asn1_issuer + 0, issuer, &issuer_len, 1); r = sc_asn1_encode(ctx, asn1_issuer, &cert->issuer, &cert->issuer_len); free(issuer); LOG_TEST_RET(ctx, r, "ASN.1 encoding of issuer"); } return SC_SUCCESS; }
int sc_pkcs15_encode_unusedspace(sc_context_t *ctx, struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen) { sc_path_t dummy_path; static const struct sc_asn1_entry c_asn1_unusedspace[] = { { "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; static const struct sc_asn1_entry c_asn1_unusedspace_values[] = { { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry *asn1_unusedspace = NULL; struct sc_asn1_entry *asn1_values = NULL; int unusedspace_count = 0, r, c = 0; sc_pkcs15_unusedspace_t *unusedspace; sc_format_path("3F00", &dummy_path); dummy_path.index = dummy_path.count = 0; unusedspace = p15card->unusedspace_list; for ( ; unusedspace != NULL; unusedspace = unusedspace->next) unusedspace_count++; if (unusedspace_count == 0) { /* The standard says there has to be at least 1 entry, * so we use a path with a length of 0 bytes */ r = sc_pkcs15_add_unusedspace(p15card, &dummy_path, NULL); if (r) return r; unusedspace_count = 1; } asn1_unusedspace = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count + 1)); if (asn1_unusedspace == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } asn1_values = (struct sc_asn1_entry *) malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count * 3)); if (asn1_values == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } for (unusedspace = p15card->unusedspace_list; unusedspace != NULL; unusedspace = unusedspace->next) { sc_copy_asn1_entry(c_asn1_unusedspace, asn1_unusedspace + c); sc_format_asn1_entry(asn1_unusedspace + c, asn1_values + 3*c, NULL, 1); sc_copy_asn1_entry(c_asn1_unusedspace_values, asn1_values + 3*c); sc_format_asn1_entry(asn1_values + 3*c, &unusedspace->path, NULL, 1); sc_format_asn1_entry(asn1_values + 3*c+1, &unusedspace->auth_id, NULL, unusedspace->auth_id.len); c++; } asn1_unusedspace[c].name = NULL; r = sc_asn1_encode(ctx, asn1_unusedspace, buf, buflen); err: if (asn1_values != NULL) free(asn1_values); if (asn1_unusedspace != NULL) free(asn1_unusedspace); /* If we added the dummy entry, remove it now */ if (unusedspace_count == 1 && sc_compare_path(&p15card->unusedspace_list->path, &dummy_path)) sc_pkcs15_remove_unusedspace(p15card, p15card->unusedspace_list); return r; }