xref: /optee_os/core/tee/tee_cryp_pbkdf2.c (revision a1cbb728630308fcf902a8953a32cc972d14757e)
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