Beispiel #1
0
void DeriveTests::dhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey)
{
	CK_ATTRIBUTE valAttrib = { CKA_VALUE, NULL_PTR, 0 };
	CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
	CPPUNIT_ASSERT(rv == CKR_OK);
	valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
	rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
	CPPUNIT_ASSERT(rv == CKR_OK);
	CK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, NULL_PTR, 0 };
	mechanism.pParameter = valAttrib.pValue;
	mechanism.ulParameterLen = valAttrib.ulValueLen;
	CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
	CK_BBOOL bFalse = CK_FALSE;
	CK_BBOOL bTrue = CK_TRUE;
	CK_ULONG secLen = 32;
	CK_ATTRIBUTE keyAttribs[] = {
		{ CKA_CLASS, &keyClass, sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
		{ CKA_PRIVATE, &bFalse, sizeof(bFalse) },
		{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
		{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
		{ CKA_VALUE_LEN, &secLen, sizeof(secLen) }
	};

	hKey = CK_INVALID_HANDLE;
	rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
			 keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
			 &hKey) );
	free(valAttrib.pValue);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
Beispiel #2
0
void DeriveTests::symDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE &hDerive, CK_MECHANISM_TYPE mechType, CK_KEY_TYPE keyType)
{
	CK_RV rv;
	CK_MECHANISM mechanism = { mechType, NULL_PTR, 0 };
	CK_MECHANISM mechEncrypt = { CKM_VENDOR_DEFINED, NULL_PTR, 0 };
	CK_KEY_DERIVATION_STRING_DATA param1;
	CK_DES_CBC_ENCRYPT_DATA_PARAMS param2;
	CK_AES_CBC_ENCRYPT_DATA_PARAMS param3;

	CK_BYTE data[] = {
		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
		0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
		0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24,
		0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32
	};
	CK_ULONG secLen = 0;

	switch (mechType)
	{
		case CKM_DES_ECB_ENCRYPT_DATA:
		case CKM_DES3_ECB_ENCRYPT_DATA:
		case CKM_AES_ECB_ENCRYPT_DATA:
			param1.pData = &data[0];
			param1.ulLen = sizeof(data);
			mechanism.pParameter = &param1;
			mechanism.ulParameterLen = sizeof(param1);
			break;
		case CKM_DES_CBC_ENCRYPT_DATA:
		case CKM_DES3_CBC_ENCRYPT_DATA:
			memcpy(param2.iv, "12345678", 8);
			param2.pData = &data[0];
			param2.length = sizeof(data);
			mechanism.pParameter = &param2;
			mechanism.ulParameterLen = sizeof(param2);
			break;
		case CKM_AES_CBC_ENCRYPT_DATA:
			memcpy(param3.iv, "1234567890ABCDEF", 16);
			param3.pData = &data[0];
			param3.length = sizeof(data);
			mechanism.pParameter = &param3;
			mechanism.ulParameterLen = sizeof(param3);
			break;
		default:
			CPPUNIT_FAIL("Invalid mechanism");
	}

	switch (keyType)
	{
		case CKK_GENERIC_SECRET:
			secLen = 32;
			break;
		case CKK_DES:
			mechEncrypt.mechanism = CKM_DES_ECB;
			break;
		case CKK_DES2:
		case CKK_DES3:
			mechEncrypt.mechanism = CKM_DES3_ECB;
			break;
		case CKK_AES:
			mechEncrypt.mechanism = CKM_AES_ECB;
			secLen = 32;
			break;
		default:
			CPPUNIT_FAIL("Invalid key type");
	}

	CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
	CK_BBOOL bFalse = CK_FALSE;
	CK_BBOOL bTrue = CK_TRUE;
	CK_ATTRIBUTE keyAttribs[] = {
		{ CKA_CLASS, &keyClass, sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
		{ CKA_PRIVATE, &bFalse, sizeof(bFalse) },
		{ CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
		{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
		{ CKA_VALUE_LEN, &secLen, sizeof(secLen) }
	};

	hDerive = CK_INVALID_HANDLE;
	if (secLen > 0)
	{
		rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
				 keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
				 &hDerive) );
	}
	else
	{
		rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
				 keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE) - 1,
				 &hDerive) );
	}
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Check that KCV has been set
	CK_ATTRIBUTE checkAttribs[] = {
		{ CKA_CHECK_VALUE, NULL_PTR, 0 }
	};
	CK_BYTE check[3];
	checkAttribs[0].pValue = check;
	checkAttribs[0].ulValueLen = sizeof(check);
	rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hDerive, checkAttribs, 1) );
	CPPUNIT_ASSERT(rv == CKR_OK);
	CPPUNIT_ASSERT(checkAttribs[0].ulValueLen == 3);

	if (keyType == CKK_GENERIC_SECRET) return;

	CK_BYTE cipherText[300];
	CK_ULONG ulCipherTextLen;
	CK_BYTE recoveredText[300];
	CK_ULONG ulRecoveredTextLen;

	rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechEncrypt,hDerive) );
	CPPUNIT_ASSERT(rv==CKR_OK);

	ulCipherTextLen = sizeof(cipherText);
	rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,data,sizeof(data),cipherText,&ulCipherTextLen) );
	CPPUNIT_ASSERT(rv==CKR_OK);

	rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechEncrypt,hDerive) );
	CPPUNIT_ASSERT(rv==CKR_OK);

	ulRecoveredTextLen = sizeof(recoveredText);
	rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
	CPPUNIT_ASSERT(rv==CKR_OK);
	CPPUNIT_ASSERT(ulRecoveredTextLen==sizeof(data));

	CPPUNIT_ASSERT(memcmp(data, recoveredText, sizeof(data)) == 0);
}
Beispiel #3
0
void DeriveTests::ecdhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey, bool useRaw)
{
	CK_ATTRIBUTE valAttrib = { CKA_EC_POINT, NULL_PTR, 0 };
	CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
	CPPUNIT_ASSERT(rv == CKR_OK);
	valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
	rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	CK_ECDH1_DERIVE_PARAMS parms = { CKD_NULL, 0, NULL_PTR, 0, NULL_PTR };
	// Use RAW or DER format
	if (useRaw)
	{
		size_t offset = 0;
		unsigned char* buf = (unsigned char*)valAttrib.pValue;
		if (valAttrib.ulValueLen > 2 && buf[0] == 0x04)
		{
			if (buf[1] < 0x80)
			{
				offset = 2;
			}
			else
			{
				if (valAttrib.ulValueLen > ((buf[1] & 0x7F) + (unsigned int)2))
				{
					offset = 2 + (buf[1] & 0x7F);
				}
			}
		}
		parms.pPublicData = buf + offset;
		parms.ulPublicDataLen = valAttrib.ulValueLen - offset;
	}
	else
	{
		parms.pPublicData = (unsigned char*)valAttrib.pValue;
		parms.ulPublicDataLen = valAttrib.ulValueLen;
	}

	CK_MECHANISM mechanism = { CKM_ECDH1_DERIVE, NULL, 0 };
	mechanism.pParameter = &parms;
	mechanism.ulParameterLen = sizeof(parms);
	CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
	CK_BBOOL bFalse = CK_FALSE;
	CK_BBOOL bTrue = CK_TRUE;
	CK_ULONG secLen = 32;
	CK_ATTRIBUTE keyAttribs[] = {
		{ CKA_CLASS, &keyClass, sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
		{ CKA_PRIVATE, &bFalse, sizeof(bFalse) },
		{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
		{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
		{ CKA_VALUE_LEN, &secLen, sizeof(secLen) }
	};

	hKey = CK_INVALID_HANDLE;
	rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
			 keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
			 &hKey) );
	free(valAttrib.pValue);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
Beispiel #4
0
/* initial code will only support what is needed for pkcs11_ec_ckey
 * i.e. CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE
 * and CK_EC_KDF_TYPE  supported by token
 * The secret key object is deleted
 *
 * In future CKM_ECMQV_DERIVE with CK_ECMQV_DERIVE_PARAMS
 * could also be supported, and the secret key object could be returned.
 */
static int pkcs11_ecdh_derive(unsigned char **out, size_t *outlen,
		const unsigned long ecdh_mechanism,
		const void * ec_params,
		void *outnewkey,
		PKCS11_KEY * key)
{
	PKCS11_SLOT *slot = KEY2SLOT(key);
	PKCS11_CTX *ctx = KEY2CTX(key);
	PKCS11_TOKEN *token = KEY2TOKEN(key);
	PKCS11_KEY_private *kpriv = PRIVKEY(key);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	CK_MECHANISM mechanism;
	int rv;

	CK_BBOOL true = TRUE;
	CK_BBOOL false = FALSE;
	CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE;
	CK_OBJECT_CLASS newkey_class= CKO_SECRET_KEY;
	CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
	CK_OBJECT_HANDLE * tmpnewkey = (CK_OBJECT_HANDLE *)outnewkey;
	CK_ATTRIBUTE newkey_template[] = {
		{CKA_TOKEN, &false, sizeof(false)}, /* session only object */
		{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
		{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
		{CKA_ENCRYPT, &true, sizeof(true)},
		{CKA_DECRYPT, &true, sizeof(true)}
	};

	memset(&mechanism, 0, sizeof(mechanism));
	mechanism.mechanism  = ecdh_mechanism;
	mechanism.pParameter =  (void*)ec_params;
	switch (ecdh_mechanism) {
		case CKM_ECDH1_DERIVE:
		case CKM_ECDH1_COFACTOR_DERIVE:
			mechanism.ulParameterLen  = sizeof(CK_ECDH1_DERIVE_PARAMS);
			break;
#if 0
		/* TODO */
		case CK_ECMQV_DERIVE_PARAMS:
			mechanism.ulParameterLen  = sizeof(CK_ECMQV_DERIVE_PARAMS);
			break;
#endif
		default:
			PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(PKCS11_NOT_SUPPORTED));
			return -1;
	}

	rv = CRYPTOKI_call(ctx, C_DeriveKey(spriv->session, &mechanism, kpriv->object, newkey_template, 5, &newkey));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, rv);

	/* Return the value of the secret key and/or the object handle of the secret key */
	if (out && outlen) { /* pkcs11_ec_ckey only asks for the value */
		if (pkcs11_getattr_alloc(token, newkey, CKA_VALUE, out, outlen)) {
			PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY,
				pkcs11_map_err(CKR_ATTRIBUTE_VALUE_INVALID));
			CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey));
			return -1;
		}
	}
	if (tmpnewkey) /* For future use (not used by pkcs11_ec_ckey) */
		*tmpnewkey = newkey;
	else /* Destroy the temporary key */
		CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey));

	return 0;
}
Beispiel #5
0
/* initial code will only support what is needed for pkcs11_ec_ckey
 * i.e. CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE
 * and CK_EC_KDF_TYPE  supported by token
 * The secret key object is deleted
 *
 * In future CKM_ECMQV_DERIVE with CK_ECMQV_DERIVE_PARAMS
 * could also be supported, and the secret key object could be returned. 
 */
