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