Ejemplo n.º 1
0
void TEE_DeriveKey(TEE_OperationHandle operation,
		   const TEE_Attribute *params, uint32_t paramCount,
		   TEE_ObjectHandle derivedKey)
{
	TEE_Result res;
	TEE_ObjectInfo key_info;
	struct utee_attribute ua[paramCount];

	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
		TEE_Panic(0);
	if (params == NULL && paramCount != 0)
		TEE_Panic(0);
	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
	    TEE_OPERATION_KEY_DERIVATION)
		TEE_Panic(0);

	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
		TEE_Panic(0);
	if (!operation->key1)
		TEE_Panic(0);
	if (operation->info.mode != TEE_MODE_DERIVE)
		TEE_Panic(0);
	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
		TEE_Panic(0);

	res = utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
	if (res != TEE_SUCCESS)
		TEE_Panic(0);

	if (key_info.objectType != TEE_TYPE_GENERIC_SECRET)
		TEE_Panic(0);
	if ((key_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
		TEE_Panic(0);

	__utee_from_attr(ua, params, paramCount);
	res = utee_cryp_derive_key(operation->state, ua, paramCount,
				   (unsigned long)derivedKey);
	if (res != TEE_SUCCESS)
		TEE_Panic(res);
}
Ejemplo n.º 2
0
TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
				 uint32_t algorithm, uint32_t mode,
				 uint32_t maxKeySize)
{
	TEE_Result res;
	TEE_OperationHandle op = TEE_HANDLE_NULL;
	uint32_t handle_state = 0;
	size_t block_size = 1;
	uint32_t req_key_usage;
	bool with_private_key = false;
	bool buffer_two_blocks = false;

	if (!operation)
		TEE_Panic(0);

	if (algorithm == TEE_ALG_AES_XTS)
		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;

	/* Check algorithm max key size */
	switch (algorithm) {
	case TEE_ALG_DSA_SHA1:
		if (maxKeySize < 512)
			return TEE_ERROR_NOT_SUPPORTED;
		if (maxKeySize > 1024)
			return TEE_ERROR_NOT_SUPPORTED;
		if (maxKeySize % 64 != 0)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_DSA_SHA224:
		if (maxKeySize != 2048)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_DSA_SHA256:
		if (maxKeySize != 2048 && maxKeySize != 3072)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P192:
	case TEE_ALG_ECDH_P192:
		if (maxKeySize != 192)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P224:
	case TEE_ALG_ECDH_P224:
		if (maxKeySize != 224)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P256:
	case TEE_ALG_ECDH_P256:
		if (maxKeySize != 256)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P384:
	case TEE_ALG_ECDH_P384:
		if (maxKeySize != 384)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_ECDSA_P521:
	case TEE_ALG_ECDH_P521:
		if (maxKeySize != 521)
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	default:
		break;
	}

	/* Check algorithm mode */
	switch (algorithm) {
	case TEE_ALG_AES_CTS:
	case TEE_ALG_AES_XTS:
		buffer_two_blocks = true;
	 /*FALLTHROUGH*/ case TEE_ALG_AES_ECB_NOPAD:
	case TEE_ALG_AES_CBC_NOPAD:
	case TEE_ALG_AES_CTR:
	case TEE_ALG_AES_CCM:
	case TEE_ALG_AES_GCM:
	case TEE_ALG_DES_ECB_NOPAD:
	case TEE_ALG_DES_CBC_NOPAD:
	case TEE_ALG_DES3_ECB_NOPAD:
	case TEE_ALG_DES3_CBC_NOPAD:
		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
			block_size = TEE_AES_BLOCK_SIZE;
		else
			block_size = TEE_DES_BLOCK_SIZE;

		if (mode == TEE_MODE_ENCRYPT)
			req_key_usage = TEE_USAGE_ENCRYPT;
		else if (mode == TEE_MODE_DECRYPT)
			req_key_usage = TEE_USAGE_DECRYPT;
		else
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
	case TEE_ALG_DSA_SHA1:
	case TEE_ALG_DSA_SHA224:
	case TEE_ALG_DSA_SHA256:
	case TEE_ALG_ECDSA_P192:
	case TEE_ALG_ECDSA_P224:
	case TEE_ALG_ECDSA_P256:
	case TEE_ALG_ECDSA_P384:
	case TEE_ALG_ECDSA_P521:
		if (mode == TEE_MODE_SIGN) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_SIGN;
		} else if (mode == TEE_MODE_VERIFY) {
			req_key_usage = TEE_USAGE_VERIFY;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSAES_PKCS1_V1_5:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSA_NOPAD:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
	case TEE_ALG_ECDH_P192:
	case TEE_ALG_ECDH_P224:
	case TEE_ALG_ECDH_P256:
	case TEE_ALG_ECDH_P384:
	case TEE_ALG_ECDH_P521:
	case TEE_ALG_HKDF_MD5_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA1_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA224_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA256_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA384_DERIVE_KEY:
	case TEE_ALG_HKDF_SHA512_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY:
	case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY:
	case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY:
		if (mode != TEE_MODE_DERIVE)
			return TEE_ERROR_NOT_SUPPORTED;
		with_private_key = true;
		req_key_usage = TEE_USAGE_DERIVE;
		break;

	case TEE_ALG_MD5:
	case TEE_ALG_SHA1:
	case TEE_ALG_SHA224:
	case TEE_ALG_SHA256:
	case TEE_ALG_SHA384:
	case TEE_ALG_SHA512:
		if (mode != TEE_MODE_DIGEST)
			return TEE_ERROR_NOT_SUPPORTED;
		/* v1.1: flags always set for digest operations */
		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
		req_key_usage = 0;
		break;

	case TEE_ALG_DES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_PKCS5:
	case TEE_ALG_AES_CMAC:
	case TEE_ALG_DES_CBC_MAC_PKCS5:
	case TEE_ALG_DES3_CBC_MAC_NOPAD:
	case TEE_ALG_DES3_CBC_MAC_PKCS5:
	case TEE_ALG_HMAC_MD5:
	case TEE_ALG_HMAC_SHA1:
	case TEE_ALG_HMAC_SHA224:
	case TEE_ALG_HMAC_SHA256:
	case TEE_ALG_HMAC_SHA384:
	case TEE_ALG_HMAC_SHA512:
		if (mode != TEE_MODE_MAC)
			return TEE_ERROR_NOT_SUPPORTED;
		req_key_usage = TEE_USAGE_MAC;
		break;

	default:
		return TEE_ERROR_NOT_SUPPORTED;
	}

	op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO);
	if (!op)
		return TEE_ERROR_OUT_OF_MEMORY;

	op->info.algorithm = algorithm;
	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
	op->info.mode = mode;
	op->info.maxKeySize = maxKeySize;
	op->info.requiredKeyUsage = req_key_usage;
	op->info.handleState = handle_state;

	if (block_size > 1) {
		size_t buffer_size = block_size;

		if (buffer_two_blocks)
			buffer_size *= 2;

		op->buffer = TEE_Malloc(buffer_size,
					TEE_USER_MEM_HINT_NO_FILL_ZERO);
		if (op->buffer == NULL) {
			res = TEE_ERROR_OUT_OF_MEMORY;
			goto out;
		}
	}
	op->block_size = block_size;
	op->buffer_two_blocks = buffer_two_blocks;

	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
		uint32_t mks = maxKeySize;
		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
						       with_private_key);

		/*
		 * If two keys are expected the max key size is the sum of
		 * the size of both keys.
		 */
		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
			mks /= 2;

		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
		if (res != TEE_SUCCESS)
			goto out;

		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
			res = TEE_AllocateTransientObject(key_type, mks,
							  &op->key2);
			if (res != TEE_SUCCESS)
				goto out;
		}
	}

	res = utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1,
				    (unsigned long)op->key2, &op->state);
	if (res != TEE_SUCCESS)
		goto out;

	/*
	 * Initialize digest operations
	 * Other multi-stage operations initialized w/ TEE_xxxInit functions
	 * Non-applicable on asymmetric operations
	 */
	if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) {
		res = utee_hash_init(op->state, NULL, 0);
		if (res != TEE_SUCCESS)
			goto out;
		/* v1.1: flags always set for digest operations */
		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
	}

	op->operationState = TEE_OPERATION_STATE_INITIAL;

	*operation = op;

