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