예제 #1
0
파일: pkcs15-sec.c 프로젝트: pawmas/opensc
LIBOPENSC_API int sc_pkcs15_decipher(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_algorithm_info_t *alg_info;
	sc_security_env_t senv;
	const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
	unsigned long pad_flags = 0, sec_flags = 0;

	LOG_FUNC_CALLED(ctx);

	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 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_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)))
		LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for decryption");

	switch (obj->type) {
		case SC_PKCS15_TYPE_PRKEY_RSA:
			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.algorithm = SC_ALGORITHM_RSA;
			break;

		case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
			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.algorithm = SC_ALGORITHM_GOSTR3410;
			break;

		default:
			LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
	}

	r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
	LOG_TEST_RET(ctx, r, "cannot encode security operation flags");

	senv.algorithm_flags = sec_flags;
	senv.operation       = SC_SEC_OPERATION_DECIPHER;
	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);
	LOG_TEST_RET(ctx, r, "sc_lock() failed");

	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_decipher(p15card->card, in, inlen, out, outlen);
	if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
		if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
			r = sc_decipher(p15card->card, in, inlen, out, outlen);
	}
	sc_unlock(p15card->card);
	LOG_TEST_RET(ctx, r, "sc_decipher() failed");

	/* Strip any padding */
	if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
		size_t s = r;
		r = sc_pkcs1_strip_02_padding(out, s, out, &s);
		LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
	}

	LOG_FUNC_RETURN(ctx, r);
}
static int do_pkdecrypt(int argc, char **argv)
{
	puts ("Not yet supported");
	return -1;
#if 0
	int i, ref, r;
	u8 indata[128];
	size_t indatalen = sizeof indata;
	u8 outdata[128];
	size_t outdatalen = sizeof outdata;
	sc_security_env_t senv;
	const char *s;

	if (argc != 2)
		goto usage;
	if (sscanf(argv[0], "%d", &ref) != 1 || ref < 0 || ref > 255) {
		printf("Invalid key reference.\n");
		goto usage;
	}

	if (argv[1][0] == '"') {
		for (s=argv[1]+1, i = 0;
		     i < sizeof indata && *s && *s != '"'; i++) 
			indata[i] = *s++;
		indatalen = i;
	} else if (sc_hex_to_bin (argv[1], indata, &indatalen)) {
		printf("Invalid data value.\n");
		goto usage;
	}

	/* setup the security environment */
	memset (&senv, 0, sizeof senv);
	senv.operation = SC_SEC_OPERATION_DECIPHER;
	senv.algorithm = SC_ALGORITHM_RSA;
	senv.key_ref_len = 1;
	senv.key_ref[0] = ref;
 	senv.flags = (SC_SEC_ENV_KEY_REF_PRESENT | SC_SEC_ENV_ALG_PRESENT);
	r = sc_set_security_env(card, &senv, 0);
	if (r) {
		printf("Failed to set the security environment: %s\n",
		       sc_strerror (r));
		return -1;
	}

	/* perform the actual decryption */
	/* FIXME: It is pretty useless to to this test padding :-; */
	memmove(indata+(sizeof indata - indatalen), indata, indatalen);
	memset(indata, 0, (sizeof indata - indatalen));
	indatalen = sizeof indata;
	r = sc_decipher(card, indata, indatalen, outdata, outdatalen);
	if (r<0) {
		printf("Decryption failed: %s\n",  sc_strerror (r));
		return -1;
	}
	hex_dump_asc (stdout, outdata, r, -1);
	printf("Done.\n");
	return 0;
usage:
	printf("Usage: pkdecrypt <key ref> <data>\n");
	return -1;
#endif
}
예제 #3
0
파일: pkcs15-sec.c 프로젝트: pawmas/opensc
/* derive one key from another. RSA can use decipher, so this is for only ECDH
 * Since the value may be returned, and the call is expected to provide
 * the buffer, we used the PKCS#11 convention of outlen == 0 and out == NULL
 * to indicate that this is a request for the size.
 * In that case r = 0, and *poutlen = expected size
 */
LIBOPENSC_API int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
		       const struct sc_pkcs15_object *obj,
		       unsigned long flags,
		       const u8 * in, size_t inlen, u8 *out,
		       unsigned long *poutlen)
{
	sc_context_t *ctx = p15card->card->ctx;
	int r;
	sc_algorithm_info_t *alg_info;
	sc_security_env_t senv;
	const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
	unsigned long pad_flags = 0, sec_flags = 0;

	LOG_FUNC_CALLED(ctx);

	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 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_DERIVE)))
		LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for derivation");

	switch (obj->type) {
		case SC_PKCS15_TYPE_PRKEY_EC:
			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);
			}

			if (out == NULL || *poutlen < (prkey->field_length +7) / 8) {
			    *poutlen = (prkey->field_length +7) / 8;
			    r = 0; /* say no data to return */
			    goto out;
			}

			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;
		default:
			LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
	}

	r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
	LOG_TEST_RET(ctx, r, "cannot encode security operation flags");

	senv.algorithm_flags = sec_flags;
	senv.operation       = SC_SEC_OPERATION_DERIVE;
	/* 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");

	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");
	}
/* TODO Do we need a sc_derive? PIV at least can use the decipher,
 * senv.operation       = SC_SEC_OPERATION_DERIVE;
 */
	r = sc_decipher(p15card->card, in, inlen, out, *poutlen);
	if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
		if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
			r = sc_decipher(p15card->card, in, inlen, out, *poutlen);
	}
	sc_unlock(p15card->card);
	LOG_TEST_RET(ctx, r, "sc_decipher/derive() failed");

	/* Strip any padding */
	if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
		size_t s = r;
		r = sc_pkcs1_strip_02_padding(out, s, out, &s);
		LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
	}

	/* If card stores derived key on card, then no data is returned
         * and the key must be used on the card. */
	*poutlen = r;
out:
	LOG_FUNC_RETURN(ctx, r);
}
int sc_pkcs15_decipher(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_algorithm_info_t *alg_info;
    sc_security_env_t senv;
    sc_context_t *ctx = p15card->card->ctx;
    const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
    unsigned long pad_flags = 0, sec_flags = 0;

    SC_FUNC_CALLED(ctx, 1);
    /* 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_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP))) {
        sc_error(ctx, "This key cannot be used for decryption\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;

    r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
    if (r != SC_SUCCESS)
        return r;

    senv.algorithm_flags = sec_flags;
    senv.operation       = SC_SEC_OPERATION_DECIPHER;
    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_decipher(p15card->card, in, inlen, out, outlen);
    sc_unlock(p15card->card);
    SC_TEST_RET(ctx, r, "sc_decipher() failed");

    /* Strip any padding */
    if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
        r = sc_pkcs1_strip_02_padding(out, (size_t)r, out, (size_t *) &r);
        SC_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
    }

    return r;
}