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