Commit fc2f4246b4b3b750e8c5aa08440ec5e1c952088e
Committed by
Simon Glass
1 parent
49cad54788
Exists in
v2017.01-smarct4x
and in
37 other branches
rsa: Split the rsa-verify to separate the modular exponentiation
Public exponentiation which is required in rsa verify functionality is tightly integrated with verification code in rsa_verify.c. The patch splits the file into twp separating the modular exponentiation. 1. rsa-verify.c - The file parses device tree keys node to fill a keyprop structure. The keyprop structure can then be converted to implementation specific format. (struct rsa_pub_key for sw implementation) - The parsed device tree node is then passed to a generic rsa_mod_exp function. 2. rsa-mod-exp.c Move the software specific functions related to modular exponentiation from rsa-verify.c to this file. Signed-off-by: Ruchika Gupta <ruchika.gupta@freescale.com> CC: Simon Glass <sjg@chromium.org> Acked-by: Simon Glass <sjg@chromium.org>
Showing 5 changed files with 404 additions and 276 deletions Side-by-side Diff
include/u-boot/rsa-mod-exp.h
1 | +/* | |
2 | + * Copyright (c) 2014, Ruchika Gupta. | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | +*/ | |
6 | + | |
7 | +#ifndef _RSA_MOD_EXP_H | |
8 | +#define _RSA_MOD_EXP_H | |
9 | + | |
10 | +#include <errno.h> | |
11 | +#include <image.h> | |
12 | + | |
13 | +/** | |
14 | + * struct key_prop - holder for a public key properties | |
15 | + * | |
16 | + * The struct has pointers to modulus (Typically called N), | |
17 | + * The inverse, R^2, exponent. These can be typecasted and | |
18 | + * used as byte arrays or converted to the required format | |
19 | + * as per requirement of RSA implementation. | |
20 | + */ | |
21 | +struct key_prop { | |
22 | + const void *rr; /* R^2 can be treated as byte array */ | |
23 | + const void *modulus; /* modulus as byte array */ | |
24 | + const void *public_exponent; /* public exponent as byte array */ | |
25 | + uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */ | |
26 | + int num_bits; /* Key length in bits */ | |
27 | + uint32_t exp_len; /* Exponent length in number of uint8_t */ | |
28 | +}; | |
29 | + | |
30 | +/** | |
31 | + * rsa_mod_exp_sw() - Perform RSA Modular Exponentiation in sw | |
32 | + * | |
33 | + * Operation: out[] = sig ^ exponent % modulus | |
34 | + * | |
35 | + * @sig: RSA PKCS1.5 signature | |
36 | + * @sig_len: Length of signature in number of bytes | |
37 | + * @node: Node with RSA key elements like modulus, exponent, R^2, n0inv | |
38 | + * @out: Result in form of byte array | |
39 | + */ | |
40 | +int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, | |
41 | + struct key_prop *node, uint8_t *out); | |
42 | + | |
43 | +#endif |
lib/rsa/Makefile
lib/rsa/rsa-mod-exp.c
1 | +/* | |
2 | + * Copyright (c) 2013, Google Inc. | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | + */ | |
6 | + | |
7 | +#ifndef USE_HOSTCC | |
8 | +#include <common.h> | |
9 | +#include <fdtdec.h> | |
10 | +#include <asm/types.h> | |
11 | +#include <asm/byteorder.h> | |
12 | +#include <asm/errno.h> | |
13 | +#include <asm/types.h> | |
14 | +#include <asm/unaligned.h> | |
15 | +#else | |
16 | +#include "fdt_host.h" | |
17 | +#include "mkimage.h" | |
18 | +#include <fdt_support.h> | |
19 | +#endif | |
20 | +#include <u-boot/rsa.h> | |
21 | +#include <u-boot/rsa-mod-exp.h> | |
22 | + | |
23 | +#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby))) | |
24 | + | |
25 | +#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a) | |
26 | +#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a)) | |
27 | + | |
28 | +/* Default public exponent for backward compatibility */ | |
29 | +#define RSA_DEFAULT_PUBEXP 65537 | |
30 | + | |
31 | +/** | |
32 | + * subtract_modulus() - subtract modulus from the given value | |
33 | + * | |
34 | + * @key: Key containing modulus to subtract | |
35 | + * @num: Number to subtract modulus from, as little endian word array | |
36 | + */ | |
37 | +static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[]) | |
38 | +{ | |
39 | + int64_t acc = 0; | |
40 | + uint i; | |
41 | + | |
42 | + for (i = 0; i < key->len; i++) { | |
43 | + acc += (uint64_t)num[i] - key->modulus[i]; | |
44 | + num[i] = (uint32_t)acc; | |
45 | + acc >>= 32; | |
46 | + } | |
47 | +} | |
48 | + | |
49 | +/** | |
50 | + * greater_equal_modulus() - check if a value is >= modulus | |
51 | + * | |
52 | + * @key: Key containing modulus to check | |
53 | + * @num: Number to check against modulus, as little endian word array | |
54 | + * @return 0 if num < modulus, 1 if num >= modulus | |
55 | + */ | |
56 | +static int greater_equal_modulus(const struct rsa_public_key *key, | |
57 | + uint32_t num[]) | |
58 | +{ | |
59 | + int i; | |
60 | + | |
61 | + for (i = (int)key->len - 1; i >= 0; i--) { | |
62 | + if (num[i] < key->modulus[i]) | |
63 | + return 0; | |
64 | + if (num[i] > key->modulus[i]) | |
65 | + return 1; | |
66 | + } | |
67 | + | |
68 | + return 1; /* equal */ | |
69 | +} | |
70 | + | |
71 | +/** | |
72 | + * montgomery_mul_add_step() - Perform montgomery multiply-add step | |
73 | + * | |
74 | + * Operation: montgomery result[] += a * b[] / n0inv % modulus | |
75 | + * | |
76 | + * @key: RSA key | |
77 | + * @result: Place to put result, as little endian word array | |
78 | + * @a: Multiplier | |
79 | + * @b: Multiplicand, as little endian word array | |
80 | + */ | |
81 | +static void montgomery_mul_add_step(const struct rsa_public_key *key, | |
82 | + uint32_t result[], const uint32_t a, const uint32_t b[]) | |
83 | +{ | |
84 | + uint64_t acc_a, acc_b; | |
85 | + uint32_t d0; | |
86 | + uint i; | |
87 | + | |
88 | + acc_a = (uint64_t)a * b[0] + result[0]; | |
89 | + d0 = (uint32_t)acc_a * key->n0inv; | |
90 | + acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a; | |
91 | + for (i = 1; i < key->len; i++) { | |
92 | + acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i]; | |
93 | + acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] + | |
94 | + (uint32_t)acc_a; | |
95 | + result[i - 1] = (uint32_t)acc_b; | |
96 | + } | |
97 | + | |
98 | + acc_a = (acc_a >> 32) + (acc_b >> 32); | |
99 | + | |
100 | + result[i - 1] = (uint32_t)acc_a; | |
101 | + | |
102 | + if (acc_a >> 32) | |
103 | + subtract_modulus(key, result); | |
104 | +} | |
105 | + | |
106 | +/** | |
107 | + * montgomery_mul() - Perform montgomery mutitply | |
108 | + * | |
109 | + * Operation: montgomery result[] = a[] * b[] / n0inv % modulus | |
110 | + * | |
111 | + * @key: RSA key | |
112 | + * @result: Place to put result, as little endian word array | |
113 | + * @a: Multiplier, as little endian word array | |
114 | + * @b: Multiplicand, as little endian word array | |
115 | + */ | |
116 | +static void montgomery_mul(const struct rsa_public_key *key, | |
117 | + uint32_t result[], uint32_t a[], const uint32_t b[]) | |
118 | +{ | |
119 | + uint i; | |
120 | + | |
121 | + for (i = 0; i < key->len; ++i) | |
122 | + result[i] = 0; | |
123 | + for (i = 0; i < key->len; ++i) | |
124 | + montgomery_mul_add_step(key, result, a[i], b); | |
125 | +} | |
126 | + | |
127 | +/** | |
128 | + * num_pub_exponent_bits() - Number of bits in the public exponent | |
129 | + * | |
130 | + * @key: RSA key | |
131 | + * @num_bits: Storage for the number of public exponent bits | |
132 | + */ | |
133 | +static int num_public_exponent_bits(const struct rsa_public_key *key, | |
134 | + int *num_bits) | |
135 | +{ | |
136 | + uint64_t exponent; | |
137 | + int exponent_bits; | |
138 | + const uint max_bits = (sizeof(exponent) * 8); | |
139 | + | |
140 | + exponent = key->exponent; | |
141 | + exponent_bits = 0; | |
142 | + | |
143 | + if (!exponent) { | |
144 | + *num_bits = exponent_bits; | |
145 | + return 0; | |
146 | + } | |
147 | + | |
148 | + for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits) | |
149 | + if (!(exponent >>= 1)) { | |
150 | + *num_bits = exponent_bits; | |
151 | + return 0; | |
152 | + } | |
153 | + | |
154 | + return -EINVAL; | |
155 | +} | |
156 | + | |
157 | +/** | |
158 | + * is_public_exponent_bit_set() - Check if a bit in the public exponent is set | |
159 | + * | |
160 | + * @key: RSA key | |
161 | + * @pos: The bit position to check | |
162 | + */ | |
163 | +static int is_public_exponent_bit_set(const struct rsa_public_key *key, | |
164 | + int pos) | |
165 | +{ | |
166 | + return key->exponent & (1ULL << pos); | |
167 | +} | |
168 | + | |
169 | +/** | |
170 | + * pow_mod() - in-place public exponentiation | |
171 | + * | |
172 | + * @key: RSA key | |
173 | + * @inout: Big-endian word array containing value and result | |
174 | + */ | |
175 | +static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) | |
176 | +{ | |
177 | + uint32_t *result, *ptr; | |
178 | + uint i; | |
179 | + int j, k; | |
180 | + | |
181 | + /* Sanity check for stack size - key->len is in 32-bit words */ | |
182 | + if (key->len > RSA_MAX_KEY_BITS / 32) { | |
183 | + debug("RSA key words %u exceeds maximum %d\n", key->len, | |
184 | + RSA_MAX_KEY_BITS / 32); | |
185 | + return -EINVAL; | |
186 | + } | |
187 | + | |
188 | + uint32_t val[key->len], acc[key->len], tmp[key->len]; | |
189 | + uint32_t a_scaled[key->len]; | |
190 | + result = tmp; /* Re-use location. */ | |
191 | + | |
192 | + /* Convert from big endian byte array to little endian word array. */ | |
193 | + for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--) | |
194 | + val[i] = get_unaligned_be32(ptr); | |
195 | + | |
196 | + if (0 != num_public_exponent_bits(key, &k)) | |
197 | + return -EINVAL; | |
198 | + | |
199 | + if (k < 2) { | |
200 | + debug("Public exponent is too short (%d bits, minimum 2)\n", | |
201 | + k); | |
202 | + return -EINVAL; | |
203 | + } | |
204 | + | |
205 | + if (!is_public_exponent_bit_set(key, 0)) { | |
206 | + debug("LSB of RSA public exponent must be set.\n"); | |
207 | + return -EINVAL; | |
208 | + } | |
209 | + | |
210 | + /* the bit at e[k-1] is 1 by definition, so start with: C := M */ | |
211 | + montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */ | |
212 | + /* retain scaled version for intermediate use */ | |
213 | + memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0])); | |
214 | + | |
215 | + for (j = k - 2; j > 0; --j) { | |
216 | + montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ | |
217 | + | |
218 | + if (is_public_exponent_bit_set(key, j)) { | |
219 | + /* acc = tmp * val / R mod n */ | |
220 | + montgomery_mul(key, acc, tmp, a_scaled); | |
221 | + } else { | |
222 | + /* e[j] == 0, copy tmp back to acc for next operation */ | |
223 | + memcpy(acc, tmp, key->len * sizeof(acc[0])); | |
224 | + } | |
225 | + } | |
226 | + | |
227 | + /* the bit at e[0] is always 1 */ | |
228 | + montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ | |
229 | + montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */ | |
230 | + memcpy(result, acc, key->len * sizeof(result[0])); | |
231 | + | |
232 | + /* Make sure result < mod; result is at most 1x mod too large. */ | |
233 | + if (greater_equal_modulus(key, result)) | |
234 | + subtract_modulus(key, result); | |
235 | + | |
236 | + /* Convert to bigendian byte array */ | |
237 | + for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++) | |
238 | + put_unaligned_be32(result[i], ptr); | |
239 | + return 0; | |
240 | +} | |
241 | + | |
242 | +static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len) | |
243 | +{ | |
244 | + int i; | |
245 | + | |
246 | + for (i = 0; i < len; i++) | |
247 | + dst[i] = fdt32_to_cpu(src[len - 1 - i]); | |
248 | +} | |
249 | + | |
250 | +int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, | |
251 | + struct key_prop *prop, uint8_t *out) | |
252 | +{ | |
253 | + struct rsa_public_key key; | |
254 | + int ret; | |
255 | + | |
256 | + if (!prop) { | |
257 | + debug("%s: Skipping invalid prop", __func__); | |
258 | + return -EBADF; | |
259 | + } | |
260 | + key.n0inv = prop->n0inv; | |
261 | + key.len = prop->num_bits; | |
262 | + | |
263 | + if (!prop->public_exponent) | |
264 | + key.exponent = RSA_DEFAULT_PUBEXP; | |
265 | + else | |
266 | + key.exponent = | |
267 | + fdt64_to_cpu(*((uint64_t *)(prop->public_exponent))); | |
268 | + | |
269 | + if (!key.len || !prop->modulus || !prop->rr) { | |
270 | + debug("%s: Missing RSA key info", __func__); | |
271 | + return -EFAULT; | |
272 | + } | |
273 | + | |
274 | + /* Sanity check for stack size */ | |
275 | + if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) { | |
276 | + debug("RSA key bits %u outside allowed range %d..%d\n", | |
277 | + key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS); | |
278 | + return -EFAULT; | |
279 | + } | |
280 | + key.len /= sizeof(uint32_t) * 8; | |
281 | + uint32_t key1[key.len], key2[key.len]; | |
282 | + | |
283 | + key.modulus = key1; | |
284 | + key.rr = key2; | |
285 | + rsa_convert_big_endian(key.modulus, (uint32_t *)prop->modulus, key.len); | |
286 | + rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len); | |
287 | + if (!key.modulus || !key.rr) { | |
288 | + debug("%s: Out of memory", __func__); | |
289 | + return -ENOMEM; | |
290 | + } | |
291 | + | |
292 | + uint32_t buf[sig_len / sizeof(uint32_t)]; | |
293 | + | |
294 | + memcpy(buf, sig, sig_len); | |
295 | + | |
296 | + ret = pow_mod(&key, buf); | |
297 | + if (ret) | |
298 | + return ret; | |
299 | + | |
300 | + memcpy(out, buf, sig_len); | |
301 | + | |
302 | + return 0; | |
303 | +} |
lib/rsa/rsa-verify.c
... | ... | @@ -17,230 +17,26 @@ |
17 | 17 | #include "mkimage.h" |
18 | 18 | #include <fdt_support.h> |
19 | 19 | #endif |
20 | +#include <u-boot/rsa-mod-exp.h> | |
20 | 21 | #include <u-boot/rsa.h> |
21 | -#include <u-boot/sha1.h> | |
22 | -#include <u-boot/sha256.h> | |
23 | 22 | |
24 | -#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby))) | |
25 | - | |
26 | -#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a) | |
27 | -#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a)) | |
28 | - | |
29 | 23 | /* Default public exponent for backward compatibility */ |
30 | 24 | #define RSA_DEFAULT_PUBEXP 65537 |
31 | 25 | |
32 | 26 | /** |
33 | - * subtract_modulus() - subtract modulus from the given value | |
27 | + * rsa_verify_key() - Verify a signature against some data using RSA Key | |
34 | 28 | * |
35 | - * @key: Key containing modulus to subtract | |
36 | - * @num: Number to subtract modulus from, as little endian word array | |
37 | - */ | |
38 | -static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[]) | |
39 | -{ | |
40 | - int64_t acc = 0; | |
41 | - uint i; | |
42 | - | |
43 | - for (i = 0; i < key->len; i++) { | |
44 | - acc += (uint64_t)num[i] - key->modulus[i]; | |
45 | - num[i] = (uint32_t)acc; | |
46 | - acc >>= 32; | |
47 | - } | |
48 | -} | |
49 | - | |
50 | -/** | |
51 | - * greater_equal_modulus() - check if a value is >= modulus | |
29 | + * Verify a RSA PKCS1.5 signature against an expected hash using | |
30 | + * the RSA Key properties in prop structure. | |
52 | 31 | * |
53 | - * @key: Key containing modulus to check | |
54 | - * @num: Number to check against modulus, as little endian word array | |
55 | - * @return 0 if num < modulus, 1 if num >= modulus | |
32 | + * @prop: Specifies key | |
33 | + * @sig: Signature | |
34 | + * @sig_len: Number of bytes in signature | |
35 | + * @hash: Pointer to the expected hash | |
36 | + * @algo: Checksum algo structure having information on RSA padding etc. | |
37 | + * @return 0 if verified, -ve on error | |
56 | 38 | */ |
57 | -static int greater_equal_modulus(const struct rsa_public_key *key, | |
58 | - uint32_t num[]) | |
59 | -{ | |
60 | - int i; | |
61 | - | |
62 | - for (i = (int)key->len - 1; i >= 0; i--) { | |
63 | - if (num[i] < key->modulus[i]) | |
64 | - return 0; | |
65 | - if (num[i] > key->modulus[i]) | |
66 | - return 1; | |
67 | - } | |
68 | - | |
69 | - return 1; /* equal */ | |
70 | -} | |
71 | - | |
72 | -/** | |
73 | - * montgomery_mul_add_step() - Perform montgomery multiply-add step | |
74 | - * | |
75 | - * Operation: montgomery result[] += a * b[] / n0inv % modulus | |
76 | - * | |
77 | - * @key: RSA key | |
78 | - * @result: Place to put result, as little endian word array | |
79 | - * @a: Multiplier | |
80 | - * @b: Multiplicand, as little endian word array | |
81 | - */ | |
82 | -static void montgomery_mul_add_step(const struct rsa_public_key *key, | |
83 | - uint32_t result[], const uint32_t a, const uint32_t b[]) | |
84 | -{ | |
85 | - uint64_t acc_a, acc_b; | |
86 | - uint32_t d0; | |
87 | - uint i; | |
88 | - | |
89 | - acc_a = (uint64_t)a * b[0] + result[0]; | |
90 | - d0 = (uint32_t)acc_a * key->n0inv; | |
91 | - acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a; | |
92 | - for (i = 1; i < key->len; i++) { | |
93 | - acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i]; | |
94 | - acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] + | |
95 | - (uint32_t)acc_a; | |
96 | - result[i - 1] = (uint32_t)acc_b; | |
97 | - } | |
98 | - | |
99 | - acc_a = (acc_a >> 32) + (acc_b >> 32); | |
100 | - | |
101 | - result[i - 1] = (uint32_t)acc_a; | |
102 | - | |
103 | - if (acc_a >> 32) | |
104 | - subtract_modulus(key, result); | |
105 | -} | |
106 | - | |
107 | -/** | |
108 | - * montgomery_mul() - Perform montgomery mutitply | |
109 | - * | |
110 | - * Operation: montgomery result[] = a[] * b[] / n0inv % modulus | |
111 | - * | |
112 | - * @key: RSA key | |
113 | - * @result: Place to put result, as little endian word array | |
114 | - * @a: Multiplier, as little endian word array | |
115 | - * @b: Multiplicand, as little endian word array | |
116 | - */ | |
117 | -static void montgomery_mul(const struct rsa_public_key *key, | |
118 | - uint32_t result[], uint32_t a[], const uint32_t b[]) | |
119 | -{ | |
120 | - uint i; | |
121 | - | |
122 | - for (i = 0; i < key->len; ++i) | |
123 | - result[i] = 0; | |
124 | - for (i = 0; i < key->len; ++i) | |
125 | - montgomery_mul_add_step(key, result, a[i], b); | |
126 | -} | |
127 | - | |
128 | -/** | |
129 | - * num_pub_exponent_bits() - Number of bits in the public exponent | |
130 | - * | |
131 | - * @key: RSA key | |
132 | - * @num_bits: Storage for the number of public exponent bits | |
133 | - */ | |
134 | -static int num_public_exponent_bits(const struct rsa_public_key *key, | |
135 | - int *num_bits) | |
136 | -{ | |
137 | - uint64_t exponent; | |
138 | - int exponent_bits; | |
139 | - const uint max_bits = (sizeof(exponent) * 8); | |
140 | - | |
141 | - exponent = key->exponent; | |
142 | - exponent_bits = 0; | |
143 | - | |
144 | - if (!exponent) { | |
145 | - *num_bits = exponent_bits; | |
146 | - return 0; | |
147 | - } | |
148 | - | |
149 | - for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits) | |
150 | - if (!(exponent >>= 1)) { | |
151 | - *num_bits = exponent_bits; | |
152 | - return 0; | |
153 | - } | |
154 | - | |
155 | - return -EINVAL; | |
156 | -} | |
157 | - | |
158 | -/** | |
159 | - * is_public_exponent_bit_set() - Check if a bit in the public exponent is set | |
160 | - * | |
161 | - * @key: RSA key | |
162 | - * @pos: The bit position to check | |
163 | - */ | |
164 | -static int is_public_exponent_bit_set(const struct rsa_public_key *key, | |
165 | - int pos) | |
166 | -{ | |
167 | - return key->exponent & (1ULL << pos); | |
168 | -} | |
169 | - | |
170 | -/** | |
171 | - * pow_mod() - in-place public exponentiation | |
172 | - * | |
173 | - * @key: RSA key | |
174 | - * @inout: Big-endian word array containing value and result | |
175 | - */ | |
176 | -static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) | |
177 | -{ | |
178 | - uint32_t *result, *ptr; | |
179 | - uint i; | |
180 | - int j, k; | |
181 | - | |
182 | - /* Sanity check for stack size - key->len is in 32-bit words */ | |
183 | - if (key->len > RSA_MAX_KEY_BITS / 32) { | |
184 | - debug("RSA key words %u exceeds maximum %d\n", key->len, | |
185 | - RSA_MAX_KEY_BITS / 32); | |
186 | - return -EINVAL; | |
187 | - } | |
188 | - | |
189 | - uint32_t val[key->len], acc[key->len], tmp[key->len]; | |
190 | - uint32_t a_scaled[key->len]; | |
191 | - result = tmp; /* Re-use location. */ | |
192 | - | |
193 | - /* Convert from big endian byte array to little endian word array. */ | |
194 | - for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--) | |
195 | - val[i] = get_unaligned_be32(ptr); | |
196 | - | |
197 | - if (0 != num_public_exponent_bits(key, &k)) | |
198 | - return -EINVAL; | |
199 | - | |
200 | - if (k < 2) { | |
201 | - debug("Public exponent is too short (%d bits, minimum 2)\n", | |
202 | - k); | |
203 | - return -EINVAL; | |
204 | - } | |
205 | - | |
206 | - if (!is_public_exponent_bit_set(key, 0)) { | |
207 | - debug("LSB of RSA public exponent must be set.\n"); | |
208 | - return -EINVAL; | |
209 | - } | |
210 | - | |
211 | - /* the bit at e[k-1] is 1 by definition, so start with: C := M */ | |
212 | - montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */ | |
213 | - /* retain scaled version for intermediate use */ | |
214 | - memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0])); | |
215 | - | |
216 | - for (j = k - 2; j > 0; --j) { | |
217 | - montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ | |
218 | - | |
219 | - if (is_public_exponent_bit_set(key, j)) { | |
220 | - /* acc = tmp * val / R mod n */ | |
221 | - montgomery_mul(key, acc, tmp, a_scaled); | |
222 | - } else { | |
223 | - /* e[j] == 0, copy tmp back to acc for next operation */ | |
224 | - memcpy(acc, tmp, key->len * sizeof(acc[0])); | |
225 | - } | |
226 | - } | |
227 | - | |
228 | - /* the bit at e[0] is always 1 */ | |
229 | - montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ | |
230 | - montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */ | |
231 | - memcpy(result, acc, key->len * sizeof(result[0])); | |
232 | - | |
233 | - /* Make sure result < mod; result is at most 1x mod too large. */ | |
234 | - if (greater_equal_modulus(key, result)) | |
235 | - subtract_modulus(key, result); | |
236 | - | |
237 | - /* Convert to bigendian byte array */ | |
238 | - for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++) | |
239 | - put_unaligned_be32(result[i], ptr); | |
240 | - return 0; | |
241 | -} | |
242 | - | |
243 | -static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig, | |
39 | +static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig, | |
244 | 40 | const uint32_t sig_len, const uint8_t *hash, |
245 | 41 | struct checksum_algo *algo) |
246 | 42 | { |
247 | 43 | |
... | ... | @@ -248,10 +44,10 @@ |
248 | 44 | int pad_len; |
249 | 45 | int ret; |
250 | 46 | |
251 | - if (!key || !sig || !hash || !algo) | |
47 | + if (!prop || !sig || !hash || !algo) | |
252 | 48 | return -EIO; |
253 | 49 | |
254 | - if (sig_len != (key->len * sizeof(uint32_t))) { | |
50 | + if (sig_len != (prop->num_bits / 8)) { | |
255 | 51 | debug("Signature is of incorrect length %d\n", sig_len); |
256 | 52 | return -EINVAL; |
257 | 53 | } |
258 | 54 | |
259 | 55 | |
... | ... | @@ -265,13 +61,13 @@ |
265 | 61 | return -EINVAL; |
266 | 62 | } |
267 | 63 | |
268 | - uint32_t buf[sig_len / sizeof(uint32_t)]; | |
64 | + uint8_t buf[sig_len]; | |
269 | 65 | |
270 | - memcpy(buf, sig, sig_len); | |
271 | - | |
272 | - ret = pow_mod(key, buf); | |
273 | - if (ret) | |
66 | + ret = rsa_mod_exp_sw(sig, sig_len, prop, buf); | |
67 | + if (ret) { | |
68 | + debug("Error in Modular exponentation\n"); | |
274 | 69 | return ret; |
70 | + } | |
275 | 71 | |
276 | 72 | padding = algo->rsa_padding; |
277 | 73 | pad_len = algo->pad_len - algo->checksum_len; |
278 | 74 | |
279 | 75 | |
280 | 76 | |
281 | 77 | |
282 | 78 | |
283 | 79 | |
284 | 80 | |
285 | 81 | |
... | ... | @@ -291,72 +87,57 @@ |
291 | 87 | return 0; |
292 | 88 | } |
293 | 89 | |
294 | -static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len) | |
295 | -{ | |
296 | - int i; | |
297 | - | |
298 | - for (i = 0; i < len; i++) | |
299 | - dst[i] = fdt32_to_cpu(src[len - 1 - i]); | |
300 | -} | |
301 | - | |
90 | +/** | |
91 | + * rsa_verify_with_keynode() - Verify a signature against some data using | |
92 | + * information in node with prperties of RSA Key like modulus, exponent etc. | |
93 | + * | |
94 | + * Parse sign-node and fill a key_prop structure with properties of the | |
95 | + * key. Verify a RSA PKCS1.5 signature against an expected hash using | |
96 | + * the properties parsed | |
97 | + * | |
98 | + * @info: Specifies key and FIT information | |
99 | + * @hash: Pointer to the expected hash | |
100 | + * @sig: Signature | |
101 | + * @sig_len: Number of bytes in signature | |
102 | + * @node: Node having the RSA Key properties | |
103 | + * @return 0 if verified, -ve on error | |
104 | + */ | |
302 | 105 | static int rsa_verify_with_keynode(struct image_sign_info *info, |
303 | - const void *hash, uint8_t *sig, uint sig_len, int node) | |
106 | + const void *hash, uint8_t *sig, | |
107 | + uint sig_len, int node) | |
304 | 108 | { |
305 | 109 | const void *blob = info->fdt_blob; |
306 | - struct rsa_public_key key; | |
307 | - const void *modulus, *rr; | |
308 | - const uint64_t *public_exponent; | |
110 | + struct key_prop prop; | |
309 | 111 | int length; |
310 | - int ret; | |
112 | + int ret = 0; | |
311 | 113 | |
312 | 114 | if (node < 0) { |
313 | 115 | debug("%s: Skipping invalid node", __func__); |
314 | 116 | return -EBADF; |
315 | 117 | } |
316 | - if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) { | |
317 | - debug("%s: Missing rsa,n0-inverse", __func__); | |
318 | - return -EFAULT; | |
319 | - } | |
320 | - key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0); | |
321 | - key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0); | |
322 | - public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length); | |
323 | - if (!public_exponent || length < sizeof(*public_exponent)) | |
324 | - key.exponent = RSA_DEFAULT_PUBEXP; | |
325 | - else | |
326 | - key.exponent = fdt64_to_cpu(*public_exponent); | |
327 | - modulus = fdt_getprop(blob, node, "rsa,modulus", NULL); | |
328 | - rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); | |
329 | - if (!key.len || !modulus || !rr) { | |
330 | - debug("%s: Missing RSA key info", __func__); | |
331 | - return -EFAULT; | |
332 | - } | |
333 | 118 | |
334 | - /* Sanity check for stack size */ | |
335 | - if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) { | |
336 | - debug("RSA key bits %u outside allowed range %d..%d\n", | |
337 | - key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS); | |
338 | - return -EFAULT; | |
339 | - } | |
340 | - key.len /= sizeof(uint32_t) * 8; | |
341 | - uint32_t key1[key.len], key2[key.len]; | |
119 | + prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0); | |
342 | 120 | |
343 | - key.modulus = key1; | |
344 | - key.rr = key2; | |
345 | - rsa_convert_big_endian(key.modulus, modulus, key.len); | |
346 | - rsa_convert_big_endian(key.rr, rr, key.len); | |
347 | - if (!key.modulus || !key.rr) { | |
348 | - debug("%s: Out of memory", __func__); | |
349 | - return -ENOMEM; | |
350 | - } | |
121 | + prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0); | |
351 | 122 | |
352 | - debug("key length %d\n", key.len); | |
353 | - ret = rsa_verify_key(&key, sig, sig_len, hash, info->algo->checksum); | |
354 | - if (ret) { | |
355 | - printf("%s: RSA failed to verify: %d\n", __func__, ret); | |
356 | - return ret; | |
123 | + prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length); | |
124 | + if (!prop.public_exponent || length < sizeof(uint64_t)) | |
125 | + prop.public_exponent = NULL; | |
126 | + | |
127 | + prop.exp_len = sizeof(uint64_t); | |
128 | + | |
129 | + prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL); | |
130 | + | |
131 | + prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); | |
132 | + | |
133 | + if (!prop.num_bits || !prop.modulus) { | |
134 | + debug("%s: Missing RSA key info", __func__); | |
135 | + return -EFAULT; | |
357 | 136 | } |
358 | 137 | |
359 | - return 0; | |
138 | + ret = rsa_verify_key(&prop, sig, sig_len, hash, info->algo->checksum); | |
139 | + | |
140 | + return ret; | |
360 | 141 | } |
361 | 142 | |
362 | 143 | int rsa_verify(struct image_sign_info *info, |
tools/Makefile
... | ... | @@ -60,7 +60,8 @@ |
60 | 60 | LIBFDT_OBJS := $(addprefix lib/libfdt/, \ |
61 | 61 | fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o) |
62 | 62 | RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ |
63 | - rsa-sign.o rsa-verify.o rsa-checksum.o) | |
63 | + rsa-sign.o rsa-verify.o rsa-checksum.o \ | |
64 | + rsa-mod-exp.o) | |
64 | 65 | |
65 | 66 | # common objs for dumpimage and mkimage |
66 | 67 | dumpimage-mkimage-objs := aisimage.o \ |
-
mentioned in commit fdf081