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;
}
Пример #2
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
/*
 * 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;
}
Пример #7
0
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);
}
Пример #8
0
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;
}
Пример #9
0
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));
}
Пример #10
0
Файл: card.c Проект: DDvO/OpenSC
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;
}
Пример #12
0
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));
}
Пример #14
0
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;
}
Пример #15
0
/*
 * 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);
}
Пример #16
0
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;
}
Пример #17
0
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);
}
Пример #18
0
/*
 * @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);
}
Пример #19
0
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;
}
Пример #20
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);
}