out:
	if (res != TEE_SUCCESS) {
		if (res != TEE_ERROR_OUT_OF_MEMORY &&
		    res != TEE_ERROR_NOT_SUPPORTED)
			TEE_Panic(0);
		if (op) {
			if (op->state) {
				TEE_FreeOperation(op);
			} else {
				TEE_Free(op->buffer);
				TEE_FreeTransientObject(op->key1);
				TEE_FreeTransientObject(op->key2);
				TEE_Free(op);
			}
		}
	}

	return res;
}
Ejemplo n.º 3
0
TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
				 uint32_t algorithm, uint32_t mode,
				 uint32_t maxKeySize)
{
	TEE_Result res;
	TEE_OperationHandle op = TEE_HANDLE_NULL;
	uint32_t handle_state = 0;
	size_t block_size = 1;
	uint32_t req_key_usage;
	bool with_private_key = false;
	bool buffer_two_blocks = false;

	if (operation == NULL)
		TEE_Panic(0);

	if (algorithm == TEE_ALG_AES_XTS)
		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;

	switch (algorithm) {
	case TEE_ALG_AES_CTS:
	case TEE_ALG_AES_XTS:
		buffer_two_blocks = true;
	 /*FALLTHROUGH*/ case TEE_ALG_AES_ECB_NOPAD:
	case TEE_ALG_AES_CBC_NOPAD:
	case TEE_ALG_AES_CTR:
	case TEE_ALG_AES_CCM:
	case TEE_ALG_AES_GCM:
	case TEE_ALG_DES_ECB_NOPAD:
	case TEE_ALG_DES_CBC_NOPAD:
	case TEE_ALG_DES3_ECB_NOPAD:
	case TEE_ALG_DES3_CBC_NOPAD:
		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
			block_size = TEE_AES_BLOCK_SIZE;
		else
			block_size = TEE_DES_BLOCK_SIZE;

		if (mode == TEE_MODE_ENCRYPT)
			req_key_usage = TEE_USAGE_ENCRYPT;
		else if (mode == TEE_MODE_DECRYPT)
			req_key_usage = TEE_USAGE_DECRYPT;
		else
			return TEE_ERROR_NOT_SUPPORTED;
		break;

	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
	case TEE_ALG_DSA_SHA1:
		if (mode == TEE_MODE_SIGN) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_SIGN;
		} else if (mode == TEE_MODE_VERIFY) {
			req_key_usage = TEE_USAGE_VERIFY;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSAES_PKCS1_V1_5:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_RSA_NOPAD:
		if (mode == TEE_MODE_ENCRYPT) {
			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
		} else if (mode == TEE_MODE_DECRYPT) {
			with_private_key = true;
			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
		} else {
			return TEE_ERROR_NOT_SUPPORTED;
		}
		break;

	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
		if (mode != TEE_MODE_DERIVE)
			return TEE_ERROR_NOT_SUPPORTED;
		with_private_key = true;
		req_key_usage = TEE_USAGE_DERIVE;
		break;

	case TEE_ALG_MD5:
	case TEE_ALG_SHA1:
	case TEE_ALG_SHA224:
	case TEE_ALG_SHA256:
	case TEE_ALG_SHA384:
	case TEE_ALG_SHA512:
		if (mode != TEE_MODE_DIGEST)
			return TEE_ERROR_NOT_SUPPORTED;
		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
		req_key_usage = 0;
		break;

	case TEE_ALG_DES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_NOPAD:
	case TEE_ALG_AES_CBC_MAC_PKCS5:
	case TEE_ALG_AES_CMAC:
	case TEE_ALG_DES_CBC_MAC_PKCS5:
	case TEE_ALG_DES3_CBC_MAC_NOPAD:
	case TEE_ALG_DES3_CBC_MAC_PKCS5:
	case TEE_ALG_HMAC_MD5:
	case TEE_ALG_HMAC_SHA1:
	case TEE_ALG_HMAC_SHA224:
	case TEE_ALG_HMAC_SHA256:
	case TEE_ALG_HMAC_SHA384:
	case TEE_ALG_HMAC_SHA512:
		if (mode != TEE_MODE_MAC)
			return TEE_ERROR_NOT_SUPPORTED;
		req_key_usage = TEE_USAGE_MAC;
		break;

	default:
		return TEE_ERROR_NOT_SUPPORTED;
	}

	op = TEE_Malloc(sizeof(*op), 0);
	if (op == NULL)
		return TEE_ERROR_OUT_OF_MEMORY;

	op->info.algorithm = algorithm;
	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
	op->info.mode = mode;
	op->info.maxKeySize = maxKeySize;
	op->info.requiredKeyUsage = req_key_usage;
	op->info.handleState = handle_state;

	if (block_size > 1) {
		size_t buffer_size = block_size;

		if (buffer_two_blocks)
			buffer_size *= 2;

		op->buffer =
		    TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
		if (op->buffer == NULL) {
			res = TEE_ERROR_OUT_OF_MEMORY;
			goto out;
		}
	}
	op->block_size = block_size;
	op->buffer_two_blocks = buffer_two_blocks;

	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
		uint32_t mks = maxKeySize;
		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
						       with_private_key);

		/*
		 * If two keys are expected the max key size is the sum of
		 * the size of both keys.
		 */
		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
			mks /= 2;

		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
		if (res != TEE_SUCCESS)
			goto out;

		if ((op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
		    0) {
			res =
			    TEE_AllocateTransientObject(key_type, mks,
							&op->key2);
			if (res != TEE_SUCCESS)
				goto out;
		}
	}

	res = utee_cryp_state_alloc(algorithm, mode, (uint32_t) op->key1,
				    (uint32_t) op->key2, &op->state);
	if (res != TEE_SUCCESS)
		goto out;

	/* For multi-stage operation do an "init". */
	TEE_ResetOperation(op);
	*operation = op;

out:
	if (res != TEE_SUCCESS) {
		TEE_FreeTransientObject(op->key1);
		TEE_FreeTransientObject(op->key2);
		TEE_FreeOperation(op);
	}

	return res;
}