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); }
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; }
static int asn1_decode_pbkdf2_params(sc_context_t *ctx, void **paramp, const u8 *buf, size_t buflen, int depth) { struct sc_pbkdf2_params info; struct sc_asn1_entry asn1_pbkdf2_params[5]; int r; sc_copy_asn1_entry(c_asn1_pbkdf2_params, asn1_pbkdf2_params); sc_format_asn1_entry(asn1_pbkdf2_params + 0, info.salt, &info.salt_len, 0); sc_format_asn1_entry(asn1_pbkdf2_params + 1, &info.iterations, NULL, 0); sc_format_asn1_entry(asn1_pbkdf2_params + 2, &info.key_length, NULL, 0); sc_format_asn1_entry(asn1_pbkdf2_params + 3, &info.hash_alg, NULL, 0); memset(&info, 0, sizeof(info)); info.salt_len = sizeof(info.salt); info.hash_alg.algorithm = SC_ALGORITHM_SHA1; r = _sc_asn1_decode(ctx, asn1_pbkdf2_params, buf, buflen, NULL, NULL, 0, depth + 1); if (r < 0) return r; *paramp = malloc(sizeof(info)); if (!*paramp) return SC_ERROR_OUT_OF_MEMORY; memcpy(*paramp, &info, sizeof(info)); return 0; }
int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_cert_info info; 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_asn1_pkcs15_object cert_obj = { obj, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; sc_pkcs15_der_t *der = &info.value; u8 id_value[128]; int id_type; size_t id_value_len = sizeof(id_value); 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_cred_ident + 0, &id_type, NULL, 0); sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0); sc_format_asn1_entry(asn1_com_cert_attr + 0, &info.id, NULL, 0); sc_format_asn1_entry(asn1_com_cert_attr + 1, &info.authority, NULL, 0); sc_format_asn1_entry(asn1_com_cert_attr + 2, asn1_cred_ident, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_attr + 0, asn1_x509_cert_value_choice, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_type_cert_attr + 0, asn1_x509_cert_attr, NULL, 0); sc_format_asn1_entry(asn1_cert + 0, &cert_obj, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); info.authority = 0; r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen); /* In case of error, trash the cert value (direct coding) */ if (r < 0 && der->value) free(der->value); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 decoding failed"); r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); if (r < 0) return r; obj->type = SC_PKCS15_TYPE_CERT_X509; obj->data = malloc(sizeof(info)); if (obj->data == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); return 0; }
int sc_pkcs15_parse_unusedspace(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card) { const u8 *p = buf; size_t left = buflen; int r; sc_path_t path, dummy_path; sc_pkcs15_id_t auth_id; struct sc_asn1_entry asn1_unusedspace[] = { { "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry 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 } }; /* Clean the list if already present */ while (card->unusedspace_list) sc_pkcs15_remove_unusedspace(card, card->unusedspace_list); sc_format_path("3F00", &dummy_path); dummy_path.index = dummy_path.count = 0; sc_format_asn1_entry(asn1_unusedspace, asn1_unusedspace_values, NULL, 1); sc_format_asn1_entry(asn1_unusedspace_values, &path, NULL, 1); sc_format_asn1_entry(asn1_unusedspace_values+1, &auth_id, NULL, 0); while (left > 0) { memset(&auth_id, 0, sizeof(auth_id)); r = sc_asn1_decode(card->card->ctx, asn1_unusedspace, p, left, &p, &left); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) break; if (r < 0) return r; /* If the path length is 0, it's a dummy path then don't add it. * If the path length isn't included (-1) then it's against the standard * but we'll just ignore it instead of returning an error. */ if (path.count > 0) { r = sc_pkcs15_make_absolute_path(&card->file_app->path, &path); if (r < 0) return r; r = sc_pkcs15_add_unusedspace(card, &path, &auth_id); if (r) return r; } } card->unusedspace_read = 1; return 0; }
int sc_pkcs15_decode_enveloped_data(sc_context_t *ctx, struct sc_pkcs15_enveloped_data *result, const u8 *buf, size_t buflen) { 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]; struct sc_pkcs15_enveloped_data data; int 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 + 2, asn1_recipients_attr, NULL, 0); sc_format_asn1_entry(asn1_enveloped_data_attr + 3, asn1_content_attr, NULL, 0); sc_format_asn1_entry(asn1_content_attr + 1, &data.ce_alg, NULL, 0); sc_format_asn1_entry(asn1_content_attr + 2, asn1_encr_content, NULL, 0); sc_format_asn1_entry(asn1_encr_content + 0, &data.content, &data.content_len, 0); sc_format_asn1_entry(asn1_recipients_attr + 0, asn1_kekri_attr, NULL, 0); sc_format_asn1_entry(asn1_kekri_attr + 1, asn1_kek_attr, NULL, 0); sc_format_asn1_entry(asn1_kekri_attr + 2, &data.ke_alg, NULL, 0); sc_format_asn1_entry(asn1_kekri_attr + 3, &data.key, &data.key_len, 0); sc_format_asn1_entry(asn1_kek_attr + 0, &data.id, &data.id.len, 0); memset(&data, 0, sizeof(data)); r = sc_asn1_decode(ctx, asn1_enveloped_data_attr, buf, buflen, NULL, NULL); if (r >= 0) *result = data; return r; }
static int parse_ddo(struct sc_pkcs15_card *p15card, const u8 * buf, size_t buflen) { struct sc_asn1_entry asn1_ddo[5]; sc_path_t odf_path, ti_path, us_path; int r; sc_copy_asn1_entry(c_asn1_ddo, asn1_ddo); sc_format_asn1_entry(asn1_ddo + 1, &odf_path, NULL, 0); sc_format_asn1_entry(asn1_ddo + 2, &ti_path, NULL, 0); sc_format_asn1_entry(asn1_ddo + 3, &us_path, NULL, 0); r = sc_asn1_decode(p15card->card->ctx, asn1_ddo, buf, buflen, NULL, NULL); if (r) { sc_error(p15card->card->ctx, "DDO parsing failed: %s\n", sc_strerror(r)); return r; } if (asn1_ddo[1].flags & SC_ASN1_PRESENT) { p15card->file_odf = sc_file_new(); if (p15card->file_odf == NULL) goto mem_err; p15card->file_odf->path = odf_path; } if (asn1_ddo[2].flags & SC_ASN1_PRESENT) { p15card->file_tokeninfo = sc_file_new(); if (p15card->file_tokeninfo == NULL) goto mem_err; p15card->file_tokeninfo->path = ti_path; } if (asn1_ddo[3].flags & SC_ASN1_PRESENT) { p15card->file_unusedspace = sc_file_new(); if (p15card->file_unusedspace == NULL) goto mem_err; p15card->file_unusedspace->path = us_path; } return 0; mem_err: if (p15card->file_odf != NULL) { sc_file_free(p15card->file_odf); p15card->file_odf = NULL; } if (p15card->file_tokeninfo != NULL) { sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } if (p15card->file_unusedspace != NULL) { sc_file_free(p15card->file_unusedspace); p15card->file_unusedspace = NULL; } return SC_ERROR_OUT_OF_MEMORY; }
int sc_pkcs15_decode_dodf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_data_info info; struct sc_asn1_entry asn1_com_data_attr[3], asn1_type_data_attr[2], asn1_data[2]; struct sc_asn1_pkcs15_object data_obj = { obj, asn1_com_data_attr, NULL, asn1_type_data_attr }; size_t label_len = sizeof(info.app_label); int r; 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); sc_format_asn1_entry(asn1_com_data_attr + 0, &info.app_label, &label_len, 0); sc_format_asn1_entry(asn1_com_data_attr + 1, &info.app_oid, NULL, 0); sc_format_asn1_entry(asn1_type_data_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_data + 0, &data_obj, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); sc_init_oid(&info.app_oid); r = sc_asn1_decode(ctx, asn1_data, *buf, *buflen, buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 decoding failed"); if (!p15card->app || !p15card->app->ddo.aid.len) { r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); if (r < 0) return r; } else { info.path.aid = p15card->app->ddo.aid; } obj->type = SC_PKCS15_TYPE_DATA_OBJECT; obj->data = malloc(sizeof(info)); if (obj->data == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); return SC_SUCCESS; }
static int asn1_encode_pbes2_params(sc_context_t *ctx, void *params, u8 **buf, size_t *buflen, int depth) { struct sc_asn1_entry asn1_pbes2_params[3]; struct sc_pbes2_params *info; info = (struct sc_pbes2_params *) params; sc_copy_asn1_entry(c_asn1_pbes2_params, asn1_pbes2_params); sc_format_asn1_entry(asn1_pbes2_params + 0, &info->derivation_alg, NULL, 0); sc_format_asn1_entry(asn1_pbes2_params + 1, &info->key_encr_alg, NULL, 0); return _sc_asn1_encode(ctx, asn1_pbes2_params, buf, buflen, depth + 1); }
static int format_le(size_t le, struct sc_asn1_entry *le_entry, u8 **lebuf, size_t *le_len) { u8 *p; if (!lebuf || !le_len) return SC_ERROR_INVALID_ARGUMENTS; p = realloc(*lebuf, *le_len); if (!p) return SC_ERROR_OUT_OF_MEMORY; *lebuf = p; switch (*le_len) { case 1: p[0] = le; break; case 2: p[0] = le >> 8; p[1] = le & 0xff; break; case 3: p[0] = 0x00; p[1] = le >> 8; p[2] = le & 0xff; break; default: return SC_ERROR_INVALID_ARGUMENTS; } sc_format_asn1_entry(le_entry, *lebuf, le_len, SC_ASN1_PRESENT); return SC_SUCCESS; }
/* * We are storing the ec_pointQ as u8 string. not as DER */ int sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, const u8 *buf, size_t buflen) { int r; u8 * ecpoint_data; size_t ecpoint_len; struct sc_asn1_entry asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE]; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); if (r < 0) LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); sc_log(ctx, "decode-EC key=%p, buf=%p, buflen=%d", key, buf, buflen); key->ecpointQ.len = ecpoint_len; key->ecpointQ.value = ecpoint_data; /* An uncompressed ecpoint is of the form 04||x||y * The 04 indicates uncompressed * x and y are same size, and field_length = sizeof(x) in bits. */ /* TODO: -DEE support more then uncompressed */ key->params.field_length = (ecpoint_len - 1)/2 * 8; return r; }
/* * We are storing the ec_pointQ as a octet string. * Thus we will just copy the string. * But to get the field length we decode it. */ int sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, const u8 *buf, size_t buflen) { int r; u8 * ecpoint_data; size_t ecpoint_len; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); if (r < 0) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"DEE-EC key=%p, buf=%p, buflen=%d", key, buf, buflen); key->ecpointQ.value = malloc(buflen); if (key->ecpointQ.value == NULL) return SC_ERROR_OUT_OF_MEMORY; key->ecpointQ.len = buflen; memcpy(key->ecpointQ.value, buf, buflen); /* An uncompressed ecpoint is of the form 04||x||y * The 04 indicates uncompressed * x and y are same size, and field_length = sizeof(x) in bits. */ /* TODO: -DEE support more then uncompressed */ key->params.field_length = (ecpoint_len - 1)/2 * 8; if (ecpoint_data) free (ecpoint_data); return r; }
static int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card) { const u8 *p = buf; size_t left = buflen; int r, i, type; 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_odf[10]; sc_copy_asn1_entry(c_asn1_odf, asn1_odf); for (i = 0; asn1_odf[i].name != NULL; i++) sc_format_asn1_entry(asn1_odf + i, asn1_obj_or_path, NULL, 0); while (left > 0) { r = sc_asn1_decode_choice(card->card->ctx, asn1_odf, p, left, &p, &left); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) break; if (r < 0) return r; type = r; r = sc_pkcs15_make_absolute_path(&card->file_app->path, &path); if (r < 0) return r; r = sc_pkcs15_add_df(card, odf_indexes[type], &path, NULL); if (r) return r; } return 0; }
int sc_sm_parse_answer(struct sc_card *card, unsigned char *resp_data, size_t resp_len, struct sm_card_response *out) { struct sc_asn1_entry asn1_sm_response[4]; unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; size_t data_len = sizeof(data); unsigned char status[2] = {0, 0}; size_t status_len = sizeof(status); unsigned char mac[8]; size_t mac_len = sizeof(mac); int rv; if (!resp_data || !resp_len || !out) return SC_ERROR_INVALID_ARGUMENTS; sc_copy_asn1_entry(c_asn1_sm_response, asn1_sm_response); sc_format_asn1_entry(asn1_sm_response + 0, data, &data_len, 0); sc_format_asn1_entry(asn1_sm_response + 1, status, &status_len, 0); sc_format_asn1_entry(asn1_sm_response + 2, mac, &mac_len, 0); rv = sc_asn1_decode(card->ctx, asn1_sm_response, resp_data, resp_len, NULL, NULL); if (rv) return rv; if (asn1_sm_response[0].flags & SC_ASN1_PRESENT) { if (data_len > sizeof(out->data)) return SC_ERROR_BUFFER_TOO_SMALL; memcpy(out->data, data, data_len); out->data_len = data_len; } if (asn1_sm_response[1].flags & SC_ASN1_PRESENT) { if (!status[0]) return SC_ERROR_INVALID_DATA; out->sw1 = status[0]; out->sw2 = status[1]; } if (asn1_sm_response[2].flags & SC_ASN1_PRESENT) { memcpy(out->mac, mac, mac_len); out->mac_len = mac_len; } return 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_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, const 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, 0); 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, 0); sc_format_asn1_entry(asn1_rsa_pub_coefficients + 1, &key->exponent.data, &key->exponent.len, 0); r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL); LOG_TEST_RET(ctx, r, "ASN.1 parsing of public key failed"); return SC_SUCCESS; }
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; }
static int asn1_encode_des_params(sc_context_t *ctx, void *params, u8 **buf, size_t *buflen, int depth) { struct sc_asn1_entry asn1_des_iv[2]; int ivlen = 8; sc_copy_asn1_entry(c_asn1_des_iv, asn1_des_iv); sc_format_asn1_entry(asn1_des_iv + 0, params, &ivlen, 1); return _sc_asn1_encode(ctx, asn1_des_iv, buf, buflen, depth + 1); }
static int asn1_encode_gostr3410_params(sc_context_t *ctx, void *params, u8 **buf, size_t *buflen, int depth) { struct sc_asn1_entry asn1_gostr3410_params0[2], asn1_gostr3410_params[4]; struct sc_pkcs15_gost_parameters *gost_params = (struct sc_pkcs15_gost_parameters *)params; int r; sc_copy_asn1_entry(c_asn1_gostr3410_params0, asn1_gostr3410_params0); sc_copy_asn1_entry(c_asn1_gostr3410_params, asn1_gostr3410_params); sc_format_asn1_entry(asn1_gostr3410_params0 + 0, asn1_gostr3410_params, NULL, 1); sc_format_asn1_entry(asn1_gostr3410_params + 0, &gost_params->key, NULL, 1); sc_format_asn1_entry(asn1_gostr3410_params + 1, &gost_params->hash, NULL, 1); /* sc_format_asn1_entry(asn1_gostr3410_params + 2, &cipherp, NULL, 1); */ r = _sc_asn1_encode(ctx, asn1_gostr3410_params0, buf, buflen, depth + 1); sc_log(ctx, "encoded-params: %s", sc_dump_hex(*buf, *buflen)); return r; }
static int asn1_decode_gostr3410_params(sc_context_t *ctx, void **paramp, const u8 *buf, size_t buflen, int depth) { struct sc_asn1_entry asn1_gostr3410_params0[2], asn1_gostr3410_params[4]; struct sc_object_id keyp, hashp, cipherp; int r; sc_copy_asn1_entry(c_asn1_gostr3410_params0, asn1_gostr3410_params0); sc_copy_asn1_entry(c_asn1_gostr3410_params, asn1_gostr3410_params); sc_format_asn1_entry(asn1_gostr3410_params0 + 0, asn1_gostr3410_params, NULL, 0); sc_format_asn1_entry(asn1_gostr3410_params + 0, &keyp, NULL, 0); sc_format_asn1_entry(asn1_gostr3410_params + 1, &hashp, NULL, 0); sc_format_asn1_entry(asn1_gostr3410_params + 2, &cipherp, NULL, 0); r = _sc_asn1_decode(ctx, asn1_gostr3410_params0, buf, buflen, NULL, NULL, 0, depth + 1); /* TODO: store in paramp */ (void)paramp; /* no warning */ return r; }
static int asn1_decode_ec_params(sc_context_t *ctx, void **paramp, const u8 *buf, size_t buflen, int depth) { int r; struct sc_object_id curve; struct sc_asn1_entry asn1_ec_params[4]; struct sc_ec_parameters *ecp; sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params %p:%"SC_FORMAT_LEN_SIZE_T"u %d", buf, buflen, depth); memset(&curve, 0, sizeof(curve)); /* We only want to copy the parms if they are a namedCurve * or ecParameters nullParam aka implicityCA is not to be * used with PKCS#11 2.20 */ sc_copy_asn1_entry(c_asn1_ec_params, asn1_ec_params); sc_format_asn1_entry(asn1_ec_params + 1, &curve, 0, 0); /* Some signature algorithms will not have any data */ if (buflen == 0 || buf == NULL) return 0; r = sc_asn1_decode_choice(ctx, asn1_ec_params, buf, buflen, NULL, NULL); /* r = index in asn1_ec_params */ sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_decode_ec_params r=%d", r); if (r < 0) return r; ecp = calloc(sizeof(struct sc_ec_parameters), 1); if (ecp == NULL) return SC_ERROR_OUT_OF_MEMORY; if (r <= 1) { ecp->der.value = malloc(buflen); if (ecp->der.value == NULL) { free(ecp); return SC_ERROR_OUT_OF_MEMORY; } ecp->der.len = buflen; memcpy(ecp->der.value, buf, buflen); } else { r = 0; } ecp->type = r; /* but 0 = ecparams if any, 1=named curve */ *paramp = ecp; return SC_SUCCESS; };
static int sc_sm_parse_answer(struct sc_context *ctx, unsigned char *resp_data, size_t resp_len, struct sm_card_response *out) { struct sc_asn1_entry asn1_sm_response[4]; unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; size_t data_len = sizeof(data); unsigned char status[2] = {0, 0}; size_t status_len = sizeof(status); unsigned char mac[8]; size_t mac_len = sizeof(mac); int r; if (!resp_data || !resp_len || !out) return SC_ERROR_INVALID_ARGUMENTS; sc_copy_asn1_entry(c_asn1_sm_response, asn1_sm_response); sc_format_asn1_entry(asn1_sm_response + 0, data, &data_len, 0); sc_format_asn1_entry(asn1_sm_response + 1, status, &status_len, 0); sc_format_asn1_entry(asn1_sm_response + 2, mac, &mac_len, 0); r = sc_asn1_decode(ctx, asn1_sm_response, resp_data, resp_len, NULL, NULL); if (r) return r; if (asn1_sm_response[1].flags & SC_ASN1_PRESENT) { out->sw1 = status[0]; out->sw2 = status[1]; } if (asn1_sm_response[2].flags & SC_ASN1_PRESENT) { memcpy(out->mac, mac, mac_len); out->mac_len = mac_len; } /* TODO: to be continued ... */ return SC_SUCCESS; }
int sc_pkcs15_decode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key, const 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; 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, 0); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 1, &key->g.data, &key->g.len, 0); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 2, &key->p.data, &key->p.len, 0); sc_format_asn1_entry(asn1_dsa_pub_coefficients + 3, &key->q.data, &key->q.len, 0); r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL); LOG_TEST_RET(ctx, r, "ASN.1 decoding failed"); return 0; }
static int sc_pkcs15_decode_prkey_dsa(sc_context_t *ctx, struct sc_pkcs15_prkey_dsa *key, const 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, 0); return sc_asn1_decode(ctx, asn1_dsa_prkey_obj, buf, buflen, NULL, NULL); }
static int format_data(sc_card_t *card, const struct iso_sm_ctx *ctx, const u8 *data, size_t datalen, struct sc_asn1_entry *formatted_encrypted_data_entry, u8 **formatted_data, size_t *formatted_data_len) { int r; u8 *pad_data = NULL; size_t pad_data_len = 0; if (!ctx || !formatted_data || !formatted_data_len) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } r = add_padding(ctx, data, datalen, &pad_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not add padding to data: %s", sc_strerror(r)); goto err; } pad_data_len = r; bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to encrypt", pad_data, pad_data_len); r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt the data"); goto err; } bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptogram", *formatted_data, r); r = prefix_buf(ctx->padding_indicator, *formatted_data, r, formatted_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not prepend padding indicator to formatted " "data: %s", sc_strerror(r)); goto err; } *formatted_data_len = r; sc_format_asn1_entry(formatted_encrypted_data_entry, *formatted_data, formatted_data_len, SC_ASN1_PRESENT); r = SC_SUCCESS; err: if (pad_data) { sc_mem_clear(pad_data, pad_data_len); free(pad_data); } return r; }
int sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key, const u8 *buf, size_t buflen) { struct sc_asn1_entry asn1_public_key[2]; struct sc_asn1_entry asn1_rsa_coeff[3]; int r; sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_coeff, NULL, 0); sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_coeff); sc_format_asn1_entry(asn1_rsa_coeff + 0, &key->modulus.data, &key->modulus.len, 0); sc_format_asn1_entry(asn1_rsa_coeff + 1, &key->exponent.data, &key->exponent.len, 0); r = sc_asn1_decode(ctx, asn1_public_key, buf, buflen, NULL, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 parsing of public key failed"); return 0; }
static int asn1_encode_pbkdf2_params(sc_context_t *ctx, void *params, u8 **buf, size_t *buflen, int depth) { struct sc_pbkdf2_params *info; struct sc_asn1_entry asn1_pbkdf2_params[5]; info = (struct sc_pbkdf2_params *) params; sc_copy_asn1_entry(c_asn1_pbkdf2_params, asn1_pbkdf2_params); sc_format_asn1_entry(asn1_pbkdf2_params + 0, info->salt, &info->salt_len, 1); sc_format_asn1_entry(asn1_pbkdf2_params + 1, &info->iterations, NULL, 1); if (info->key_length > 0) sc_format_asn1_entry(asn1_pbkdf2_params + 2, &info->key_length, NULL, 1); if (info->hash_alg.algorithm != SC_ALGORITHM_SHA1) sc_format_asn1_entry(asn1_pbkdf2_params + 3, &info->hash_alg, NULL, 0); return _sc_asn1_encode(ctx, asn1_pbkdf2_params, buf, buflen, depth + 1); }
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); }
static int asn1_decode_pbes2_params(sc_context_t *ctx, void **paramp, const u8 *buf, size_t buflen, int depth) { struct sc_asn1_entry asn1_pbes2_params[3]; struct sc_pbes2_params info; int r; sc_copy_asn1_entry(c_asn1_pbes2_params, asn1_pbes2_params); sc_format_asn1_entry(asn1_pbes2_params + 0, &info.derivation_alg, NULL, 0); sc_format_asn1_entry(asn1_pbes2_params + 1, &info.key_encr_alg, NULL, 0); memset(&info, 0, sizeof(info)); r = _sc_asn1_decode(ctx, asn1_pbes2_params, buf, buflen, NULL, NULL, 0, depth + 1); if (r < 0) return r; *paramp = malloc(sizeof(info)); if (!*paramp) return SC_ERROR_OUT_OF_MEMORY; memcpy(*paramp, &info, sizeof(info)); return 0; }