xref: /optee_os/core/tee/tee_cryp_pbkdf2.c (revision b1469ba0bfd0371eb52bd50f5c52eeda7a8f5f1e)
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 <crypto/crypto.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <tee/tee_cryp_pbkdf2.h>
32 #include <tee/tee_cryp_utl.h>
33 #include <utee_defines.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 
57 	memset(out, 0, len);
58 	for (i = 1; i <= p->iteration_count; i++) {
59 		res = crypto_mac_init(h->ctx, h->algo, p->password,
60 				      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 = crypto_mac_update(h->ctx, h->algo,
67 							p->salt, 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 = crypto_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 = crypto_mac_update(h->ctx, h->algo, u,
81 						h->hash_len);
82 			if (res != TEE_SUCCESS)
83 				return res;
84 		}
85 
86 		res = crypto_mac_final(h->ctx, h->algo, u, sizeof(u));
87 		if (res != TEE_SUCCESS)
88 			return res;
89 
90 		for (j = 0; j < len; j++)
91 			out[j] ^= u[j];
92 	}
93 	return TEE_SUCCESS;
94 }
95 
96 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
97 			   size_t password_len, const uint8_t *salt,
98 			   size_t salt_len, uint32_t iteration_count,
99 			   uint8_t *derived_key, size_t derived_key_len)
100 {
101 	TEE_Result res;
102 	size_t ctx_size, i, l, r;
103 	uint8_t *out = derived_key;
104 	struct pbkdf2_parms pbkdf2_parms;
105 	struct hmac_parms hmac_parms = {0, };
106 
107 	hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id);
108 
109 	res = tee_mac_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len);
110 	if (res != TEE_SUCCESS)
111 		return res;
112 
113 	res = crypto_mac_get_ctx_size(hmac_parms.algo, &ctx_size);
114 	if (res != TEE_SUCCESS)
115 		return res;
116 
117 	hmac_parms.ctx = malloc(ctx_size);
118 	if (!hmac_parms.ctx)
119 		return TEE_ERROR_OUT_OF_MEMORY;
120 
121 	pbkdf2_parms.password = password;
122 	pbkdf2_parms.password_len = password_len;
123 	pbkdf2_parms.salt = salt;
124 	pbkdf2_parms.salt_len = salt_len;
125 	pbkdf2_parms.iteration_count = iteration_count;
126 
127 	l = derived_key_len / hmac_parms.hash_len;
128 	r = derived_key_len % hmac_parms.hash_len;
129 
130 	for (i = 1; i <= l; i++) {
131 		res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms,
132 			       &pbkdf2_parms);
133 		if (res != TEE_SUCCESS)
134 			goto out;
135 		out += hmac_parms.hash_len;
136 	}
137 	if (r)
138 		res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms);
139 
140 out:
141 	free(hmac_parms.ctx);
142 	return res;
143 }
144