Example #1
0
/*
 * Get EC key material and stash pointer in ex_data
 * Note we get called twice, once for private key, and once for public
 * We need to get the EC_PARAMS and EC_POINT into both,
 * as lib11 dates from RSA only where all the pub key components
 * were also part of the private key.  With EC the point
 * is not in the private key, and the params may or may not be.
 *
 */
static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY *key)
{
	EVP_PKEY *pk;
	EC_KEY *ec;

	ec = pkcs11_get_ec(key);
	if (ec == NULL)
		return NULL;
	pk = EVP_PKEY_new();
	if (pk == NULL) {
		EC_KEY_free(ec);
		return NULL;
	}
	EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */

	if (key->isPrivate) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
		EC_KEY_set_method(ec, PKCS11_get_ec_key_method());
#else
		ECDSA_set_method(ec, PKCS11_get_ecdsa_method());
		ECDH_set_method(ec, PKCS11_get_ecdh_method());
#endif
	}
	/* TODO: Retrieve the ECDSA private key object attributes instead,
	 * unless the key has the "sensitive" attribute set */

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	EC_KEY_set_ex_data(ec, ec_ex_index, key);
#else
	ECDSA_set_ex_data(ec, ec_ex_index, key);
#endif
	EC_KEY_free(ec); /* Drops our reference to it */
	return pk;
}
// Signing functions
bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism)
{
	std::string lowerMechanism;
	lowerMechanism.resize(mechanism.size());
	std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);

	if (lowerMechanism.compare("ecdsa"))
	{
		ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
		return false;
	}

	// Check if the private key is the right type
	if (!privateKey->isOfType(OSSLECPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey;
	EC_KEY* eckey = pk->getOSSLKey();

	if (eckey == NULL)
	{
		ERROR_MSG("Could not get the OpenSSL private key");

		return false;
	}

	// Use the OpenSSL implementation and not any engine
	ECDSA_set_method(eckey, ECDSA_OpenSSL());

	// Perform the signature operation
	size_t len = pk->getOrderLength();
	if (len == 0)
	{
		ERROR_MSG("Could not get the order length");
		return false;
	}
	signature.resize(2 * len);
	memset(&signature[0], 0, 2 * len);
	ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
	if (sig == NULL)
	{
		ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error());
		return false;
	}
	// Store the 2 values with padding
	BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]);
	BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]);
	ECDSA_SIG_free(sig);
	return true;
}
static
PKCS11H_BOOL
__pkcs11h_openssl_session_setECDSA(
	IN const pkcs11h_openssl_session_t openssl_session,
	IN EVP_PKEY * evp
) {
	PKCS11H_BOOL ret = FALSE;
	EC_KEY *ec = NULL;

	_PKCS11H_DEBUG (
		PKCS11H_LOG_DEBUG2,
		"PKCS#11: __pkcs11h_openssl_session_setECDSA - entered openssl_session=%p, evp=%p",
		(void *)openssl_session,
		(void *)evp
	);

	if (
		(ec = EVP_PKEY_get1_EC_KEY (evp)) == NULL
	) {
		_PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get EC key");
		goto cleanup;
	}

	ECDSA_set_method (ec, __openssl_methods.ecdsa);
	ECDSA_set_ex_data (ec, __openssl_methods.ecdsa_index, openssl_session);

	ret = TRUE;

cleanup:

	if (ec != NULL) {
		EC_KEY_free (ec);
		ec = NULL;
	}

	_PKCS11H_DEBUG (
		PKCS11H_LOG_DEBUG2,
		"PKCS#11: __pkcs11h_openssl_session_setECDSA - return ret=%d",
		ret
	);

	return ret;
}
// Verification functions
bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism)
{
	std::string lowerMechanism;
	lowerMechanism.resize(mechanism.size());
	std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower);

	if (lowerMechanism.compare("ecdsa"))
	{
		ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str());
		return false;
	}

	// Check if the private key is the right type
	if (!publicKey->isOfType(OSSLECPublicKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey;
	EC_KEY* eckey = pk->getOSSLKey();

	if (eckey == NULL)
	{
		ERROR_MSG("Could not get the OpenSSL public key");

		return false;
	}

	// Use the OpenSSL implementation and not any engine
	ECDSA_set_method(eckey, ECDSA_OpenSSL());

	// Perform the verify operation
	size_t len = pk->getOrderLength();
	if (len == 0)
	{
		ERROR_MSG("Could not get the order length");
		return false;
	}
	if (signature.size() != 2 * len)
	{
		ERROR_MSG("Invalid buffer length");
		return false;
	}
	ECDSA_SIG* sig = ECDSA_SIG_new();
	if (sig == NULL)
	{
		ERROR_MSG("Could not create an ECDSA_SIG object");
		return false;
	}
	if (sig->r != NULL)
		BN_clear_free(sig->r);
	const unsigned char *s = signature.const_byte_str();
	sig->r = BN_bin2bn(s, len, NULL);
	if (sig->s != NULL)
		BN_clear_free(sig->s);
	sig->s = BN_bin2bn(s + len, len, NULL);
	if (sig->r == NULL || sig->s == NULL)
	{
		ERROR_MSG("Could not add data to the ECDSA_SIG object");
		ECDSA_SIG_free(sig);
		return false;
	}
	int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey);
	if (ret != 1)
	{
		if (ret < 0)
			ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error());

		ECDSA_SIG_free(sig);
		return false;
	}

	ECDSA_SIG_free(sig);
	return true;
}
Example #5
0
/*
 * Get EC key material and stash pointer in ex_data
 * Note we get called twice, once for private key, and once for public
 * We need to get the EC_PARAMS and EC_POINT into both,
 * as lib11 dates from RSA only where all the pub key components
 * were also part of the private key.  With EC the point
 * is not in the private key, and the params may or may not be.
 *
 */
