blob: 5b3ea02f82f83dc8d5126e445f56fe14c783dcb8 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ruchika Guptafc2f4242015-01-23 16:01:50 +05302/*
3 * Copyright (c) 2013, Google Inc.
Ruchika Guptafc2f4242015-01-23 16:01:50 +05304 */
5
6#ifndef USE_HOSTCC
Ruchika Guptafc2f4242015-01-23 16:01:50 +05307#include <fdtdec.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -06008#include <log.h>
Ruchika Guptafc2f4242015-01-23 16:01:50 +05309#include <asm/types.h>
10#include <asm/byteorder.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090011#include <linux/errno.h>
Ruchika Guptafc2f4242015-01-23 16:01:50 +053012#include <asm/types.h>
13#include <asm/unaligned.h>
14#else
15#include "fdt_host.h"
16#include "mkimage.h"
17#include <fdt_support.h>
18#endif
19#include <u-boot/rsa.h>
20#include <u-boot/rsa-mod-exp.h>
21
22#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
23
24#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
25#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
26
Rasmus Villemoes3f8808e2020-10-06 12:09:45 +020027static inline uint64_t fdt64_to_cpup(const void *p)
28{
29 fdt64_t w;
30
31 memcpy(&w, p, sizeof(w));
32 return fdt64_to_cpu(w);
33}
34
Ruchika Guptafc2f4242015-01-23 16:01:50 +053035/* Default public exponent for backward compatibility */
36#define RSA_DEFAULT_PUBEXP 65537
37
38/**
39 * subtract_modulus() - subtract modulus from the given value
40 *
41 * @key: Key containing modulus to subtract
42 * @num: Number to subtract modulus from, as little endian word array
43 */
44static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
45{
46 int64_t acc = 0;
47 uint i;
48
49 for (i = 0; i < key->len; i++) {
50 acc += (uint64_t)num[i] - key->modulus[i];
51 num[i] = (uint32_t)acc;
52 acc >>= 32;
53 }
54}
55
56/**
57 * greater_equal_modulus() - check if a value is >= modulus
58 *
59 * @key: Key containing modulus to check
60 * @num: Number to check against modulus, as little endian word array
Heinrich Schuchardt185f8122022-01-19 18:05:50 +010061 * Return: 0 if num < modulus, 1 if num >= modulus
Ruchika Guptafc2f4242015-01-23 16:01:50 +053062 */
63static int greater_equal_modulus(const struct rsa_public_key *key,
64 uint32_t num[])
65{
66 int i;
67
68 for (i = (int)key->len - 1; i >= 0; i--) {
69 if (num[i] < key->modulus[i])
70 return 0;
71 if (num[i] > key->modulus[i])
72 return 1;
73 }
74
75 return 1; /* equal */
76}
77
78/**
79 * montgomery_mul_add_step() - Perform montgomery multiply-add step
80 *
81 * Operation: montgomery result[] += a * b[] / n0inv % modulus
82 *
83 * @key: RSA key
84 * @result: Place to put result, as little endian word array
85 * @a: Multiplier
86 * @b: Multiplicand, as little endian word array
87 */
88static void montgomery_mul_add_step(const struct rsa_public_key *key,
89 uint32_t result[], const uint32_t a, const uint32_t b[])
90{
91 uint64_t acc_a, acc_b;
92 uint32_t d0;
93 uint i;
94
95 acc_a = (uint64_t)a * b[0] + result[0];
96 d0 = (uint32_t)acc_a * key->n0inv;
97 acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
98 for (i = 1; i < key->len; i++) {
99 acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
100 acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
101 (uint32_t)acc_a;
102 result[i - 1] = (uint32_t)acc_b;
103 }
104
105 acc_a = (acc_a >> 32) + (acc_b >> 32);
106
107 result[i - 1] = (uint32_t)acc_a;
108
109 if (acc_a >> 32)
110 subtract_modulus(key, result);
111}
112
113/**
114 * montgomery_mul() - Perform montgomery mutitply
115 *
116 * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
117 *
118 * @key: RSA key
119 * @result: Place to put result, as little endian word array
120 * @a: Multiplier, as little endian word array
121 * @b: Multiplicand, as little endian word array
122 */
123static void montgomery_mul(const struct rsa_public_key *key,
124 uint32_t result[], uint32_t a[], const uint32_t b[])
125{
126 uint i;
127
128 for (i = 0; i < key->len; ++i)
129 result[i] = 0;
130 for (i = 0; i < key->len; ++i)
131 montgomery_mul_add_step(key, result, a[i], b);
132}
133
134/**
135 * num_pub_exponent_bits() - Number of bits in the public exponent
136 *
137 * @key: RSA key
138 * @num_bits: Storage for the number of public exponent bits
139 */
140static int num_public_exponent_bits(const struct rsa_public_key *key,
141 int *num_bits)
142{
143 uint64_t exponent;
144 int exponent_bits;
145 const uint max_bits = (sizeof(exponent) * 8);
146
147 exponent = key->exponent;
148 exponent_bits = 0;
149
150 if (!exponent) {
151 *num_bits = exponent_bits;
152 return 0;
153 }
154
155 for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
156 if (!(exponent >>= 1)) {
157 *num_bits = exponent_bits;
158 return 0;
159 }
160
161 return -EINVAL;
162}
163
164/**
165 * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
166 *
167 * @key: RSA key
168 * @pos: The bit position to check
169 */
170static int is_public_exponent_bit_set(const struct rsa_public_key *key,
171 int pos)
172{
173 return key->exponent & (1ULL << pos);
174}
175
176/**
177 * pow_mod() - in-place public exponentiation
178 *
179 * @key: RSA key
180 * @inout: Big-endian word array containing value and result
181 */
182static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
183{
184 uint32_t *result, *ptr;
185 uint i;
186 int j, k;
187
188 /* Sanity check for stack size - key->len is in 32-bit words */
189 if (key->len > RSA_MAX_KEY_BITS / 32) {
190 debug("RSA key words %u exceeds maximum %d\n", key->len,
191 RSA_MAX_KEY_BITS / 32);
192 return -EINVAL;
193 }
194
195 uint32_t val[key->len], acc[key->len], tmp[key->len];
196 uint32_t a_scaled[key->len];
197 result = tmp; /* Re-use location. */
198
199 /* Convert from big endian byte array to little endian word array. */
200 for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
201 val[i] = get_unaligned_be32(ptr);
202
203 if (0 != num_public_exponent_bits(key, &k))
204 return -EINVAL;
205
206 if (k < 2) {
207 debug("Public exponent is too short (%d bits, minimum 2)\n",
208 k);
209 return -EINVAL;
210 }
211
212 if (!is_public_exponent_bit_set(key, 0)) {
213 debug("LSB of RSA public exponent must be set.\n");
214 return -EINVAL;
215 }
216
217 /* the bit at e[k-1] is 1 by definition, so start with: C := M */
218 montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
219 /* retain scaled version for intermediate use */
220 memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
221
222 for (j = k - 2; j > 0; --j) {
223 montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
224
225 if (is_public_exponent_bit_set(key, j)) {
226 /* acc = tmp * val / R mod n */
227 montgomery_mul(key, acc, tmp, a_scaled);
228 } else {
229 /* e[j] == 0, copy tmp back to acc for next operation */
230 memcpy(acc, tmp, key->len * sizeof(acc[0]));
231 }
232 }
233
234 /* the bit at e[0] is always 1 */
235 montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
236 montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
237 memcpy(result, acc, key->len * sizeof(result[0]));
238
239 /* Make sure result < mod; result is at most 1x mod too large. */
240 if (greater_equal_modulus(key, result))
241 subtract_modulus(key, result);
242
243 /* Convert to bigendian byte array */
244 for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
245 put_unaligned_be32(result[i], ptr);
246 return 0;
247}
248
249static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
250{
251 int i;
252
253 for (i = 0; i < len; i++)
254 dst[i] = fdt32_to_cpu(src[len - 1 - i]);
255}
256
257int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
258 struct key_prop *prop, uint8_t *out)
259{
260 struct rsa_public_key key;
261 int ret;
262
263 if (!prop) {
264 debug("%s: Skipping invalid prop", __func__);
265 return -EBADF;
266 }
267 key.n0inv = prop->n0inv;
268 key.len = prop->num_bits;
269
270 if (!prop->public_exponent)
271 key.exponent = RSA_DEFAULT_PUBEXP;
272 else
Rasmus Villemoes3f8808e2020-10-06 12:09:45 +0200273 key.exponent = fdt64_to_cpup(prop->public_exponent);
Ruchika Guptafc2f4242015-01-23 16:01:50 +0530274
275 if (!key.len || !prop->modulus || !prop->rr) {
276 debug("%s: Missing RSA key info", __func__);
277 return -EFAULT;
278 }
279
280 /* Sanity check for stack size */
281 if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
282 debug("RSA key bits %u outside allowed range %d..%d\n",
283 key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
284 return -EFAULT;
285 }
286 key.len /= sizeof(uint32_t) * 8;
287 uint32_t key1[key.len], key2[key.len];
288
289 key.modulus = key1;
290 key.rr = key2;
291 rsa_convert_big_endian(key.modulus, (uint32_t *)prop->modulus, key.len);
292 rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len);
293 if (!key.modulus || !key.rr) {
294 debug("%s: Out of memory", __func__);
295 return -ENOMEM;
296 }
297
298 uint32_t buf[sig_len / sizeof(uint32_t)];
299
300 memcpy(buf, sig, sig_len);
301
302 ret = pow_mod(&key, buf);
303 if (ret)
304 return ret;
305
306 memcpy(out, buf, sig_len);
307
308 return 0;
309}
Siva Durga Prasad Paladugu37e3a362018-06-26 15:02:19 +0530310
311#if defined(CONFIG_CMD_ZYNQ_RSA)
312/**
313 * zynq_pow_mod - in-place public exponentiation
314 *
315 * @keyptr: RSA key
316 * @inout: Big-endian word array containing value and result
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100317 * Return: 0 on successful calculation, otherwise failure error code
Siva Durga Prasad Paladugu37e3a362018-06-26 15:02:19 +0530318 *
319 * FIXME: Use pow_mod() instead of zynq_pow_mod()
320 * pow_mod calculation required for zynq is bit different from
321 * pw_mod above here, hence defined zynq specific routine.
322 */
Michal Simekc2a2c832020-10-22 10:59:08 +0200323int zynq_pow_mod(uint32_t *keyptr, uint32_t *inout)
Siva Durga Prasad Paladugu37e3a362018-06-26 15:02:19 +0530324{
325 u32 *result, *ptr;
326 uint i;
327 struct rsa_public_key *key;
328 u32 val[RSA2048_BYTES], acc[RSA2048_BYTES], tmp[RSA2048_BYTES];
329
330 key = (struct rsa_public_key *)keyptr;
331
332 /* Sanity check for stack size - key->len is in 32-bit words */
333 if (key->len > RSA_MAX_KEY_BITS / 32) {
334 debug("RSA key words %u exceeds maximum %d\n", key->len,
335 RSA_MAX_KEY_BITS / 32);
336 return -EINVAL;
337 }
338
339 result = tmp; /* Re-use location. */
340
341 for (i = 0, ptr = inout; i < key->len; i++, ptr++)
342 val[i] = *(ptr);
343
344 montgomery_mul(key, acc, val, key->rr); /* axx = a * RR / R mod M */
345 for (i = 0; i < 16; i += 2) {
346 montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
347 montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
348 }
349 montgomery_mul(key, result, acc, val); /* result = XX * a / R mod M */
350
351 /* Make sure result < mod; result is at most 1x mod too large. */
352 if (greater_equal_modulus(key, result))
353 subtract_modulus(key, result);
354
355 for (i = 0, ptr = inout; i < key->len; i++, ptr++)
356 *ptr = result[i];
357
358 return 0;
359}
360#endif