xref: /rk3399_rockchip-uboot/lib/rsa/rsa-verify.c (revision e0f2f15534146729fdf2ce58b740121fd67eea1c)
119c402afSSimon Glass /*
219c402afSSimon Glass  * Copyright (c) 2013, Google Inc.
319c402afSSimon Glass  *
41a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
519c402afSSimon Glass  */
619c402afSSimon Glass 
729a23f9dSHeiko Schocher #ifndef USE_HOSTCC
819c402afSSimon Glass #include <common.h>
919c402afSSimon Glass #include <fdtdec.h>
1029a23f9dSHeiko Schocher #include <asm/types.h>
1129a23f9dSHeiko Schocher #include <asm/byteorder.h>
1229a23f9dSHeiko Schocher #include <asm/errno.h>
1329a23f9dSHeiko Schocher #include <asm/types.h>
1429a23f9dSHeiko Schocher #include <asm/unaligned.h>
1529a23f9dSHeiko Schocher #else
1629a23f9dSHeiko Schocher #include "fdt_host.h"
1729a23f9dSHeiko Schocher #include "mkimage.h"
1829a23f9dSHeiko Schocher #include <fdt_support.h>
1929a23f9dSHeiko Schocher #endif
202b9912e6SJeroen Hofstee #include <u-boot/rsa.h>
212b9912e6SJeroen Hofstee #include <u-boot/sha1.h>
222b9912e6SJeroen Hofstee #include <u-boot/sha256.h>
2319c402afSSimon Glass 
2419c402afSSimon Glass #define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
2519c402afSSimon Glass 
2629a23f9dSHeiko Schocher #define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
2729a23f9dSHeiko Schocher #define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
2829a23f9dSHeiko Schocher 
29*e0f2f155SMichael van der Westhuizen /* Default public exponent for backward compatibility */
30*e0f2f155SMichael van der Westhuizen #define RSA_DEFAULT_PUBEXP	65537
31*e0f2f155SMichael van der Westhuizen 
3219c402afSSimon Glass /**
3319c402afSSimon Glass  * subtract_modulus() - subtract modulus from the given value
3419c402afSSimon Glass  *
3519c402afSSimon Glass  * @key:	Key containing modulus to subtract
3619c402afSSimon Glass  * @num:	Number to subtract modulus from, as little endian word array
3719c402afSSimon Glass  */
3819c402afSSimon Glass static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
3919c402afSSimon Glass {
4019c402afSSimon Glass 	int64_t acc = 0;
4119c402afSSimon Glass 	uint i;
4219c402afSSimon Glass 
4319c402afSSimon Glass 	for (i = 0; i < key->len; i++) {
4419c402afSSimon Glass 		acc += (uint64_t)num[i] - key->modulus[i];
4519c402afSSimon Glass 		num[i] = (uint32_t)acc;
4619c402afSSimon Glass 		acc >>= 32;
4719c402afSSimon Glass 	}
4819c402afSSimon Glass }
4919c402afSSimon Glass 
5019c402afSSimon Glass /**
5119c402afSSimon Glass  * greater_equal_modulus() - check if a value is >= modulus
5219c402afSSimon Glass  *
5319c402afSSimon Glass  * @key:	Key containing modulus to check
5419c402afSSimon Glass  * @num:	Number to check against modulus, as little endian word array
5519c402afSSimon Glass  * @return 0 if num < modulus, 1 if num >= modulus
5619c402afSSimon Glass  */
5719c402afSSimon Glass static int greater_equal_modulus(const struct rsa_public_key *key,
5819c402afSSimon Glass 				 uint32_t num[])
5919c402afSSimon Glass {
6019c402afSSimon Glass 	uint32_t i;
6119c402afSSimon Glass 
6219c402afSSimon Glass 	for (i = key->len - 1; i >= 0; i--) {
6319c402afSSimon Glass 		if (num[i] < key->modulus[i])
6419c402afSSimon Glass 			return 0;
6519c402afSSimon Glass 		if (num[i] > key->modulus[i])
6619c402afSSimon Glass 			return 1;
6719c402afSSimon Glass 	}
6819c402afSSimon Glass 
6919c402afSSimon Glass 	return 1;  /* equal */
7019c402afSSimon Glass }
7119c402afSSimon Glass 
7219c402afSSimon Glass /**
7319c402afSSimon Glass  * montgomery_mul_add_step() - Perform montgomery multiply-add step
7419c402afSSimon Glass  *
7519c402afSSimon Glass  * Operation: montgomery result[] += a * b[] / n0inv % modulus
7619c402afSSimon Glass  *
7719c402afSSimon Glass  * @key:	RSA key
7819c402afSSimon Glass  * @result:	Place to put result, as little endian word array
7919c402afSSimon Glass  * @a:		Multiplier
8019c402afSSimon Glass  * @b:		Multiplicand, as little endian word array
8119c402afSSimon Glass  */
8219c402afSSimon Glass static void montgomery_mul_add_step(const struct rsa_public_key *key,
8319c402afSSimon Glass 		uint32_t result[], const uint32_t a, const uint32_t b[])
8419c402afSSimon Glass {
8519c402afSSimon Glass 	uint64_t acc_a, acc_b;
8619c402afSSimon Glass 	uint32_t d0;
8719c402afSSimon Glass 	uint i;
8819c402afSSimon Glass 
8919c402afSSimon Glass 	acc_a = (uint64_t)a * b[0] + result[0];
9019c402afSSimon Glass 	d0 = (uint32_t)acc_a * key->n0inv;
9119c402afSSimon Glass 	acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
9219c402afSSimon Glass 	for (i = 1; i < key->len; i++) {
9319c402afSSimon Glass 		acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
9419c402afSSimon Glass 		acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
9519c402afSSimon Glass 				(uint32_t)acc_a;
9619c402afSSimon Glass 		result[i - 1] = (uint32_t)acc_b;
9719c402afSSimon Glass 	}
9819c402afSSimon Glass 
9919c402afSSimon Glass 	acc_a = (acc_a >> 32) + (acc_b >> 32);
10019c402afSSimon Glass 
10119c402afSSimon Glass 	result[i - 1] = (uint32_t)acc_a;
10219c402afSSimon Glass 
10319c402afSSimon Glass 	if (acc_a >> 32)
10419c402afSSimon Glass 		subtract_modulus(key, result);
10519c402afSSimon Glass }
10619c402afSSimon Glass 
10719c402afSSimon Glass /**
10819c402afSSimon Glass  * montgomery_mul() - Perform montgomery mutitply
10919c402afSSimon Glass  *
11019c402afSSimon Glass  * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
11119c402afSSimon Glass  *
11219c402afSSimon Glass  * @key:	RSA key
11319c402afSSimon Glass  * @result:	Place to put result, as little endian word array
11419c402afSSimon Glass  * @a:		Multiplier, as little endian word array
11519c402afSSimon Glass  * @b:		Multiplicand, as little endian word array
11619c402afSSimon Glass  */
11719c402afSSimon Glass static void montgomery_mul(const struct rsa_public_key *key,
11819c402afSSimon Glass 		uint32_t result[], uint32_t a[], const uint32_t b[])
11919c402afSSimon Glass {
12019c402afSSimon Glass 	uint i;
12119c402afSSimon Glass 
12219c402afSSimon Glass 	for (i = 0; i < key->len; ++i)
12319c402afSSimon Glass 		result[i] = 0;
12419c402afSSimon Glass 	for (i = 0; i < key->len; ++i)
12519c402afSSimon Glass 		montgomery_mul_add_step(key, result, a[i], b);
12619c402afSSimon Glass }
12719c402afSSimon Glass 
12819c402afSSimon Glass /**
129*e0f2f155SMichael van der Westhuizen  * num_pub_exponent_bits() - Number of bits in the public exponent
130*e0f2f155SMichael van der Westhuizen  *
131*e0f2f155SMichael van der Westhuizen  * @key:	RSA key
132*e0f2f155SMichael van der Westhuizen  * @num_bits:	Storage for the number of public exponent bits
133*e0f2f155SMichael van der Westhuizen  */
134*e0f2f155SMichael van der Westhuizen static int num_public_exponent_bits(const struct rsa_public_key *key,
135*e0f2f155SMichael van der Westhuizen 		int *num_bits)
136*e0f2f155SMichael van der Westhuizen {
137*e0f2f155SMichael van der Westhuizen 	uint64_t exponent;
138*e0f2f155SMichael van der Westhuizen 	int exponent_bits;
139*e0f2f155SMichael van der Westhuizen 	const uint max_bits = (sizeof(exponent) * 8);
140*e0f2f155SMichael van der Westhuizen 
141*e0f2f155SMichael van der Westhuizen 	exponent = key->exponent;
142*e0f2f155SMichael van der Westhuizen 	exponent_bits = 0;
143*e0f2f155SMichael van der Westhuizen 
144*e0f2f155SMichael van der Westhuizen 	if (!exponent) {
145*e0f2f155SMichael van der Westhuizen 		*num_bits = exponent_bits;
146*e0f2f155SMichael van der Westhuizen 		return 0;
147*e0f2f155SMichael van der Westhuizen 	}
148*e0f2f155SMichael van der Westhuizen 
149*e0f2f155SMichael van der Westhuizen 	for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
150*e0f2f155SMichael van der Westhuizen 		if (!(exponent >>= 1)) {
151*e0f2f155SMichael van der Westhuizen 			*num_bits = exponent_bits;
152*e0f2f155SMichael van der Westhuizen 			return 0;
153*e0f2f155SMichael van der Westhuizen 		}
154*e0f2f155SMichael van der Westhuizen 
155*e0f2f155SMichael van der Westhuizen 	return -EINVAL;
156*e0f2f155SMichael van der Westhuizen }
157*e0f2f155SMichael van der Westhuizen 
158*e0f2f155SMichael van der Westhuizen /**
159*e0f2f155SMichael van der Westhuizen  * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
160*e0f2f155SMichael van der Westhuizen  *
161*e0f2f155SMichael van der Westhuizen  * @key:	RSA key
162*e0f2f155SMichael van der Westhuizen  * @pos:	The bit position to check
163*e0f2f155SMichael van der Westhuizen  */
164*e0f2f155SMichael van der Westhuizen static int is_public_exponent_bit_set(const struct rsa_public_key *key,
165*e0f2f155SMichael van der Westhuizen 		int pos)
166*e0f2f155SMichael van der Westhuizen {
167*e0f2f155SMichael van der Westhuizen 	return key->exponent & (1ULL << pos);
168*e0f2f155SMichael van der Westhuizen }
169*e0f2f155SMichael van der Westhuizen 
170*e0f2f155SMichael van der Westhuizen /**
17119c402afSSimon Glass  * pow_mod() - in-place public exponentiation
17219c402afSSimon Glass  *
17319c402afSSimon Glass  * @key:	RSA key
17419c402afSSimon Glass  * @inout:	Big-endian word array containing value and result
17519c402afSSimon Glass  */
17619c402afSSimon Glass static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
17719c402afSSimon Glass {
17819c402afSSimon Glass 	uint32_t *result, *ptr;
17919c402afSSimon Glass 	uint i;
180*e0f2f155SMichael van der Westhuizen 	int j, k;
18119c402afSSimon Glass 
18219c402afSSimon Glass 	/* Sanity check for stack size - key->len is in 32-bit words */
18319c402afSSimon Glass 	if (key->len > RSA_MAX_KEY_BITS / 32) {
18419c402afSSimon Glass 		debug("RSA key words %u exceeds maximum %d\n", key->len,
18519c402afSSimon Glass 		      RSA_MAX_KEY_BITS / 32);
18619c402afSSimon Glass 		return -EINVAL;
18719c402afSSimon Glass 	}
18819c402afSSimon Glass 
18919c402afSSimon Glass 	uint32_t val[key->len], acc[key->len], tmp[key->len];
190*e0f2f155SMichael van der Westhuizen 	uint32_t a_scaled[key->len];
19119c402afSSimon Glass 	result = tmp;  /* Re-use location. */
19219c402afSSimon Glass 
19319c402afSSimon Glass 	/* Convert from big endian byte array to little endian word array. */
19419c402afSSimon Glass 	for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
19519c402afSSimon Glass 		val[i] = get_unaligned_be32(ptr);
19619c402afSSimon Glass 
197*e0f2f155SMichael van der Westhuizen 	if (0 != num_public_exponent_bits(key, &k))
198*e0f2f155SMichael van der Westhuizen 		return -EINVAL;
199*e0f2f155SMichael van der Westhuizen 
200*e0f2f155SMichael van der Westhuizen 	if (k < 2) {
201*e0f2f155SMichael van der Westhuizen 		debug("Public exponent is too short (%d bits, minimum 2)\n",
202*e0f2f155SMichael van der Westhuizen 		      k);
203*e0f2f155SMichael van der Westhuizen 		return -EINVAL;
20419c402afSSimon Glass 	}
205*e0f2f155SMichael van der Westhuizen 
206*e0f2f155SMichael van der Westhuizen 	if (!is_public_exponent_bit_set(key, 0)) {
207*e0f2f155SMichael van der Westhuizen 		debug("LSB of RSA public exponent must be set.\n");
208*e0f2f155SMichael van der Westhuizen 		return -EINVAL;
209*e0f2f155SMichael van der Westhuizen 	}
210*e0f2f155SMichael van der Westhuizen 
211*e0f2f155SMichael van der Westhuizen 	/* the bit at e[k-1] is 1 by definition, so start with: C := M */
212*e0f2f155SMichael van der Westhuizen 	montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
213*e0f2f155SMichael van der Westhuizen 	/* retain scaled version for intermediate use */
214*e0f2f155SMichael van der Westhuizen 	memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
215*e0f2f155SMichael van der Westhuizen 
216*e0f2f155SMichael van der Westhuizen 	for (j = k - 2; j > 0; --j) {
217*e0f2f155SMichael van der Westhuizen 		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
218*e0f2f155SMichael van der Westhuizen 
219*e0f2f155SMichael van der Westhuizen 		if (is_public_exponent_bit_set(key, j)) {
220*e0f2f155SMichael van der Westhuizen 			/* acc = tmp * val / R mod n */
221*e0f2f155SMichael van der Westhuizen 			montgomery_mul(key, acc, tmp, a_scaled);
222*e0f2f155SMichael van der Westhuizen 		} else {
223*e0f2f155SMichael van der Westhuizen 			/* e[j] == 0, copy tmp back to acc for next operation */
224*e0f2f155SMichael van der Westhuizen 			memcpy(acc, tmp, key->len * sizeof(acc[0]));
225*e0f2f155SMichael van der Westhuizen 		}
226*e0f2f155SMichael van der Westhuizen 	}
227*e0f2f155SMichael van der Westhuizen 
228*e0f2f155SMichael van der Westhuizen 	/* the bit at e[0] is always 1 */
229*e0f2f155SMichael van der Westhuizen 	montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
230*e0f2f155SMichael van der Westhuizen 	montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
231*e0f2f155SMichael van der Westhuizen 	memcpy(result, acc, key->len * sizeof(result[0]));
23219c402afSSimon Glass 
23319c402afSSimon Glass 	/* Make sure result < mod; result is at most 1x mod too large. */
23419c402afSSimon Glass 	if (greater_equal_modulus(key, result))
23519c402afSSimon Glass 		subtract_modulus(key, result);
23619c402afSSimon Glass 
23719c402afSSimon Glass 	/* Convert to bigendian byte array */
23819c402afSSimon Glass 	for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
23919c402afSSimon Glass 		put_unaligned_be32(result[i], ptr);
24019c402afSSimon Glass 	return 0;
24119c402afSSimon Glass }
24219c402afSSimon Glass 
24319c402afSSimon Glass static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
244646257d1SHeiko Schocher 			  const uint32_t sig_len, const uint8_t *hash,
245646257d1SHeiko Schocher 			  struct checksum_algo *algo)
24619c402afSSimon Glass {
24719c402afSSimon Glass 	const uint8_t *padding;
24819c402afSSimon Glass 	int pad_len;
24919c402afSSimon Glass 	int ret;
25019c402afSSimon Glass 
251646257d1SHeiko Schocher 	if (!key || !sig || !hash || !algo)
25219c402afSSimon Glass 		return -EIO;
25319c402afSSimon Glass 
25419c402afSSimon Glass 	if (sig_len != (key->len * sizeof(uint32_t))) {
25519c402afSSimon Glass 		debug("Signature is of incorrect length %d\n", sig_len);
25619c402afSSimon Glass 		return -EINVAL;
25719c402afSSimon Glass 	}
25819c402afSSimon Glass 
259646257d1SHeiko Schocher 	debug("Checksum algorithm: %s", algo->name);
260646257d1SHeiko Schocher 
26119c402afSSimon Glass 	/* Sanity check for stack size */
26219c402afSSimon Glass 	if (sig_len > RSA_MAX_SIG_BITS / 8) {
26319c402afSSimon Glass 		debug("Signature length %u exceeds maximum %d\n", sig_len,
26419c402afSSimon Glass 		      RSA_MAX_SIG_BITS / 8);
26519c402afSSimon Glass 		return -EINVAL;
26619c402afSSimon Glass 	}
26719c402afSSimon Glass 
26819c402afSSimon Glass 	uint32_t buf[sig_len / sizeof(uint32_t)];
26919c402afSSimon Glass 
27019c402afSSimon Glass 	memcpy(buf, sig, sig_len);
27119c402afSSimon Glass 
27219c402afSSimon Glass 	ret = pow_mod(key, buf);
27319c402afSSimon Glass 	if (ret)
27419c402afSSimon Glass 		return ret;
27519c402afSSimon Glass 
276646257d1SHeiko Schocher 	padding = algo->rsa_padding;
277db1b5f3dSHeiko Schocher 	pad_len = algo->pad_len - algo->checksum_len;
27819c402afSSimon Glass 
27919c402afSSimon Glass 	/* Check pkcs1.5 padding bytes. */
28019c402afSSimon Glass 	if (memcmp(buf, padding, pad_len)) {
28119c402afSSimon Glass 		debug("In RSAVerify(): Padding check failed!\n");
28219c402afSSimon Glass 		return -EINVAL;
28319c402afSSimon Glass 	}
28419c402afSSimon Glass 
28519c402afSSimon Glass 	/* Check hash. */
28619c402afSSimon Glass 	if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
28719c402afSSimon Glass 		debug("In RSAVerify(): Hash check failed!\n");
28819c402afSSimon Glass 		return -EACCES;
28919c402afSSimon Glass 	}
29019c402afSSimon Glass 
29119c402afSSimon Glass 	return 0;
29219c402afSSimon Glass }
29319c402afSSimon Glass 
29419c402afSSimon Glass static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
29519c402afSSimon Glass {
29619c402afSSimon Glass 	int i;
29719c402afSSimon Glass 
29819c402afSSimon Glass 	for (i = 0; i < len; i++)
29919c402afSSimon Glass 		dst[i] = fdt32_to_cpu(src[len - 1 - i]);
30019c402afSSimon Glass }
30119c402afSSimon Glass 
30219c402afSSimon Glass static int rsa_verify_with_keynode(struct image_sign_info *info,
30319c402afSSimon Glass 		const void *hash, uint8_t *sig, uint sig_len, int node)
30419c402afSSimon Glass {
30519c402afSSimon Glass 	const void *blob = info->fdt_blob;
30619c402afSSimon Glass 	struct rsa_public_key key;
30719c402afSSimon Glass 	const void *modulus, *rr;
308*e0f2f155SMichael van der Westhuizen 	const uint64_t *public_exponent;
309*e0f2f155SMichael van der Westhuizen 	int length;
31019c402afSSimon Glass 	int ret;
31119c402afSSimon Glass 
31219c402afSSimon Glass 	if (node < 0) {
31319c402afSSimon Glass 		debug("%s: Skipping invalid node", __func__);
31419c402afSSimon Glass 		return -EBADF;
31519c402afSSimon Glass 	}
31619c402afSSimon Glass 	if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) {
31719c402afSSimon Glass 		debug("%s: Missing rsa,n0-inverse", __func__);
31819c402afSSimon Glass 		return -EFAULT;
31919c402afSSimon Glass 	}
32019c402afSSimon Glass 	key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
32119c402afSSimon Glass 	key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
322*e0f2f155SMichael van der Westhuizen 	public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
323*e0f2f155SMichael van der Westhuizen 	if (!public_exponent || length < sizeof(*public_exponent))
324*e0f2f155SMichael van der Westhuizen 		key.exponent = RSA_DEFAULT_PUBEXP;
325*e0f2f155SMichael van der Westhuizen 	else
326*e0f2f155SMichael van der Westhuizen 		key.exponent = fdt64_to_cpu(*public_exponent);
32719c402afSSimon Glass 	modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
32819c402afSSimon Glass 	rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
32919c402afSSimon Glass 	if (!key.len || !modulus || !rr) {
33019c402afSSimon Glass 		debug("%s: Missing RSA key info", __func__);
33119c402afSSimon Glass 		return -EFAULT;
33219c402afSSimon Glass 	}
33319c402afSSimon Glass 
33419c402afSSimon Glass 	/* Sanity check for stack size */
33519c402afSSimon Glass 	if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
33619c402afSSimon Glass 		debug("RSA key bits %u outside allowed range %d..%d\n",
33719c402afSSimon Glass 		      key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
33819c402afSSimon Glass 		return -EFAULT;
33919c402afSSimon Glass 	}
34019c402afSSimon Glass 	key.len /= sizeof(uint32_t) * 8;
34119c402afSSimon Glass 	uint32_t key1[key.len], key2[key.len];
34219c402afSSimon Glass 
34319c402afSSimon Glass 	key.modulus = key1;
34419c402afSSimon Glass 	key.rr = key2;
34519c402afSSimon Glass 	rsa_convert_big_endian(key.modulus, modulus, key.len);
34619c402afSSimon Glass 	rsa_convert_big_endian(key.rr, rr, key.len);
34719c402afSSimon Glass 	if (!key.modulus || !key.rr) {
34819c402afSSimon Glass 		debug("%s: Out of memory", __func__);
34919c402afSSimon Glass 		return -ENOMEM;
35019c402afSSimon Glass 	}
35119c402afSSimon Glass 
35219c402afSSimon Glass 	debug("key length %d\n", key.len);
353646257d1SHeiko Schocher 	ret = rsa_verify_key(&key, sig, sig_len, hash, info->algo->checksum);
35419c402afSSimon Glass 	if (ret) {
35519c402afSSimon Glass 		printf("%s: RSA failed to verify: %d\n", __func__, ret);
35619c402afSSimon Glass 		return ret;
35719c402afSSimon Glass 	}
35819c402afSSimon Glass 
35919c402afSSimon Glass 	return 0;
36019c402afSSimon Glass }
36119c402afSSimon Glass 
36219c402afSSimon Glass int rsa_verify(struct image_sign_info *info,
36319c402afSSimon Glass 	       const struct image_region region[], int region_count,
36419c402afSSimon Glass 	       uint8_t *sig, uint sig_len)
36519c402afSSimon Glass {
36619c402afSSimon Glass 	const void *blob = info->fdt_blob;
367646257d1SHeiko Schocher 	/* Reserve memory for maximum checksum-length */
368db1b5f3dSHeiko Schocher 	uint8_t hash[info->algo->checksum->pad_len];
36919c402afSSimon Glass 	int ndepth, noffset;
37019c402afSSimon Glass 	int sig_node, node;
37119c402afSSimon Glass 	char name[100];
372646257d1SHeiko Schocher 	int ret;
373646257d1SHeiko Schocher 
374646257d1SHeiko Schocher 	/*
375646257d1SHeiko Schocher 	 * Verify that the checksum-length does not exceed the
376646257d1SHeiko Schocher 	 * rsa-signature-length
377646257d1SHeiko Schocher 	 */
378db1b5f3dSHeiko Schocher 	if (info->algo->checksum->checksum_len >
379db1b5f3dSHeiko Schocher 	    info->algo->checksum->pad_len) {
380db1b5f3dSHeiko Schocher 		debug("%s: invlaid checksum-algorithm %s for %s\n",
381db1b5f3dSHeiko Schocher 		      __func__, info->algo->checksum->name, info->algo->name);
382646257d1SHeiko Schocher 		return -EINVAL;
383646257d1SHeiko Schocher 	}
38419c402afSSimon Glass 
38519c402afSSimon Glass 	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
38619c402afSSimon Glass 	if (sig_node < 0) {
38719c402afSSimon Glass 		debug("%s: No signature node found\n", __func__);
38819c402afSSimon Glass 		return -ENOENT;
38919c402afSSimon Glass 	}
39019c402afSSimon Glass 
391646257d1SHeiko Schocher 	/* Calculate checksum with checksum-algorithm */
392646257d1SHeiko Schocher 	info->algo->checksum->calculate(region, region_count, hash);
39319c402afSSimon Glass 
39419c402afSSimon Glass 	/* See if we must use a particular key */
39519c402afSSimon Glass 	if (info->required_keynode != -1) {
39619c402afSSimon Glass 		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
39719c402afSSimon Glass 			info->required_keynode);
39819c402afSSimon Glass 		if (!ret)
39919c402afSSimon Glass 			return ret;
40019c402afSSimon Glass 	}
40119c402afSSimon Glass 
40219c402afSSimon Glass 	/* Look for a key that matches our hint */
40319c402afSSimon Glass 	snprintf(name, sizeof(name), "key-%s", info->keyname);
40419c402afSSimon Glass 	node = fdt_subnode_offset(blob, sig_node, name);
40519c402afSSimon Glass 	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
40619c402afSSimon Glass 	if (!ret)
40719c402afSSimon Glass 		return ret;
40819c402afSSimon Glass 
40919c402afSSimon Glass 	/* No luck, so try each of the keys in turn */
41019c402afSSimon Glass 	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
41119c402afSSimon Glass 			(noffset >= 0) && (ndepth > 0);
41219c402afSSimon Glass 			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
41319c402afSSimon Glass 		if (ndepth == 1 && noffset != node) {
41419c402afSSimon Glass 			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
41519c402afSSimon Glass 						      noffset);
41619c402afSSimon Glass 			if (!ret)
41719c402afSSimon Glass 				break;
41819c402afSSimon Glass 		}
41919c402afSSimon Glass 	}
42019c402afSSimon Glass 
42119c402afSSimon Glass 	return ret;
42219c402afSSimon Glass }
423