static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY * key)
{
	EVP_PKEY *pk;
	EC_KEY * ec = NULL;
	CK_RV ckrv;
	size_t ec_paramslen = 0;
	CK_BYTE * ec_params = NULL;
	size_t ec_pointlen = 0;
	CK_BYTE * ec_point = NULL;
	PKCS11_KEY * pubkey;
	ASN1_OCTET_STRING *os=NULL;

	pk = EVP_PKEY_new();
	if (pk == NULL)
		return NULL;

	ec = EC_KEY_new();
	if (ec == NULL) {
		EVP_PKEY_free(pk);
		return NULL;
	}
	EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */

	/* For Openssl req we need at least the
	 * EC_KEY_get0_group(ec_key)) to return the group.
	 * Even if it fails will continue as a sign only does not need
	 * need this if the pkcs11 or card can figure this out.
	 */

	if (key_getattr_var(key, CKA_EC_PARAMS, NULL, &ec_paramslen) == CKR_OK &&
			ec_paramslen > 0) {
		ec_params = OPENSSL_malloc(ec_paramslen);
		if (ec_params) {
			ckrv = key_getattr_var(key, CKA_EC_PARAMS, ec_params, &ec_paramslen);
			if (ckrv == CKR_OK) {
				const unsigned char * a = ec_params;
				/* convert to OpenSSL parmas */
				d2i_ECParameters(&ec, &a, (long) ec_paramslen);
			}
		}
	}

	/* Now get the ec_point */
	pubkey = key->isPrivate ? PKCS11_find_key_from_key(key) : key;
	if (pubkey) {
		ckrv = key_getattr_var(pubkey, CKA_EC_POINT, NULL, &ec_pointlen);
		if (ckrv == CKR_OK && ec_pointlen > 0) {
			ec_point = OPENSSL_malloc(ec_pointlen);
			if (ec_point) {
				ckrv = key_getattr_var(pubkey, CKA_EC_POINT, ec_point, &ec_pointlen);
				if (ckrv == CKR_OK) {
					/* PKCS#11 returns ASN1 octstring*/
					const unsigned char * a;
					/* we have asn1 octet string, need to strip off 04 len */

					a = ec_point;
					os = d2i_ASN1_OCTET_STRING(NULL, &a, (long) ec_pointlen);
					if (os) {
						a = os->data;
						o2i_ECPublicKey(&ec, &a, os->length);
					}
/* EC_KEY_print_fp(stderr, ec, 5); */
				}
			}
		}
	}

	/* If the key is not extractable, create a key object
	 * that will use the card's functions to sign & decrypt
	 */
	if (os)
		ASN1_STRING_free(os);
	if (ec_point)
		OPENSSL_free(ec_point);
	if (ec_params)
		OPENSSL_free(ec_params);

	if (key->isPrivate) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
		EC_KEY_set_method(ec, PKCS11_get_ec_key_method());
#else
		ECDSA_set_method(ec, PKCS11_get_ecdsa_method());
	/* TODO: Retrieve the ECDSA private key object attributes instead,
	 * unless the key has the "sensitive" attribute set */
#endif
	}
	/* TODO: Extract the ECDSA private key instead, if the key
	 * is marked as extractable (and not private?) */

#if OPENSSL_VERSION_NUMBER >= 0x10100002L
	EC_KEY_set_ex_data(ec,ec_key_ex_index, key);
#else
	ECDSA_set_ex_data(ec, ecdsa_ex_index, key);
#endif
	EC_KEY_free(ec); /* drops our reference to it */
	return pk;
}