static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot, sc_apdu_t *apdu) { size_t ssize, rsize, rbuflen = 0; u8 *sbuf = NULL, *rbuf = NULL; int r; /* we always use a at least 258 byte size big return buffer * to mimic the behaviour of the old implementation (some readers * seems to require a larger than necessary return buffer). * The buffer for the returned data needs to be at least 2 bytes * larger than the expected data length to store SW1 and SW2. */ rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2; rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_MEMORY_FAILURE; goto out; } /* encode and log the APDU */ r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, slot->active_protocol); if (r != SC_SUCCESS) goto out; if (reader->ctx->debug >= 6) sc_apdu_log(reader->ctx, sbuf, ssize, 1); r = pcsc_internal_transmit(reader, slot, sbuf, ssize, rbuf, &rsize, apdu->control); if (r < 0) { /* unable to transmit ... most likely a reader problem */ sc_error(reader->ctx, "unable to transmit"); goto out; } if (reader->ctx->debug >= 6) sc_apdu_log(reader->ctx, rbuf, rsize, 0); /* set response */ r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize); out: if (sbuf != NULL) { sc_mem_clear(sbuf, ssize); free(sbuf); } if (rbuf != NULL) { sc_mem_clear(rbuf, rbuflen); free(rbuf); } return r; }
static void sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) { assert(key != NULL); switch (key->algorithm) { case SC_ALGORITHM_RSA: free(key->u.rsa.modulus.data); free(key->u.rsa.exponent.data); free(key->u.rsa.d.data); free(key->u.rsa.p.data); free(key->u.rsa.q.data); free(key->u.rsa.iqmp.data); free(key->u.rsa.dmp1.data); free(key->u.rsa.dmq1.data); break; case SC_ALGORITHM_DSA: free(key->u.dsa.pub.data); free(key->u.dsa.p.data); free(key->u.dsa.q.data); free(key->u.dsa.g.data); free(key->u.dsa.priv.data); break; case SC_ALGORITHM_GOSTR3410: assert(key->u.gostr3410.d.data); free(key->u.gostr3410.d.data); break; case SC_ALGORITHM_EC: /* TODO: -DEE may not need much */ break; } sc_mem_clear(key, sizeof(key)); }
static int openct_reader_transmit(sc_reader_t *reader, sc_slot_info_t *slot, sc_apdu_t *apdu) { size_t ssize, rsize, rbuflen = 0; u8 *sbuf = NULL, *rbuf = NULL; int r; rsize = rbuflen = apdu->resplen + 2; rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_MEMORY_FAILURE; goto out; } /* encode and log the APDU */ r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW); if (r != SC_SUCCESS) goto out; if (reader->ctx->debug >= 6) sc_apdu_log(reader->ctx, sbuf, ssize, 1); r = openct_reader_internal_transmit(reader, slot, sbuf, ssize, rbuf, &rsize, apdu->control); if (r < 0) { /* unable to transmit ... most likely a reader problem */ sc_error(reader->ctx, "unable to transmit"); goto out; } if (reader->ctx->debug >= 6) sc_apdu_log(reader->ctx, rbuf, rsize, 0); /* set response */ r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize); out: if (sbuf != NULL) { sc_mem_clear(sbuf, ssize); free(sbuf); } if (rbuf != NULL) { sc_mem_clear(rbuf, rbuflen); free(rbuf); } return r; }
static int ctapi_transmit(sc_reader_t *reader, sc_apdu_t *apdu) { size_t ssize, rsize, rbuflen = 0; u8 *sbuf = NULL, *rbuf = NULL; int r; rsize = rbuflen = apdu->resplen + 2; rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } /* encode and log the APDU */ r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW); if (r != SC_SUCCESS) goto out; sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, sbuf, ssize, 1); r = ctapi_internal_transmit(reader, sbuf, ssize, rbuf, &rsize, apdu->control); if (r < 0) { /* unable to transmit ... most likely a reader problem */ sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to transmit"); goto out; } sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, rbuf, rsize, 0); /* set response */ r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize); out: if (sbuf != NULL) { sc_mem_clear(sbuf, ssize); free(sbuf); } if (rbuf != NULL) { sc_mem_clear(rbuf, rbuflen); free(rbuf); } return r; }
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; }
/* * Called when releasing a reader. release() has to * deallocate the private data. Other fields will be * freed by OpenSC. */ static int openct_reader_release(sc_reader_t *reader) { struct driver_data *data = (struct driver_data *) reader->drv_data; SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); if (data) { if (data->h && !(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) ct_reader_disconnect(data->h); sc_mem_clear(data, sizeof(*data)); reader->drv_data = NULL; free(data); } return SC_SUCCESS; }
static void sc_card_free(sc_card_t *card) { sc_free_apps(card); sc_free_ef_atr(card); if (card->ef_dir != NULL) sc_file_free(card->ef_dir); free(card->ops); if (card->algorithms != NULL) free(card->algorithms); if (card->mutex != NULL) { int r = sc_mutex_destroy(card->ctx, card->mutex); if (r != SC_SUCCESS) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "unable to destroy mutex"); } sc_mem_clear(card, sizeof(*card)); free(card); }
int sc_release_context(sc_context_t *ctx) { unsigned int i; if (ctx == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); while (list_size(&ctx->readers)) { sc_reader_t *rdr = (sc_reader_t *) list_get_at(&ctx->readers, 0); _sc_delete_reader(ctx, rdr); } if (ctx->reader_driver->ops->finish != NULL) ctx->reader_driver->ops->finish(ctx); for (i = 0; ctx->card_drivers[i]; i++) { struct sc_card_driver *drv = ctx->card_drivers[i]; if (drv->atr_map) _sc_free_atr(ctx, drv); if (drv->dll) sc_dlclose(drv->dll); } if (ctx->preferred_language != NULL) free(ctx->preferred_language); if (ctx->mutex != NULL) { int r = sc_mutex_destroy(ctx, ctx->mutex); if (r != SC_SUCCESS) { sc_log(ctx, "unable to destroy mutex"); return r; } } if (ctx->conf != NULL) scconf_free(ctx->conf); if (ctx->debug_file && (ctx->debug_file != stdout && ctx->debug_file != stderr)) fclose(ctx->debug_file); if (ctx->debug_filename != NULL) free(ctx->debug_filename); if (ctx->app_name != NULL) free(ctx->app_name); list_destroy(&ctx->readers); sc_mem_clear(ctx, sizeof(*ctx)); free(ctx); return SC_SUCCESS; }
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key) { assert(key != NULL); if (key->alg_id) { sc_asn1_clear_algorithm_id(key->alg_id); free(key->alg_id); } switch (key->algorithm) { case SC_ALGORITHM_RSA: if (key->u.rsa.modulus.data) free(key->u.rsa.modulus.data); if (key->u.rsa.exponent.data) free(key->u.rsa.exponent.data); break; case SC_ALGORITHM_DSA: if (key->u.dsa.pub.data) free(key->u.dsa.pub.data); if (key->u.dsa.g.data) free(key->u.dsa.g.data); if (key->u.dsa.p.data) free(key->u.dsa.p.data); if (key->u.dsa.q.data) free(key->u.dsa.q.data); break; case SC_ALGORITHM_GOSTR3410: if (key->u.gostr3410.xy.data) free(key->u.gostr3410.xy.data); break; case SC_ALGORITHM_EC: if (key->u.ec.params.der.value) free(key->u.ec.params.der.value); if (key->u.ec.params.named_curve) free(key->u.ec.params.named_curve); if (key->u.ec.ecpointQ.value) free(key->u.ec.ecpointQ.value); break; } if (key->data.value) free(key->data.value); sc_mem_clear(key, sizeof(*key)); }
static void sc_card_free(sc_card_t *card) { sc_free_apps(card); sc_free_ef_atr(card); if (card->ef_dir != NULL) sc_file_free(card->ef_dir); free(card->ops); if (card->algorithms != NULL) { int i; for (i=0; i<card->algorithm_count; i++) { struct sc_algorithm_info *info = (card->algorithms + i); if (info->algorithm == SC_ALGORITHM_EC) { struct sc_ec_parameters ep = info->u._ec.params; free(ep.named_curve); free(ep.der.value); } } free(card->algorithms); card->algorithms = NULL; card->algorithm_count = 0; } if (card->cache.current_ef) sc_file_free(card->cache.current_ef); if (card->cache.current_df) sc_file_free(card->cache.current_df); if (card->mutex != NULL) { int r = sc_mutex_destroy(card->ctx, card->mutex); if (r != SC_SUCCESS) sc_log(card->ctx, "unable to destroy mutex"); } sc_mem_clear(card, sizeof(*card)); free(card); }
/* * Called when releasing a reader. release() has to * deallocate the private data. Other fields will be * freed by OpenSC. */ static int openct_reader_release(sc_reader_t *reader) { struct driver_data *data = (struct driver_data *) reader->drv_data; int i; SC_FUNC_CALLED(reader->ctx, 1); if (data) { if (data->h) ct_reader_disconnect(data->h); sc_mem_clear(data, sizeof(*data)); reader->drv_data = NULL; free(data); } for (i = 0; i < SC_MAX_SLOTS; i++) { if(reader->slot[i].drv_data) free(reader->slot[i].drv_data); } return SC_NO_ERROR; }
static int esteid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { int r; struct sc_pin_cmd_data tmp; LOG_FUNC_CALLED(card->ctx); sc_log(card->ctx, "PIN CMD is %d", data->cmd); if (data->cmd == SC_PIN_CMD_GET_INFO) { sc_log(card->ctx, "SC_PIN_CMD_GET_INFO for %d", data->pin_reference); r = esteid_get_pin_remaining_tries(card, data->pin_reference); LOG_TEST_RET(card->ctx, r, "GET DATA(pin info) failed"); data->pin1.tries_left = r; data->pin1.max_tries = -1; // "no support, which means the one set in PKCS#15 emulation sticks data->pin1.logged_in = SC_PIN_STATE_UNKNOWN; LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } else if (data->cmd == SC_PIN_CMD_UNBLOCK) { // Verify PUK, then issue UNBLOCK // VERIFY memcpy(&tmp, data, sizeof(struct sc_pin_cmd_data)); tmp.cmd = SC_PIN_CMD_VERIFY; tmp.pin_reference = PUK_REF; tmp.pin2.len = 0; r = iso_ops->pin_cmd(card, &tmp, tries_left); LOG_TEST_RET(card->ctx, r, "VERIFY during unblock failed"); if (data->pin_reference == 0x85) { LOG_TEST_RET(card->ctx, esteid_select_file(card, &adf2, NULL), "Cannot select QSCD AID"); } // UNBLOCK tmp = *data; tmp.cmd = SC_PIN_CMD_UNBLOCK; tmp.pin1.len = 0; r = iso_ops->pin_cmd(card, &tmp, tries_left); sc_mem_clear(&tmp, sizeof(tmp)); LOG_FUNC_RETURN(card->ctx, r); } LOG_FUNC_RETURN(card->ctx, iso_ops->pin_cmd(card, data, tries_left)); }
void sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) { assert(key != NULL); switch (key->algorithm) { case SC_ALGORITHM_RSA: free(key->u.rsa.modulus.data); free(key->u.rsa.exponent.data); free(key->u.rsa.p.data); free(key->u.rsa.q.data); free(key->u.rsa.iqmp.data); free(key->u.rsa.dmp1.data); free(key->u.rsa.dmq1.data); break; case SC_ALGORITHM_DSA: free(key->u.dsa.pub.data); free(key->u.dsa.p.data); free(key->u.dsa.q.data); free(key->u.dsa.g.data); free(key->u.dsa.priv.data); break; } sc_mem_clear(key, sizeof(key)); }
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 *in, size_t inlen, u8 *out, size_t outlen) { int r; sc_security_env_t senv; sc_context_t *ctx = p15card->card->ctx; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; u8 buf[512], *tmp; size_t modlen = prkey->modulus_length / 8; unsigned long pad_flags = 0, sec_flags = 0; SC_FUNC_CALLED(ctx, 1); /* some strange cards/setups need decrypt to sign ... */ if (p15card->flags & SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT) { size_t tmplen = sizeof(buf); if (flags & SC_ALGORITHM_RSA_RAW) { return sc_pkcs15_decipher(p15card, obj,flags, in, inlen, out, outlen); } if (modlen > tmplen) { sc_error(ctx, "Buffer too small, needs recompile!\n"); return SC_ERROR_NOT_ALLOWED; } r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen); /* no padding needed - already done */ flags &= ~SC_ALGORITHM_RSA_PADS; /* instead use raw rsa */ flags |= SC_ALGORITHM_RSA_RAW; SC_TEST_RET(ctx, r, "Unable to add padding"); r = sc_pkcs15_decipher(p15card, obj,flags, buf, modlen, out, outlen); return r; } /* If the key is extractable, the caller should extract the * key and do the crypto himself */ if (!prkey->native) return SC_ERROR_EXTRACTABLE_KEY; if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) { sc_error(ctx, "This key cannot be used for signing\n"); return SC_ERROR_NOT_ALLOWED; } alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_error(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length); return SC_ERROR_NOT_SUPPORTED; } senv.algorithm = SC_ALGORITHM_RSA; /* Probably never happens, but better make sure */ if (inlen > sizeof(buf) || outlen < modlen) return SC_ERROR_BUFFER_TOO_SMALL; memcpy(buf, in, inlen); tmp = buf; /* flags: the requested algo * algo_info->flags: what is supported by the card * senv.algorithm_flags: what the card will have to do */ /* If the card doesn't support the requested algorithm, see if we * can strip the input so a more restrictive algo can be used */ if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && !(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) { unsigned int algo; size_t tmplen = sizeof(buf); r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen); if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) { sc_mem_clear(buf, sizeof(buf)); return SC_ERROR_INVALID_DATA; } flags &= ~SC_ALGORITHM_RSA_HASH_NONE; flags |= algo; inlen = tmplen; } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); if (r != SC_SUCCESS) { sc_mem_clear(buf, sizeof(buf)); return r; } senv.algorithm_flags = sec_flags; /* add the padding bytes (if necessary) */ if (pad_flags != 0) { size_t tmplen = sizeof(buf); r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen); SC_TEST_RET(ctx, r, "Unable to add padding"); inlen = tmplen; } else if ((flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { /* Add zero-padding if input is shorter than the modulus */ if (inlen < modlen) { if (modlen > sizeof(buf)) return SC_ERROR_BUFFER_TOO_SMALL; memmove(tmp+modlen-inlen, tmp, inlen); memset(tmp, 0, modlen-inlen); } } senv.operation = SC_SEC_OPERATION_SIGN; senv.flags = 0; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } senv.flags |= SC_SEC_ENV_ALG_PRESENT; r = sc_lock(p15card->card); SC_TEST_RET(ctx, r, "sc_lock() failed"); if (prkey->path.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); SC_TEST_RET(ctx,r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); SC_TEST_RET(ctx, r, "sc_set_security_env() failed"); } r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); sc_mem_clear(buf, sizeof(buf)); sc_unlock(p15card->card); SC_TEST_RET(ctx, r, "sc_compute_signature() failed"); return r; }
/* * Store a key on the card */ static int rtecp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) { sc_card_t *card; sc_pkcs15_prkey_info_t *key_info; sc_file_t *pukey_df; sc_path_t path; unsigned char *buf; size_t buf_len, key_len, len, i; int r; if (!profile || !p15card || !p15card->card || !p15card->card->ctx || !obj || !obj->data || !key) return SC_ERROR_INVALID_ARGUMENTS; card = p15card->card; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); if ((obj->type != SC_PKCS15_TYPE_PRKEY_RSA || key->algorithm != SC_ALGORITHM_RSA) && (obj->type != SC_PKCS15_TYPE_PRKEY_GOSTR3410 || key->algorithm != SC_ALGORITHM_GOSTR3410)) return SC_ERROR_NOT_SUPPORTED; key_info = (sc_pkcs15_prkey_info_t *)obj->data; assert(key_info); if (key->algorithm == SC_ALGORITHM_RSA) { assert(key_info->modulus_length % 128 == 0); len = key_info->modulus_length / 8 / 2; key_len = len * 5 + 8; buf_len = key_len; } else { assert(key_info->modulus_length == SC_PKCS15_GOSTR3410_KEYSIZE); len = key_info->modulus_length / 8; key_len = len; buf_len = len; } if (key->algorithm == SC_ALGORITHM_RSA && (!key->u.rsa.p.data || !key->u.rsa.q.data || !key->u.rsa.iqmp.data || !key->u.rsa.dmp1.data || !key->u.rsa.dmq1.data || !key->u.rsa.modulus.data || !key->u.rsa.exponent.data || key->u.rsa.p.len != len || key->u.rsa.q.len != len || key->u.rsa.iqmp.len != len || key->u.rsa.dmp1.len != len || key->u.rsa.dmq1.len != len || key->u.rsa.modulus.len != 2*len || key->u.rsa.exponent.len > len || key->u.rsa.exponent.len == 0)) return SC_ERROR_INVALID_ARGUMENTS; if (key->algorithm == SC_ALGORITHM_GOSTR3410 && (!key->u.gostr3410.d.data || key->u.gostr3410.d.len != len)) return SC_ERROR_INVALID_ARGUMENTS; buf = calloc(1, buf_len); if (!buf) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); assert(key_len <= buf_len); if (key->algorithm == SC_ALGORITHM_RSA) { /* p */ for (i = 0; i < len; ++i) buf[i] = key->u.rsa.p.data[len - 1 - i]; /* q */ for (i = 0; i < len; ++i) buf[len + 4 + i] = key->u.rsa.q.data[len - 1 - i]; /* iqmp */ for (i = 0; i < len; ++i) buf[len + 4 + len + 4 + i] = key->u.rsa.iqmp.data[len - 1 - i]; /* dmp1 */ for (i = 0; i < len; ++i) buf[len + 4 + len + 4 + len + i] = key->u.rsa.dmp1.data[len - 1 - i]; /* dmq1 */ for (i = 0; i < len; ++i) buf[len * 4 + 8 + i] = key->u.rsa.dmq1.data[len - 1 - i]; } else { /* d */ for (i = 0; i < len; ++i) buf[i] = key->u.gostr3410.d.data[len - 1 - i]; } path = key_info->path; r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) r = sc_change_reference_data(card, 0, 0, NULL, 0, buf, key_len, NULL); assert(buf); sc_mem_clear(buf, key_len); /* store public key */ if (key->algorithm == SC_ALGORITHM_RSA) key_len = len * 3; else goto end; assert(key_len <= buf_len); if (key->algorithm == SC_ALGORITHM_RSA) { /* modulus */ for (i = 0; i < 2*len; ++i) buf[i] = key->u.rsa.modulus.data[2*len - 1 - i]; /* exponent */ for (i = 0; i < key->u.rsa.exponent.len && i < len; ++i) buf[2 * len + i] = key->u.rsa.exponent.data[ key->u.rsa.exponent.len - 1 - i]; } if (r == SC_SUCCESS) { r = sc_profile_get_file(profile, "PuKey-DF", &pukey_df); if (r == SC_SUCCESS) { assert(pukey_df); path = pukey_df->path; r = sc_append_file_id(&path, key_info->key_reference); sc_file_free(pukey_df); } else if (card->ctx->debug >= 2) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s\n", "Get PuKey-DF info failed"); } if (r == SC_SUCCESS) { r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) r = sc_change_reference_data(card, 0, 0, NULL, 0, buf, key_len, NULL); if (r && card->ctx->debug >= 2) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s\n", "Store public key failed"); } end: assert(buf); free(buf); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 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; }
LIBOPENSC_API int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 *in, size_t inlen, u8 *out, size_t outlen) { sc_context_t *ctx = p15card->card->ctx; int r; sc_security_env_t senv; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; u8 buf[1024], *tmp; size_t modlen; unsigned long pad_flags = 0, sec_flags = 0; LOG_FUNC_CALLED(ctx); sc_log(ctx, "security operation flags 0x%X", flags); memset(&senv, 0, sizeof(senv)); /* Card driver should have the access to supported algorithms from 'tokenInfo'. So that * it can get value of card specific 'AlgorithmInfo::algRef'. */ memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos)); if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private key"); /* If the key is not native, we can't operate with it. */ if (!prkey->native) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it"); if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for signing"); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: modlen = prkey->modulus_length / 8; alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_RSA; break; case SC_PKCS15_TYPE_PRKEY_GOSTR3410: modlen = (prkey->modulus_length + 7) / 8 * 2; alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_GOSTR3410; break; case SC_PKCS15_TYPE_PRKEY_EC: modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.algorithm = SC_ALGORITHM_EC; senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT; senv.algorithm_ref = prkey->field_length; break; /* add other crypto types here */ default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported"); } /* Probably never happens, but better make sure */ if (inlen > sizeof(buf) || outlen < modlen) LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); memcpy(buf, in, inlen); /* revert data to sign when signing with the GOST key. * TODO: can it be confirmed by the GOST standard? * TODO: tested with RuTokenECP, has to be validated for RuToken. */ if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410) sc_mem_reverse(buf, inlen); tmp = buf; /* flags: the requested algo * algo_info->flags: what is supported by the card * senv.algorithm_flags: what the card will have to do */ /* if the card has SC_ALGORITHM_NEED_USAGE set, and the key is for signing and decryption, we need to emulate signing */ /* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */ sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage); if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) && ((prkey->usage & USAGE_ANY_SIGN) && (prkey->usage & USAGE_ANY_DECIPHER)) ) { size_t tmplen = sizeof(buf); if (flags & SC_ALGORITHM_RSA_RAW) { r = sc_pkcs15_decipher(p15card, obj,flags, in, inlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } if (modlen > tmplen) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!"); r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen); /* no padding needed - already done */ flags &= ~SC_ALGORITHM_RSA_PADS; /* instead use raw rsa */ flags |= SC_ALGORITHM_RSA_RAW; LOG_TEST_RET(ctx, r, "Unable to add padding"); r = sc_pkcs15_decipher(p15card, obj,flags, buf, modlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } /* If the card doesn't support the requested algorithm, see if we * can strip the input so a more restrictive algo can be used */ if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && !(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) { unsigned int algo; size_t tmplen = sizeof(buf); r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen); if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); } flags &= ~SC_ALGORITHM_RSA_HASH_NONE; flags |= algo; inlen = tmplen; } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); if (r != SC_SUCCESS) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, r); } senv.algorithm_flags = sec_flags; sc_log(ctx, "DEE flags:0x%8.8x alg_info->flags:0x%8.8x pad:0x%8.8x sec:0x%8.8x", flags, alg_info->flags, pad_flags, sec_flags); /* add the padding bytes (if necessary) */ if (pad_flags != 0) { size_t tmplen = sizeof(buf); r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding"); inlen = tmplen; } else if ( senv.algorithm == SC_ALGORITHM_RSA && (flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { /* Add zero-padding if input is shorter than the modulus */ if (inlen < modlen) { if (modlen > sizeof(buf)) return SC_ERROR_BUFFER_TOO_SMALL; memmove(tmp+modlen-inlen, tmp, inlen); memset(tmp, 0, modlen-inlen); } inlen = modlen; } senv.operation = SC_SEC_OPERATION_SIGN; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } r = sc_lock(p15card->card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); sc_log(ctx, "Private key path '%s'", sc_print_path(&prkey->path)); if (prkey->path.len != 0 || prkey->path.aid.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_set_security_env() failed"); } r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS) r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); sc_mem_clear(buf, sizeof(buf)); sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_compute_signature() failed"); LOG_FUNC_RETURN(ctx, r); }
/* * @brief Use PUT DATA to import a private RSA key. * * For simplicity, command chaining has to be used. One chunk (apdu) must contain * one RSA field (P, Q, etc.). The first apdu must contain the outer tag (7F48). * * @param card * @param rsa The RSA private key to import. * * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. * other errors: Transmit errors / errors returned by card. */ static int isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) { sc_apdu_t apdu; u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; u8 *p = NULL; int r; size_t tags_len; LOG_FUNC_CALLED(card->ctx); if(!args->privkey.rsa.p.value || !args->privkey.rsa.q.value || !args->privkey.rsa.iqmp.value || !args->privkey.rsa.dmp1.value || !args->privkey.rsa.dmq1.value) { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "RSA key is missing information."); } /* Note: The format is according to ISO 2-byte tag 7F48 * "T-L pair to indicate a private key data object" */ /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */ tags_len = 0; r = sc_asn1_put_tag(0x92, NULL, args->privkey.rsa.p.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x93, NULL, args->privkey.rsa.q.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x94, NULL, args->privkey.rsa.iqmp.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x95, NULL, args->privkey.rsa.dmp1.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x96, NULL, args->privkey.rsa.dmq1.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; /* Write the outer tag and length information. */ p = sbuf; r = sc_asn1_put_tag(0x7F48, NULL, tags_len, p, sizeof(sbuf), &p); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); /* Write inner tags. */ /* p */ r = sc_asn1_put_tag(0x92, args->privkey.rsa.p.value, args->privkey.rsa.p.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* q */ r = sc_asn1_put_tag(0x93, args->privkey.rsa.q.value, args->privkey.rsa.q.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* 1/q mod p */ r = sc_asn1_put_tag(0x94, args->privkey.rsa.iqmp.value, args->privkey.rsa.iqmp.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* d mod (p-1) */ r = sc_asn1_put_tag(0x95, args->privkey.rsa.dmp1.value, args->privkey.rsa.dmp1.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* d mod (q-1) */ r = sc_asn1_put_tag(0x96, args->privkey.rsa.dmq1.value, args->privkey.rsa.dmq1.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* Send to card, using chaining or extended APDUs. */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0) { /* The lower layers will automatically do chaining */ apdu.flags |= SC_APDU_FLAGS_CHAINING; } r = sc_transmit_apdu(card, &apdu); if(r < 0) goto out; r = sc_check_sw(card, apdu.sw1, apdu.sw2); if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) { sc_log(card->ctx, "Key import not supported by the card with that particular key type. " "Your card may not support the specified algorithm used by the applet / specified by you. " "In most cases, this happens when trying to import EC keys not supported by your java card. " "In this case, look for supported field lengths and whether FP and/or F2M are supported. " "If you tried to import a private RSA key, check the key length."); } if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) { sc_log(card->ctx, "Key import not allowed by the applet's security policy. " "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," " rebuild and reinstall the applet."); } if(r < 0) goto out; r = SC_SUCCESS; out: sc_mem_clear(sbuf, sizeof(sbuf)); LOG_FUNC_RETURN(card->ctx, r); }
static int __sc_ui_read_pin(sc_context_t *ctx, const char *prompt, const char *label, int flags, sc_pkcs15_pin_info_t *pin_info, char **out) { if (prompt) { printf("%s", prompt); if (flags & SC_UI_PIN_OPTIONAL) printf(" (Optional - press return for no PIN)"); printf(".\n"); } *out = NULL; while (1) { char buffer[64], *pin; size_t len; snprintf(buffer, sizeof(buffer), "Please enter %s: ", label); if ((pin = getpass(buffer)) == NULL) return SC_ERROR_INTERNAL; len = strlen(pin); if (len == 0 && (flags & SC_UI_PIN_OPTIONAL)) return 0; if (pin_info && (flags & SC_UI_PIN_CHECK_LENGTH)) { if (len < pin_info->min_length) { fprintf(stderr, "PIN too short (min %lu characters)\n", (unsigned long) pin_info->min_length); continue; } if (pin_info->max_length && len > pin_info->max_length) { fprintf(stderr, "PIN too long (max %lu characters)\n", (unsigned long) pin_info->max_length); continue; } } *out = strdup(pin); sc_mem_clear(pin, len); if (!(flags & SC_UI_PIN_RETYPE)) break; pin = getpass("Please type again to verify: "); if (!strcmp(*out, pin)) { sc_mem_clear(pin, len); break; } free(*out); *out = NULL; if (!(flags & SC_UI_PIN_MISMATCH_RETRY)) { fprintf(stderr, "PINs do not match.\n"); return SC_ERROR_KEYPAD_PIN_MISMATCH; } fprintf(stderr, "Sorry, the two pins did not match. " "Please try again.\n"); sc_mem_clear(pin, strlen(pin)); /* Currently, there's no way out of this dialog. * We should allow the user to bail out after n * attempts. */ } return 0; }
/* * @brief Use PUT DATA to import a private EC key. * * Format of transmitted data: * 0xE0 - Private class, constructed encoding, number one. * 0x81 - prime * 0x82 - coefficient A * 0x83 - coefficient B * 0x84 - base point G * 0x85 - order * 0x87 - cofactor * 0x88 - private D (private key) * * @param card * @param ec The EC private key to import. * * @return SC_ERROR_INVALID_ARGUMENTS: Curve parameters or private component is missing. * other errors: Transmit errors / errors returned by card. * ASN1 errors. */ static int isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) { sc_apdu_t apdu; u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; int r; u8 *p; size_t tags_len; LOG_FUNC_CALLED(card->ctx); if(!args->privkey.ec.privateD.value || !args->privkey.ec.params.prime.value || !args->privkey.ec.params.coefficientA.value || !args->privkey.ec.params.coefficientB.value || !args->privkey.ec.params.basePointG.value || !args->privkey.ec.params.order.value || !args->privkey.ec.params.coFactor.value ) { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Missing information about EC private key."); } /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */ tags_len = 0; r = sc_asn1_put_tag(0x81, NULL, args->privkey.ec.params.prime.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x82, NULL, args->privkey.ec.params.coefficientA.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x83, NULL, args->privkey.ec.params.coefficientB.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x84, NULL, args->privkey.ec.params.basePointG.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x85, NULL, args->privkey.ec.params.order.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x87, NULL, args->privkey.ec.params.coFactor.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; r = sc_asn1_put_tag(0x88, NULL, args->privkey.ec.privateD.len, NULL, 0, NULL); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); tags_len += r; /* Write the outer tag and length information. */ p = sbuf; r = sc_asn1_put_tag(0xE0, NULL, tags_len, p, sizeof(sbuf), &p); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); /* Write inner tags. */ r = isoApplet_put_ec_params(card, &args->privkey.ec.params, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) { sc_log(card->ctx, "Error composing EC params."); goto out; } r = sc_asn1_put_tag(0x88, args->privkey.ec.privateD.value, args->privkey.ec.privateD.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) goto out; /* Send to card. */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); apdu.lc = p - sbuf; apdu.datalen = p - sbuf; apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); if(r < 0) { sc_log(card->ctx, "APDU transmit failed"); goto out; } r = sc_check_sw(card, apdu.sw1, apdu.sw2); if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) { sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported. " "If you are using an older applet version and are trying to import keys, please update your applet first."); } else if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) { sc_log(card->ctx, "Key import not supported by the card with that particular key type. " "Your card may not support the specified algorithm used by the applet / specified by you. " "In most cases, this happens when trying to import EC keys not supported by your java card. " "In this case, look for supported field lengths and whether FP and/or F2M are supported. " "If you tried to import a private RSA key, check the key length."); } else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) { sc_log(card->ctx, "Key import not allowed by the applet's security policy. " "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," " rebuild and reinstall the applet."); } if(r < 0) { sc_log(card->ctx, "Card returned error"); goto out; } r = SC_SUCCESS; out: sc_mem_clear(sbuf, sizeof(sbuf)); LOG_FUNC_RETURN(card->ctx, r); }