Beispiel #1
0
static TEE_Result check_shdr(struct shdr *shdr)
{
	struct rsa_public_key key;
	TEE_Result res;
	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
	size_t hash_size;

	if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA)
		return TEE_ERROR_SECURITY;

	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
		return TEE_ERROR_SECURITY;

	res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
				       &hash_size);
	if (res != TEE_SUCCESS)
		return res;
	if (hash_size != shdr->hash_size)
		return TEE_ERROR_SECURITY;

	if (!crypto_ops.acipher.alloc_rsa_public_key ||
	    !crypto_ops.acipher.free_rsa_public_key ||
	    !crypto_ops.acipher.rsassa_verify ||
	    !crypto_ops.bignum.bin2bn)
		return TEE_ERROR_NOT_SUPPORTED;

	res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size);
	if (res != TEE_SUCCESS)
		return res;

	res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e);
	if (res != TEE_SUCCESS)
		goto out;
	res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus,
				       ta_pub_key_modulus_size, key.n);
	if (res != TEE_SUCCESS)
		goto out;

	res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1,
				SHDR_GET_HASH(shdr), shdr->hash_size,
				SHDR_GET_SIG(shdr), shdr->sig_size);
out:
	crypto_ops.acipher.free_rsa_public_key(&key);
	if (res != TEE_SUCCESS)
		return TEE_ERROR_SECURITY;
	return TEE_SUCCESS;
}
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;
}
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;
}