xref: /optee_os/core/tee/tee_cryp_concat_kdf.c (revision 78b7c7c7653f8bff42fe44d31a79d7f6bbfd4d47)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, Linaro Limited
4  * All rights reserved.
5  */
6 
7 #include <crypto/crypto.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <tee/tee_cryp_concat_kdf.h>
11 #include <tee/tee_cryp_utl.h>
12 #include <utee_defines.h>
13 
14 TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret,
15 			       size_t shared_secret_len,
16 			       const uint8_t *other_info,
17 			       size_t other_info_len, uint8_t *derived_key,
18 			       size_t derived_key_len)
19 {
20 	TEE_Result res;
21 	size_t ctx_size, hash_len, i, n, sz;
22 	void *ctx = NULL;
23 	uint8_t tmp[TEE_MAX_HASH_SIZE];
24 	uint32_t be_count;
25 	uint8_t *out = derived_key;
26 	uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id);
27 
28 	res = crypto_hash_get_ctx_size(hash_algo, &ctx_size);
29 	if (res != TEE_SUCCESS)
30 		goto out;
31 
32 	ctx = malloc(ctx_size);
33 	if (!ctx) {
34 		res = TEE_ERROR_OUT_OF_MEMORY;
35 		goto out;
36 	}
37 
38 	res = tee_hash_get_digest_size(hash_algo, &hash_len);
39 	if (res != TEE_SUCCESS)
40 		goto out;
41 
42 	n = derived_key_len / hash_len;
43 	sz = hash_len;
44 	for (i = 1; i <= n + 1; i++) {
45 		be_count = TEE_U32_TO_BIG_ENDIAN(i);
46 
47 		res = crypto_hash_init(ctx, hash_algo);
48 		if (res != TEE_SUCCESS)
49 			goto out;
50 		res = crypto_hash_update(ctx, hash_algo, (uint8_t *)&be_count,
51 				   sizeof(be_count));
52 		if (res != TEE_SUCCESS)
53 			goto out;
54 		res = crypto_hash_update(ctx, hash_algo, shared_secret,
55 				   shared_secret_len);
56 		if (res != TEE_SUCCESS)
57 			goto out;
58 		if (other_info && other_info_len) {
59 			res = crypto_hash_update(ctx, hash_algo, other_info,
60 					   other_info_len);
61 			if (res != TEE_SUCCESS)
62 				goto out;
63 		}
64 		res = crypto_hash_final(ctx, hash_algo, tmp, sizeof(tmp));
65 		if (res != TEE_SUCCESS)
66 			goto out;
67 
68 		if (i == n + 1)
69 			sz = derived_key_len % hash_len;
70 		memcpy(out, tmp, sz);
71 		out += sz;
72 	}
73 	res = TEE_SUCCESS;
74 out:
75 	free(ctx);
76 	return res;
77 }
78