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
pbkdf2_f(uint8_t * out,size_t len,uint32_t idx,struct hmac_parms * h,struct pbkdf2_parms * p)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
tee_cryp_pbkdf2(uint32_t hash_id,const uint8_t * password,size_t password_len,const uint8_t * salt,size_t salt_len,uint32_t iteration_count,uint8_t * derived_key,size_t derived_key_len)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