xref: /optee_os/core/tee/tee_cryp_pbkdf2.c (revision 51ac0e23b5c2b3c84469a0de79c9f027a46d5747)
1 /*
2  * Copyright (c) 2014, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <tee/tee_cryp_pbkdf2.h>
29 #include <tee/tee_cryp_provider.h>
30 #include <tee/tee_cryp_utl.h>
31 #include <utee_defines.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 struct hmac_parms {
36 	uint32_t algo;
37 	size_t hash_len;
38 	void *ctx;
39 };
40 
41 struct pbkdf2_parms {
42 	const uint8_t *password;
43 	size_t password_len;
44 	const uint8_t *salt;
45 	size_t salt_len;
46 	uint32_t iteration_count;
47 };
48 
49 static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx,
50 			   struct hmac_parms *h, struct pbkdf2_parms *p)
51 {
52 	TEE_Result res;
53 	uint8_t u[TEE_MAX_HASH_SIZE];
54 	uint32_t be_index;
55 	size_t i, j;
56 	const struct mac_ops *mac = &crypto_ops.mac;
57 
58 	memset(out, 0, len);
59 	for (i = 1; i <= p->iteration_count; i++) {
60 		res = mac->init(h->ctx, h->algo, p->password, p->password_len);
61 		if (res != TEE_SUCCESS)
62 			return res;
63 
64 		if (i == 1) {
65 			if (p->salt && p->salt_len) {
66 				res = mac->update(h->ctx, h->algo, p->salt,
67 						  p->salt_len);
68 				if (res != TEE_SUCCESS)
69 					return res;
70 			}
71 
72 			be_index = TEE_U32_TO_BIG_ENDIAN(idx);
73 
74 			res = mac->update(h->ctx, h->algo,
75 					  (uint8_t *)&be_index,
76 					  sizeof(be_index));
77 			if (res != TEE_SUCCESS)
78 				return res;
79 		} else {
80 			res = mac->update(h->ctx, h->algo, u, h->hash_len);
81 			if (res != TEE_SUCCESS)
82 				return res;
83 		}
84 
85 		res = mac->final(h->ctx, h->algo, u, sizeof(u));
86 		if (res != TEE_SUCCESS)
87 			return res;
88 
89 		for (j = 0; j < len; j++)
90 			out[j] ^= u[j];
91 	}
92 	return TEE_SUCCESS;
93 }
94 
95 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
96 			   size_t password_len, const uint8_t *salt,
97 			   size_t salt_len, uint32_t iteration_count,
98 			   uint8_t *derived_key, size_t derived_key_len)
99 {
100 	TEE_Result res;
101 	size_t ctx_size, i, l, r;
102 	uint8_t *out = derived_key;
103 	struct pbkdf2_parms pbkdf2_parms;
104 	struct hmac_parms hmac_parms = {0, };
105 	const struct mac_ops *mac = &crypto_ops.mac;
106 
107 	if (!mac->get_ctx_size || !mac->init || !mac->update ||
108 	    !mac->final)
109 		return TEE_ERROR_NOT_IMPLEMENTED;
110 
111 	hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id);
112 
113 	res = tee_mac_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len);
114 	if (res != TEE_SUCCESS)
115 		return res;
116 
117 	res = mac->get_ctx_size(hmac_parms.algo, &ctx_size);
118 	if (res != TEE_SUCCESS)
119 		return res;
120 
121 	hmac_parms.ctx = malloc(ctx_size);
122 	if (!hmac_parms.ctx)
123 		return TEE_ERROR_OUT_OF_MEMORY;
124 
125 	pbkdf2_parms.password = password;
126 	pbkdf2_parms.password_len = password_len;
127 	pbkdf2_parms.salt = salt;
128 	pbkdf2_parms.salt_len = salt_len;
129 	pbkdf2_parms.iteration_count = iteration_count;
130 
131 	l = derived_key_len / hmac_parms.hash_len;
132 	r = derived_key_len % hmac_parms.hash_len;
133 
134 	for (i = 1; i <= l; i++) {
135 		res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms,
136 			       &pbkdf2_parms);
137 		if (res != TEE_SUCCESS)
138 			goto out;
139 		out += hmac_parms.hash_len;
140 	}
141 	if (r)
142 		res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms);
143 
144 out:
145 	free(hmac_parms.ctx);
146 	return res;
147 }
148