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