int pkcs11_ecdh_derive_internal(unsigned char **out, size_t *outlen,
		const unsigned long ecdh_mechanism,
		const void * ec_params,
		void *outnewkey,
		PKCS11_KEY * key)
{
	int rv;
	int ret = -1;
	unsigned char * buf = NULL;
	size_t buflen;
	PKCS11_KEY_private *priv;
	PKCS11_SLOT *slot;
	PKCS11_CTX *ctx;
	PKCS11_TOKEN *token;
	CK_SESSION_HANDLE session;
	CK_MECHANISM mechanism;

	CK_BBOOL true = TRUE;
	CK_BBOOL false = FALSE;
	CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE;
	CK_OBJECT_CLASS newkey_class= CKO_SECRET_KEY;
	CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
	CK_OBJECT_HANDLE * tmpnewkey = (CK_OBJECT_HANDLE *)outnewkey;
	CK_ATTRIBUTE newkey_template[] = {
		{CKA_TOKEN, &false, sizeof(false)}, /* session only object */
		{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
		{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
		{CKA_ENCRYPT, &true, sizeof(true)},
		{CKA_DECRYPT, &true, sizeof(true)}
	};

	ctx = KEY2CTX(key);
	priv = PRIVKEY(key);
	token = KEY2TOKEN(key);
	slot = KEY2SLOT(key);

	CHECK_KEY_FORK(key);

	session = PRIVSLOT(slot)->session;

	memset(&mechanism, 0, sizeof(mechanism));
	mechanism.mechanism  = ecdh_mechanism;
	mechanism.pParameter =  (void*)ec_params;
	switch (ecdh_mechanism) {
		case CKM_ECDH1_DERIVE:
		case CKM_ECDH1_COFACTOR_DERIVE:
			mechanism.ulParameterLen  = sizeof(CK_ECDH1_DERIVE_PARAMS);
			break;
//		case CK_ECMQV_DERIVE_PARAMS:
//			mechanism.ulParameterLen  = sizeof(CK_ECMQV_DERIVE_PARAMS);
//			break;
		default:
		    PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, PKCS11_NOT_SUPPORTED);
		    goto err;
	}

	CRYPTO_w_lock(PRIVSLOT(slot)->lockid);
	rv = CRYPTOKI_call(ctx, C_DeriveKey(session, &mechanism, priv->object, newkey_template, 5, &newkey));
	if (rv) {
	    PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(rv));
	    goto err;
	}

	/* Return the value of the secret key and/or the object handle of the secret key */
	
	/* pkcs11_ec_ckey only asks for the value */

	if (out && outlen) {
		/* get size of secret key value */
		if (!pkcs11_getattr_var(token, newkey, CKA_VALUE, NULL, &buflen)
			&& buflen > 0) {
			buf = OPENSSL_malloc(buflen);
			if (buf == NULL) {
				PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY,
					pkcs11_map_err(CKR_HOST_MEMORY));
				goto err;
			}
		} else {
			PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY,
				pkcs11_map_err(CKR_ATTRIBUTE_VALUE_INVALID));
			goto err;
		}

		pkcs11_getattr_var(token, newkey, CKA_VALUE, buf, &buflen);
		*out = buf;
		*outlen = buflen;
		buf = NULL;
	}

	/* not used by pkcs11_ec_ckey for future use */
	if (tmpnewkey) {
	    *tmpnewkey = newkey;
	    newkey = CK_INVALID_HANDLE;
	}

	ret = 1;
err:
	if (buf)
	    OPENSSL_free(buf);
	if (newkey != CK_INVALID_HANDLE && session != CK_INVALID_HANDLE)
		CRYPTOKI_call(ctx, C_DestroyObject(session, newkey));
	
	return ret;
}