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_pbkdf2.h> 10 #include <tee/tee_cryp_utl.h> 11 #include <utee_defines.h> 12 13 struct hmac_parms { 14 uint32_t algo; 15 size_t hash_len; 16 void *ctx; 17 }; 18 19 struct pbkdf2_parms { 20 const uint8_t *password; 21 size_t password_len; 22 const uint8_t *salt; 23 size_t salt_len; 24 uint32_t iteration_count; 25 }; 26 27 static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx, 28 struct hmac_parms *h, struct pbkdf2_parms *p) 29 { 30 TEE_Result res; 31 uint8_t u[TEE_MAX_HASH_SIZE]; 32 uint32_t be_index; 33 size_t i, j; 34 35 memset(out, 0, len); 36 for (i = 1; i <= p->iteration_count; i++) { 37 res = crypto_mac_init(h->ctx, p->password, p->password_len); 38 if (res != TEE_SUCCESS) 39 return res; 40 41 if (i == 1) { 42 if (p->salt && p->salt_len) { 43 res = crypto_mac_update(h->ctx, p->salt, 44 p->salt_len); 45 if (res != TEE_SUCCESS) 46 return res; 47 } 48 49 be_index = TEE_U32_TO_BIG_ENDIAN(idx); 50 51 res = crypto_mac_update(h->ctx, (uint8_t *)&be_index, 52 sizeof(be_index)); 53 if (res != TEE_SUCCESS) 54 return res; 55 } else { 56 res = crypto_mac_update(h->ctx, u, h->hash_len); 57 if (res != TEE_SUCCESS) 58 return res; 59 } 60 61 res = crypto_mac_final(h->ctx, u, sizeof(u)); 62 if (res != TEE_SUCCESS) 63 return res; 64 65 for (j = 0; j < len; j++) 66 out[j] ^= u[j]; 67 } 68 return TEE_SUCCESS; 69 } 70 71 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, 72 size_t password_len, const uint8_t *salt, 73 size_t salt_len, uint32_t iteration_count, 74 uint8_t *derived_key, size_t derived_key_len) 75 { 76 TEE_Result res; 77 size_t i, l, r; 78 uint8_t *out = derived_key; 79 struct pbkdf2_parms pbkdf2_parms; 80 struct hmac_parms hmac_parms = {0, }; 81 82 hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id); 83 84 res = tee_alg_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len); 85 if (res != TEE_SUCCESS) 86 return res; 87 88 res = crypto_mac_alloc_ctx(&hmac_parms.ctx, hmac_parms.algo); 89 if (res != TEE_SUCCESS) 90 return res; 91 92 pbkdf2_parms.password = password; 93 pbkdf2_parms.password_len = password_len; 94 pbkdf2_parms.salt = salt; 95 pbkdf2_parms.salt_len = salt_len; 96 pbkdf2_parms.iteration_count = iteration_count; 97 98 l = derived_key_len / hmac_parms.hash_len; 99 r = derived_key_len % hmac_parms.hash_len; 100 101 for (i = 1; i <= l; i++) { 102 res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms, 103 &pbkdf2_parms); 104 if (res != TEE_SUCCESS) 105 goto out; 106 out += hmac_parms.hash_len; 107 } 108 if (r) 109 res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms); 110 111 out: 112 crypto_mac_free_ctx(hmac_parms.ctx); 113 return res; 114 } 115