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