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, h->algo, p->password, 38 p->password_len); 39 if (res != TEE_SUCCESS) 40 return res; 41 42 if (i == 1) { 43 if (p->salt && p->salt_len) { 44 res = crypto_mac_update(h->ctx, h->algo, 45 p->salt, p->salt_len); 46 if (res != TEE_SUCCESS) 47 return res; 48 } 49 50 be_index = TEE_U32_TO_BIG_ENDIAN(idx); 51 52 res = crypto_mac_update(h->ctx, h->algo, 53 (uint8_t *)&be_index, 54 sizeof(be_index)); 55 if (res != TEE_SUCCESS) 56 return res; 57 } else { 58 res = crypto_mac_update(h->ctx, h->algo, u, 59 h->hash_len); 60 if (res != TEE_SUCCESS) 61 return res; 62 } 63 64 res = crypto_mac_final(h->ctx, h->algo, u, sizeof(u)); 65 if (res != TEE_SUCCESS) 66 return res; 67 68 for (j = 0; j < len; j++) 69 out[j] ^= u[j]; 70 } 71 return TEE_SUCCESS; 72 } 73 74 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, 75 size_t password_len, const uint8_t *salt, 76 size_t salt_len, uint32_t iteration_count, 77 uint8_t *derived_key, size_t derived_key_len) 78 { 79 TEE_Result res; 80 size_t i, l, r; 81 uint8_t *out = derived_key; 82 struct pbkdf2_parms pbkdf2_parms; 83 struct hmac_parms hmac_parms = {0, }; 84 85 hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id); 86 87 res = tee_mac_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len); 88 if (res != TEE_SUCCESS) 89 return res; 90 91 res = crypto_mac_alloc_ctx(&hmac_parms.ctx, hmac_parms.algo); 92 if (res != TEE_SUCCESS) 93 return res; 94 95 pbkdf2_parms.password = password; 96 pbkdf2_parms.password_len = password_len; 97 pbkdf2_parms.salt = salt; 98 pbkdf2_parms.salt_len = salt_len; 99 pbkdf2_parms.iteration_count = iteration_count; 100 101 l = derived_key_len / hmac_parms.hash_len; 102 r = derived_key_len % hmac_parms.hash_len; 103 104 for (i = 1; i <= l; i++) { 105 res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms, 106 &pbkdf2_parms); 107 if (res != TEE_SUCCESS) 108 goto out; 109 out += hmac_parms.hash_len; 110 } 111 if (r) 112 res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms); 113 114 out: 115 crypto_mac_free_ctx(hmac_parms.ctx, hmac_parms.algo); 116 return res; 117 } 118