1fc2f4246SRuchika Gupta /*
2fc2f4246SRuchika Gupta * Copyright (c) 2013, Google Inc.
3fc2f4246SRuchika Gupta *
4fc2f4246SRuchika Gupta * SPDX-License-Identifier: GPL-2.0+
5fc2f4246SRuchika Gupta */
6fc2f4246SRuchika Gupta
7fc2f4246SRuchika Gupta #ifndef USE_HOSTCC
8fc2f4246SRuchika Gupta #include <common.h>
9fc2f4246SRuchika Gupta #include <fdtdec.h>
10fc2f4246SRuchika Gupta #include <asm/types.h>
11fc2f4246SRuchika Gupta #include <asm/byteorder.h>
121221ce45SMasahiro Yamada #include <linux/errno.h>
13fc2f4246SRuchika Gupta #include <asm/types.h>
14fc2f4246SRuchika Gupta #include <asm/unaligned.h>
15fc2f4246SRuchika Gupta #else
16fc2f4246SRuchika Gupta #include "fdt_host.h"
17fc2f4246SRuchika Gupta #include "mkimage.h"
18fc2f4246SRuchika Gupta #include <fdt_support.h>
19fc2f4246SRuchika Gupta #endif
20fc2f4246SRuchika Gupta #include <u-boot/rsa.h>
21fc2f4246SRuchika Gupta #include <u-boot/rsa-mod-exp.h>
22fc2f4246SRuchika Gupta
23fc2f4246SRuchika Gupta #define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
24fc2f4246SRuchika Gupta
25fc2f4246SRuchika Gupta #define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
26fc2f4246SRuchika Gupta #define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
27fc2f4246SRuchika Gupta
28fc2f4246SRuchika Gupta /* Default public exponent for backward compatibility */
29fc2f4246SRuchika Gupta #define RSA_DEFAULT_PUBEXP 65537
30fc2f4246SRuchika Gupta
31fc2f4246SRuchika Gupta /**
32fc2f4246SRuchika Gupta * subtract_modulus() - subtract modulus from the given value
33fc2f4246SRuchika Gupta *
34fc2f4246SRuchika Gupta * @key: Key containing modulus to subtract
35fc2f4246SRuchika Gupta * @num: Number to subtract modulus from, as little endian word array
36fc2f4246SRuchika Gupta */
subtract_modulus(const struct rsa_public_key * key,uint32_t num[])37fc2f4246SRuchika Gupta static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
38fc2f4246SRuchika Gupta {
39fc2f4246SRuchika Gupta int64_t acc = 0;
40fc2f4246SRuchika Gupta uint i;
41fc2f4246SRuchika Gupta
42fc2f4246SRuchika Gupta for (i = 0; i < key->len; i++) {
43fc2f4246SRuchika Gupta acc += (uint64_t)num[i] - key->modulus[i];
44fc2f4246SRuchika Gupta num[i] = (uint32_t)acc;
45fc2f4246SRuchika Gupta acc >>= 32;
46fc2f4246SRuchika Gupta }
47fc2f4246SRuchika Gupta }
48fc2f4246SRuchika Gupta
49fc2f4246SRuchika Gupta /**
50fc2f4246SRuchika Gupta * greater_equal_modulus() - check if a value is >= modulus
51fc2f4246SRuchika Gupta *
52fc2f4246SRuchika Gupta * @key: Key containing modulus to check
53fc2f4246SRuchika Gupta * @num: Number to check against modulus, as little endian word array
54fc2f4246SRuchika Gupta * @return 0 if num < modulus, 1 if num >= modulus
55fc2f4246SRuchika Gupta */
greater_equal_modulus(const struct rsa_public_key * key,uint32_t num[])56fc2f4246SRuchika Gupta static int greater_equal_modulus(const struct rsa_public_key *key,
57fc2f4246SRuchika Gupta uint32_t num[])
58fc2f4246SRuchika Gupta {
59fc2f4246SRuchika Gupta int i;
60fc2f4246SRuchika Gupta
61fc2f4246SRuchika Gupta for (i = (int)key->len - 1; i >= 0; i--) {
62fc2f4246SRuchika Gupta if (num[i] < key->modulus[i])
63fc2f4246SRuchika Gupta return 0;
64fc2f4246SRuchika Gupta if (num[i] > key->modulus[i])
65fc2f4246SRuchika Gupta return 1;
66fc2f4246SRuchika Gupta }
67fc2f4246SRuchika Gupta
68fc2f4246SRuchika Gupta return 1; /* equal */
69fc2f4246SRuchika Gupta }
70fc2f4246SRuchika Gupta
71fc2f4246SRuchika Gupta /**
72fc2f4246SRuchika Gupta * montgomery_mul_add_step() - Perform montgomery multiply-add step
73fc2f4246SRuchika Gupta *
74fc2f4246SRuchika Gupta * Operation: montgomery result[] += a * b[] / n0inv % modulus
75fc2f4246SRuchika Gupta *
76fc2f4246SRuchika Gupta * @key: RSA key
77fc2f4246SRuchika Gupta * @result: Place to put result, as little endian word array
78fc2f4246SRuchika Gupta * @a: Multiplier
79fc2f4246SRuchika Gupta * @b: Multiplicand, as little endian word array
80fc2f4246SRuchika Gupta */
montgomery_mul_add_step(const struct rsa_public_key * key,uint32_t result[],const uint32_t a,const uint32_t b[])81fc2f4246SRuchika Gupta static void montgomery_mul_add_step(const struct rsa_public_key *key,
82fc2f4246SRuchika Gupta uint32_t result[], const uint32_t a, const uint32_t b[])
83fc2f4246SRuchika Gupta {
84fc2f4246SRuchika Gupta uint64_t acc_a, acc_b;
85fc2f4246SRuchika Gupta uint32_t d0;
86fc2f4246SRuchika Gupta uint i;
87fc2f4246SRuchika Gupta
88fc2f4246SRuchika Gupta acc_a = (uint64_t)a * b[0] + result[0];
89fc2f4246SRuchika Gupta d0 = (uint32_t)acc_a * key->n0inv;
90fc2f4246SRuchika Gupta acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
91fc2f4246SRuchika Gupta for (i = 1; i < key->len; i++) {
92fc2f4246SRuchika Gupta acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
93fc2f4246SRuchika Gupta acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
94fc2f4246SRuchika Gupta (uint32_t)acc_a;
95fc2f4246SRuchika Gupta result[i - 1] = (uint32_t)acc_b;
96fc2f4246SRuchika Gupta }
97fc2f4246SRuchika Gupta
98fc2f4246SRuchika Gupta acc_a = (acc_a >> 32) + (acc_b >> 32);
99fc2f4246SRuchika Gupta
100fc2f4246SRuchika Gupta result[i - 1] = (uint32_t)acc_a;
101fc2f4246SRuchika Gupta
102fc2f4246SRuchika Gupta if (acc_a >> 32)
103fc2f4246SRuchika Gupta subtract_modulus(key, result);
104fc2f4246SRuchika Gupta }
105fc2f4246SRuchika Gupta
106fc2f4246SRuchika Gupta /**
107fc2f4246SRuchika Gupta * montgomery_mul() - Perform montgomery mutitply
108fc2f4246SRuchika Gupta *
109fc2f4246SRuchika Gupta * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
110fc2f4246SRuchika Gupta *
111fc2f4246SRuchika Gupta * @key: RSA key
112fc2f4246SRuchika Gupta * @result: Place to put result, as little endian word array
113fc2f4246SRuchika Gupta * @a: Multiplier, as little endian word array
114fc2f4246SRuchika Gupta * @b: Multiplicand, as little endian word array
115fc2f4246SRuchika Gupta */
montgomery_mul(const struct rsa_public_key * key,uint32_t result[],uint32_t a[],const uint32_t b[])116fc2f4246SRuchika Gupta static void montgomery_mul(const struct rsa_public_key *key,
117fc2f4246SRuchika Gupta uint32_t result[], uint32_t a[], const uint32_t b[])
118fc2f4246SRuchika Gupta {
119fc2f4246SRuchika Gupta uint i;
120fc2f4246SRuchika Gupta
121fc2f4246SRuchika Gupta for (i = 0; i < key->len; ++i)
122fc2f4246SRuchika Gupta result[i] = 0;
123fc2f4246SRuchika Gupta for (i = 0; i < key->len; ++i)
124fc2f4246SRuchika Gupta montgomery_mul_add_step(key, result, a[i], b);
125fc2f4246SRuchika Gupta }
126fc2f4246SRuchika Gupta
127fc2f4246SRuchika Gupta /**
128fc2f4246SRuchika Gupta * num_pub_exponent_bits() - Number of bits in the public exponent
129fc2f4246SRuchika Gupta *
130fc2f4246SRuchika Gupta * @key: RSA key
131fc2f4246SRuchika Gupta * @num_bits: Storage for the number of public exponent bits
132fc2f4246SRuchika Gupta */
num_public_exponent_bits(const struct rsa_public_key * key,int * num_bits)133fc2f4246SRuchika Gupta static int num_public_exponent_bits(const struct rsa_public_key *key,
134fc2f4246SRuchika Gupta int *num_bits)
135fc2f4246SRuchika Gupta {
136fc2f4246SRuchika Gupta uint64_t exponent;
137fc2f4246SRuchika Gupta int exponent_bits;
138fc2f4246SRuchika Gupta const uint max_bits = (sizeof(exponent) * 8);
139fc2f4246SRuchika Gupta
140fc2f4246SRuchika Gupta exponent = key->exponent;
141fc2f4246SRuchika Gupta exponent_bits = 0;
142fc2f4246SRuchika Gupta
143fc2f4246SRuchika Gupta if (!exponent) {
144fc2f4246SRuchika Gupta *num_bits = exponent_bits;
145fc2f4246SRuchika Gupta return 0;
146fc2f4246SRuchika Gupta }
147fc2f4246SRuchika Gupta
148fc2f4246SRuchika Gupta for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
149fc2f4246SRuchika Gupta if (!(exponent >>= 1)) {
150fc2f4246SRuchika Gupta *num_bits = exponent_bits;
151fc2f4246SRuchika Gupta return 0;
152fc2f4246SRuchika Gupta }
153fc2f4246SRuchika Gupta
154fc2f4246SRuchika Gupta return -EINVAL;
155fc2f4246SRuchika Gupta }
156fc2f4246SRuchika Gupta
157fc2f4246SRuchika Gupta /**
158fc2f4246SRuchika Gupta * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
159fc2f4246SRuchika Gupta *
160fc2f4246SRuchika Gupta * @key: RSA key
161fc2f4246SRuchika Gupta * @pos: The bit position to check
162fc2f4246SRuchika Gupta */
is_public_exponent_bit_set(const struct rsa_public_key * key,int pos)163fc2f4246SRuchika Gupta static int is_public_exponent_bit_set(const struct rsa_public_key *key,
164fc2f4246SRuchika Gupta int pos)
165fc2f4246SRuchika Gupta {
166fc2f4246SRuchika Gupta return key->exponent & (1ULL << pos);
167fc2f4246SRuchika Gupta }
168fc2f4246SRuchika Gupta
169fc2f4246SRuchika Gupta /**
170fc2f4246SRuchika Gupta * pow_mod() - in-place public exponentiation
171fc2f4246SRuchika Gupta *
172fc2f4246SRuchika Gupta * @key: RSA key
173fc2f4246SRuchika Gupta * @inout: Big-endian word array containing value and result
174fc2f4246SRuchika Gupta */
pow_mod(const struct rsa_public_key * key,uint32_t * inout)175fc2f4246SRuchika Gupta static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
176fc2f4246SRuchika Gupta {
177fc2f4246SRuchika Gupta uint32_t *result, *ptr;
178fc2f4246SRuchika Gupta uint i;
179fc2f4246SRuchika Gupta int j, k;
180fc2f4246SRuchika Gupta
181fc2f4246SRuchika Gupta /* Sanity check for stack size - key->len is in 32-bit words */
182fc2f4246SRuchika Gupta if (key->len > RSA_MAX_KEY_BITS / 32) {
183fc2f4246SRuchika Gupta debug("RSA key words %u exceeds maximum %d\n", key->len,
184fc2f4246SRuchika Gupta RSA_MAX_KEY_BITS / 32);
185fc2f4246SRuchika Gupta return -EINVAL;
186fc2f4246SRuchika Gupta }
187fc2f4246SRuchika Gupta
188fc2f4246SRuchika Gupta uint32_t val[key->len], acc[key->len], tmp[key->len];
189fc2f4246SRuchika Gupta uint32_t a_scaled[key->len];
190fc2f4246SRuchika Gupta result = tmp; /* Re-use location. */
191fc2f4246SRuchika Gupta
192fc2f4246SRuchika Gupta /* Convert from big endian byte array to little endian word array. */
193fc2f4246SRuchika Gupta for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
194fc2f4246SRuchika Gupta val[i] = get_unaligned_be32(ptr);
195fc2f4246SRuchika Gupta
196fc2f4246SRuchika Gupta if (0 != num_public_exponent_bits(key, &k))
197fc2f4246SRuchika Gupta return -EINVAL;
198fc2f4246SRuchika Gupta
199fc2f4246SRuchika Gupta if (k < 2) {
200fc2f4246SRuchika Gupta debug("Public exponent is too short (%d bits, minimum 2)\n",
201fc2f4246SRuchika Gupta k);
202fc2f4246SRuchika Gupta return -EINVAL;
203fc2f4246SRuchika Gupta }
204fc2f4246SRuchika Gupta
205fc2f4246SRuchika Gupta if (!is_public_exponent_bit_set(key, 0)) {
206fc2f4246SRuchika Gupta debug("LSB of RSA public exponent must be set.\n");
207fc2f4246SRuchika Gupta return -EINVAL;
208fc2f4246SRuchika Gupta }
209fc2f4246SRuchika Gupta
210fc2f4246SRuchika Gupta /* the bit at e[k-1] is 1 by definition, so start with: C := M */
211fc2f4246SRuchika Gupta montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
212fc2f4246SRuchika Gupta /* retain scaled version for intermediate use */
213fc2f4246SRuchika Gupta memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
214fc2f4246SRuchika Gupta
215fc2f4246SRuchika Gupta for (j = k - 2; j > 0; --j) {
216fc2f4246SRuchika Gupta montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
217fc2f4246SRuchika Gupta
218fc2f4246SRuchika Gupta if (is_public_exponent_bit_set(key, j)) {
219fc2f4246SRuchika Gupta /* acc = tmp * val / R mod n */
220fc2f4246SRuchika Gupta montgomery_mul(key, acc, tmp, a_scaled);
221fc2f4246SRuchika Gupta } else {
222fc2f4246SRuchika Gupta /* e[j] == 0, copy tmp back to acc for next operation */
223fc2f4246SRuchika Gupta memcpy(acc, tmp, key->len * sizeof(acc[0]));
224fc2f4246SRuchika Gupta }
225fc2f4246SRuchika Gupta }
226fc2f4246SRuchika Gupta
227fc2f4246SRuchika Gupta /* the bit at e[0] is always 1 */
228fc2f4246SRuchika Gupta montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
229fc2f4246SRuchika Gupta montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
230fc2f4246SRuchika Gupta memcpy(result, acc, key->len * sizeof(result[0]));
231fc2f4246SRuchika Gupta
232fc2f4246SRuchika Gupta /* Make sure result < mod; result is at most 1x mod too large. */
233fc2f4246SRuchika Gupta if (greater_equal_modulus(key, result))
234fc2f4246SRuchika Gupta subtract_modulus(key, result);
235fc2f4246SRuchika Gupta
236fc2f4246SRuchika Gupta /* Convert to bigendian byte array */
237fc2f4246SRuchika Gupta for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
238fc2f4246SRuchika Gupta put_unaligned_be32(result[i], ptr);
239fc2f4246SRuchika Gupta return 0;
240fc2f4246SRuchika Gupta }
241fc2f4246SRuchika Gupta
rsa_convert_big_endian(uint32_t * dst,const uint32_t * src,int len)242fc2f4246SRuchika Gupta static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
243fc2f4246SRuchika Gupta {
244fc2f4246SRuchika Gupta int i;
245fc2f4246SRuchika Gupta
246fc2f4246SRuchika Gupta for (i = 0; i < len; i++)
247fc2f4246SRuchika Gupta dst[i] = fdt32_to_cpu(src[len - 1 - i]);
248fc2f4246SRuchika Gupta }
249fc2f4246SRuchika Gupta
rsa_mod_exp_sw(const uint8_t * sig,uint32_t sig_len,struct key_prop * prop,uint8_t * out)250fc2f4246SRuchika Gupta int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
251fc2f4246SRuchika Gupta struct key_prop *prop, uint8_t *out)
252fc2f4246SRuchika Gupta {
253*a8f564c3SJoseph Chen #ifndef USE_HOSTCC
254*a8f564c3SJoseph Chen __cacheline_aligned uint64_t tmp;
255*a8f564c3SJoseph Chen #else
256*a8f564c3SJoseph Chen uint64_t tmp;
257*a8f564c3SJoseph Chen #endif
258fc2f4246SRuchika Gupta struct rsa_public_key key;
259fc2f4246SRuchika Gupta int ret;
260fc2f4246SRuchika Gupta
261fc2f4246SRuchika Gupta if (!prop) {
262fc2f4246SRuchika Gupta debug("%s: Skipping invalid prop", __func__);
263fc2f4246SRuchika Gupta return -EBADF;
264fc2f4246SRuchika Gupta }
265fc2f4246SRuchika Gupta key.n0inv = prop->n0inv;
266fc2f4246SRuchika Gupta key.len = prop->num_bits;
267fc2f4246SRuchika Gupta
268*a8f564c3SJoseph Chen if (!prop->public_exponent) {
269fc2f4246SRuchika Gupta key.exponent = RSA_DEFAULT_PUBEXP;
270*a8f564c3SJoseph Chen } else {
271*a8f564c3SJoseph Chen /*
272*a8f564c3SJoseph Chen * it seems fdt64_to_cpu() input param address must be 8-bytes
273*a8f564c3SJoseph Chen * align, otherwise it brings a data-abort. No root cause was
274*a8f564c3SJoseph Chen * found.
275*a8f564c3SJoseph Chen *
276*a8f564c3SJoseph Chen * workaround it this a tmp value.
277*a8f564c3SJoseph Chen */
278*a8f564c3SJoseph Chen memcpy((void *)&tmp, prop->public_exponent, sizeof(uint64_t));
279*a8f564c3SJoseph Chen key.exponent = fdt64_to_cpu(tmp);
280*a8f564c3SJoseph Chen }
281fc2f4246SRuchika Gupta
282fc2f4246SRuchika Gupta if (!key.len || !prop->modulus || !prop->rr) {
283fc2f4246SRuchika Gupta debug("%s: Missing RSA key info", __func__);
284fc2f4246SRuchika Gupta return -EFAULT;
285fc2f4246SRuchika Gupta }
286fc2f4246SRuchika Gupta
287fc2f4246SRuchika Gupta /* Sanity check for stack size */
288fc2f4246SRuchika Gupta if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
289fc2f4246SRuchika Gupta debug("RSA key bits %u outside allowed range %d..%d\n",
290fc2f4246SRuchika Gupta key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
291fc2f4246SRuchika Gupta return -EFAULT;
292fc2f4246SRuchika Gupta }
293fc2f4246SRuchika Gupta key.len /= sizeof(uint32_t) * 8;
294fc2f4246SRuchika Gupta uint32_t key1[key.len], key2[key.len];
295fc2f4246SRuchika Gupta
296fc2f4246SRuchika Gupta key.modulus = key1;
297fc2f4246SRuchika Gupta key.rr = key2;
298fc2f4246SRuchika Gupta rsa_convert_big_endian(key.modulus, (uint32_t *)prop->modulus, key.len);
299fc2f4246SRuchika Gupta rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len);
300fc2f4246SRuchika Gupta if (!key.modulus || !key.rr) {
301fc2f4246SRuchika Gupta debug("%s: Out of memory", __func__);
302fc2f4246SRuchika Gupta return -ENOMEM;
303fc2f4246SRuchika Gupta }
304fc2f4246SRuchika Gupta
305fc2f4246SRuchika Gupta uint32_t buf[sig_len / sizeof(uint32_t)];
306fc2f4246SRuchika Gupta
307fc2f4246SRuchika Gupta memcpy(buf, sig, sig_len);
308fc2f4246SRuchika Gupta
309fc2f4246SRuchika Gupta ret = pow_mod(&key, buf);
310fc2f4246SRuchika Gupta if (ret)
311fc2f4246SRuchika Gupta return ret;
312fc2f4246SRuchika Gupta
313fc2f4246SRuchika Gupta memcpy(out, buf, sig_len);
314fc2f4246SRuchika Gupta
315fc2f4246SRuchika Gupta return 0;
316fc2f4246SRuchika Gupta }
317