xref: /rk3399_rockchip-uboot/lib/rsa/rsa-verify.c (revision 85289e9d5d410dfcd041dc7b762f4bd06a31bc24)
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>
9008ec9b4SJoseph Chen #include <crypto.h>
1019c402afSSimon Glass #include <fdtdec.h>
1129a23f9dSHeiko Schocher #include <asm/types.h>
1229a23f9dSHeiko Schocher #include <asm/byteorder.h>
131221ce45SMasahiro Yamada #include <linux/errno.h>
1429a23f9dSHeiko Schocher #include <asm/types.h>
1529a23f9dSHeiko Schocher #include <asm/unaligned.h>
16c937ff6dSRuchika Gupta #include <dm.h>
1729a23f9dSHeiko Schocher #else
1829a23f9dSHeiko Schocher #include "fdt_host.h"
1929a23f9dSHeiko Schocher #include "mkimage.h"
2029a23f9dSHeiko Schocher #include <fdt_support.h>
2129a23f9dSHeiko Schocher #endif
22fc2f4246SRuchika Gupta #include <u-boot/rsa-mod-exp.h>
232b9912e6SJeroen Hofstee #include <u-boot/rsa.h>
2429a23f9dSHeiko Schocher 
25e0f2f155SMichael van der Westhuizen /* Default public exponent for backward compatibility */
26e0f2f155SMichael van der Westhuizen #define RSA_DEFAULT_PUBEXP	65537
27e0f2f155SMichael van der Westhuizen 
2819c402afSSimon Glass /**
29da29f299SAndrew Duda  * rsa_verify_padding() - Verify RSA message padding is valid
30da29f299SAndrew Duda  *
31da29f299SAndrew Duda  * Verify a RSA message's padding is consistent with PKCS1.5
32da29f299SAndrew Duda  * padding as described in the RSA PKCS#1 v2.1 standard.
33da29f299SAndrew Duda  *
34da29f299SAndrew Duda  * @msg:	Padded message
35da29f299SAndrew Duda  * @pad_len:	Number of expected padding bytes
36da29f299SAndrew Duda  * @algo:	Checksum algo structure having information on DER encoding etc.
37da29f299SAndrew Duda  * @return 0 on success, != 0 on failure
38da29f299SAndrew Duda  */
39da29f299SAndrew Duda static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
40da29f299SAndrew Duda 			      struct checksum_algo *algo)
41da29f299SAndrew Duda {
42da29f299SAndrew Duda 	int ff_len;
43da29f299SAndrew Duda 	int ret;
44da29f299SAndrew Duda 
45da29f299SAndrew Duda 	/* first byte must be 0x00 */
46da29f299SAndrew Duda 	ret = *msg++;
47da29f299SAndrew Duda 	/* second byte must be 0x01 */
48da29f299SAndrew Duda 	ret |= *msg++ ^ 0x01;
49da29f299SAndrew Duda 	/* next ff_len bytes must be 0xff */
50da29f299SAndrew Duda 	ff_len = pad_len - algo->der_len - 3;
51da29f299SAndrew Duda 	ret |= *msg ^ 0xff;
52da29f299SAndrew Duda 	ret |= memcmp(msg, msg+1, ff_len-1);
53da29f299SAndrew Duda 	msg += ff_len;
54da29f299SAndrew Duda 	/* next byte must be 0x00 */
55da29f299SAndrew Duda 	ret |= *msg++;
56da29f299SAndrew Duda 	/* next der_len bytes must match der_prefix */
57da29f299SAndrew Duda 	ret |= memcmp(msg, algo->der_prefix, algo->der_len);
58da29f299SAndrew Duda 
59da29f299SAndrew Duda 	return ret;
60da29f299SAndrew Duda }
61da29f299SAndrew Duda 
62008ec9b4SJoseph Chen #if !defined(USE_HOSTCC)
63008ec9b4SJoseph Chen #if CONFIG_IS_ENABLED(FIT_HW_CRYPTO)
64008ec9b4SJoseph Chen static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
65008ec9b4SJoseph Chen {
66008ec9b4SJoseph Chen 	int i;
67008ec9b4SJoseph Chen 
68008ec9b4SJoseph Chen 	for (i = 0; i < len; i++)
69008ec9b4SJoseph Chen 		dst[i] = fdt32_to_cpu(src[len - 1 - i]);
70008ec9b4SJoseph Chen }
71008ec9b4SJoseph Chen 
720fb93272SJoseph Chen static int rsa_mod_exp_hw(struct key_prop *prop, const uint8_t *sig,
73008ec9b4SJoseph Chen 			  const uint32_t sig_len, const uint32_t key_len,
74008ec9b4SJoseph Chen 			  uint8_t *output)
75008ec9b4SJoseph Chen {
76008ec9b4SJoseph Chen 	struct udevice *dev;
77008ec9b4SJoseph Chen 	uint8_t sig_reverse[sig_len];
78008ec9b4SJoseph Chen 	uint8_t buf[sig_len];
79008ec9b4SJoseph Chen 	rsa_key rsa_key;
80008ec9b4SJoseph Chen 	int i, ret;
81008ec9b4SJoseph Chen 
82008ec9b4SJoseph Chen 	if (key_len != RSA2048_BYTES)
83008ec9b4SJoseph Chen 		return -EINVAL;
84008ec9b4SJoseph Chen 
85008ec9b4SJoseph Chen 	rsa_key.algo = CRYPTO_RSA2048;
86008ec9b4SJoseph Chen 	rsa_key.n = malloc(key_len);
87008ec9b4SJoseph Chen 	rsa_key.e = malloc(key_len);
88008ec9b4SJoseph Chen 	rsa_key.c = malloc(key_len);
89008ec9b4SJoseph Chen 	if (!rsa_key.n || !rsa_key.e || !rsa_key.c)
90008ec9b4SJoseph Chen 		return -ENOMEM;
91008ec9b4SJoseph Chen 
92008ec9b4SJoseph Chen 	rsa_convert_big_endian(rsa_key.n, (uint32_t *)prop->modulus,
93008ec9b4SJoseph Chen 			       key_len / sizeof(uint32_t));
94008ec9b4SJoseph Chen 	rsa_convert_big_endian(rsa_key.e, (uint32_t *)prop->public_exponent_BN,
95008ec9b4SJoseph Chen 			       key_len / sizeof(uint32_t));
96008ec9b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
97008ec9b4SJoseph Chen 	rsa_convert_big_endian(rsa_key.c, (uint32_t *)prop->factor_c,
98008ec9b4SJoseph Chen 			       key_len / sizeof(uint32_t));
99008ec9b4SJoseph Chen #else
100008ec9b4SJoseph Chen 	rsa_convert_big_endian(rsa_key.c, (uint32_t *)prop->factor_np,
101008ec9b4SJoseph Chen 			       key_len / sizeof(uint32_t));
102008ec9b4SJoseph Chen #endif
103008ec9b4SJoseph Chen 	for (i = 0; i < sig_len; i++)
104008ec9b4SJoseph Chen 		sig_reverse[sig_len-1-i] = sig[i];
105008ec9b4SJoseph Chen 
106008ec9b4SJoseph Chen 	dev = crypto_get_device(rsa_key.algo);
107008ec9b4SJoseph Chen 	if (!dev) {
108008ec9b4SJoseph Chen 		printf("No crypto device for expected RSA\n");
109008ec9b4SJoseph Chen 		return -ENODEV;
110008ec9b4SJoseph Chen 	}
111008ec9b4SJoseph Chen 
112008ec9b4SJoseph Chen 	ret = crypto_rsa_verify(dev, &rsa_key, (u8 *)sig_reverse, buf);
113008ec9b4SJoseph Chen 	if (ret)
114008ec9b4SJoseph Chen 		goto out;
115008ec9b4SJoseph Chen 
116008ec9b4SJoseph Chen 	for (i = 0; i < sig_len; i++)
117008ec9b4SJoseph Chen 		sig_reverse[sig_len-1-i] = buf[i];
118008ec9b4SJoseph Chen 
119008ec9b4SJoseph Chen 	memcpy(output, sig_reverse, sig_len);
120008ec9b4SJoseph Chen out:
121008ec9b4SJoseph Chen 	free(rsa_key.n);
122008ec9b4SJoseph Chen 	free(rsa_key.e);
123008ec9b4SJoseph Chen 	free(rsa_key.c);
124008ec9b4SJoseph Chen 
125008ec9b4SJoseph Chen 	return ret;
126008ec9b4SJoseph Chen }
127008ec9b4SJoseph Chen #endif
128008ec9b4SJoseph Chen #endif
129008ec9b4SJoseph Chen 
130219050bfSPhilippe Reynes int padding_pkcs_15_verify(struct image_sign_info *info,
131219050bfSPhilippe Reynes 			   uint8_t *msg, int msg_len,
132219050bfSPhilippe Reynes 			   const uint8_t *hash, int hash_len)
133219050bfSPhilippe Reynes {
134219050bfSPhilippe Reynes 	struct checksum_algo *checksum = info->checksum;
135219050bfSPhilippe Reynes 	int ret, pad_len = msg_len - checksum->checksum_len;
136219050bfSPhilippe Reynes 
137219050bfSPhilippe Reynes 	/* Check pkcs1.5 padding bytes. */
138219050bfSPhilippe Reynes 	ret = rsa_verify_padding(msg, pad_len, checksum);
139219050bfSPhilippe Reynes 	if (ret) {
140219050bfSPhilippe Reynes 		debug("In RSAVerify(): Padding check failed!\n");
141219050bfSPhilippe Reynes 		return -EINVAL;
142219050bfSPhilippe Reynes 	}
143219050bfSPhilippe Reynes 
144219050bfSPhilippe Reynes 	/* Check hash. */
145219050bfSPhilippe Reynes 	if (memcmp((uint8_t *)msg + pad_len, hash, msg_len - pad_len)) {
146219050bfSPhilippe Reynes 		debug("In RSAVerify(): Hash check failed!\n");
147219050bfSPhilippe Reynes 		return -EACCES;
148219050bfSPhilippe Reynes 	}
149219050bfSPhilippe Reynes 
150219050bfSPhilippe Reynes 	return 0;
151219050bfSPhilippe Reynes }
152219050bfSPhilippe Reynes 
153*85289e9dSPhilippe Reynes #ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
154*85289e9dSPhilippe Reynes static void u32_i2osp(uint32_t val, uint8_t *buf)
155*85289e9dSPhilippe Reynes {
156*85289e9dSPhilippe Reynes 	buf[0] = (uint8_t)((val >> 24) & 0xff);
157*85289e9dSPhilippe Reynes 	buf[1] = (uint8_t)((val >> 16) & 0xff);
158*85289e9dSPhilippe Reynes 	buf[2] = (uint8_t)((val >>  8) & 0xff);
159*85289e9dSPhilippe Reynes 	buf[3] = (uint8_t)((val >>  0) & 0xff);
160*85289e9dSPhilippe Reynes }
161*85289e9dSPhilippe Reynes 
162*85289e9dSPhilippe Reynes /**
163*85289e9dSPhilippe Reynes  * mask_generation_function1() - generate an octet string
164*85289e9dSPhilippe Reynes  *
165*85289e9dSPhilippe Reynes  * Generate an octet string used to check rsa signature.
166*85289e9dSPhilippe Reynes  * It use an input octet string and a hash function.
167*85289e9dSPhilippe Reynes  *
168*85289e9dSPhilippe Reynes  * @checksum:	A Hash function
169*85289e9dSPhilippe Reynes  * @seed:	Specifies an input variable octet string
170*85289e9dSPhilippe Reynes  * @seed_len:	Size of the input octet string
171*85289e9dSPhilippe Reynes  * @output:	Specifies the output octet string
172*85289e9dSPhilippe Reynes  * @output_len:	Size of the output octet string
173*85289e9dSPhilippe Reynes  * @return 0 if the octet string was correctly generated, others on error
174*85289e9dSPhilippe Reynes  */
175*85289e9dSPhilippe Reynes static int mask_generation_function1(struct checksum_algo *checksum,
176*85289e9dSPhilippe Reynes 				     uint8_t *seed, int seed_len,
177*85289e9dSPhilippe Reynes 				     uint8_t *output, int output_len)
178*85289e9dSPhilippe Reynes {
179*85289e9dSPhilippe Reynes 	struct image_region region[2];
180*85289e9dSPhilippe Reynes 	int ret = 0, i, i_output = 0, region_count = 2;
181*85289e9dSPhilippe Reynes 	uint32_t counter = 0;
182*85289e9dSPhilippe Reynes 	uint8_t buf_counter[4], *tmp;
183*85289e9dSPhilippe Reynes 	int hash_len = checksum->checksum_len;
184*85289e9dSPhilippe Reynes 
185*85289e9dSPhilippe Reynes 	memset(output, 0, output_len);
186*85289e9dSPhilippe Reynes 
187*85289e9dSPhilippe Reynes 	region[0].data = seed;
188*85289e9dSPhilippe Reynes 	region[0].size = seed_len;
189*85289e9dSPhilippe Reynes 	region[1].data = &buf_counter[0];
190*85289e9dSPhilippe Reynes 	region[1].size = 4;
191*85289e9dSPhilippe Reynes 
192*85289e9dSPhilippe Reynes 	tmp = malloc(hash_len);
193*85289e9dSPhilippe Reynes 	if (!tmp) {
194*85289e9dSPhilippe Reynes 		debug("%s: can't allocate array tmp\n", __func__);
195*85289e9dSPhilippe Reynes 		ret = -ENOMEM;
196*85289e9dSPhilippe Reynes 		goto out;
197*85289e9dSPhilippe Reynes 	}
198*85289e9dSPhilippe Reynes 
199*85289e9dSPhilippe Reynes 	while (i_output < output_len) {
200*85289e9dSPhilippe Reynes 		u32_i2osp(counter, &buf_counter[0]);
201*85289e9dSPhilippe Reynes 
202*85289e9dSPhilippe Reynes 		ret = checksum->calculate(checksum->name,
203*85289e9dSPhilippe Reynes 					  region, region_count,
204*85289e9dSPhilippe Reynes 					  tmp);
205*85289e9dSPhilippe Reynes 		if (ret < 0) {
206*85289e9dSPhilippe Reynes 			debug("%s: Error in checksum calculation\n", __func__);
207*85289e9dSPhilippe Reynes 			goto out;
208*85289e9dSPhilippe Reynes 		}
209*85289e9dSPhilippe Reynes 
210*85289e9dSPhilippe Reynes 		i = 0;
211*85289e9dSPhilippe Reynes 		while ((i_output < output_len) && (i < hash_len)) {
212*85289e9dSPhilippe Reynes 			output[i_output] = tmp[i];
213*85289e9dSPhilippe Reynes 			i_output++;
214*85289e9dSPhilippe Reynes 			i++;
215*85289e9dSPhilippe Reynes 		}
216*85289e9dSPhilippe Reynes 
217*85289e9dSPhilippe Reynes 		counter++;
218*85289e9dSPhilippe Reynes 	}
219*85289e9dSPhilippe Reynes 
220*85289e9dSPhilippe Reynes out:
221*85289e9dSPhilippe Reynes 	free(tmp);
222*85289e9dSPhilippe Reynes 
223*85289e9dSPhilippe Reynes 	return ret;
224*85289e9dSPhilippe Reynes }
225*85289e9dSPhilippe Reynes 
226*85289e9dSPhilippe Reynes static int compute_hash_prime(struct checksum_algo *checksum,
227*85289e9dSPhilippe Reynes 			      uint8_t *pad, int pad_len,
228*85289e9dSPhilippe Reynes 			      uint8_t *hash, int hash_len,
229*85289e9dSPhilippe Reynes 			      uint8_t *salt, int salt_len,
230*85289e9dSPhilippe Reynes 			      uint8_t *hprime)
231*85289e9dSPhilippe Reynes {
232*85289e9dSPhilippe Reynes 	struct image_region region[3];
233*85289e9dSPhilippe Reynes 	int ret, region_count = 3;
234*85289e9dSPhilippe Reynes 
235*85289e9dSPhilippe Reynes 	region[0].data = pad;
236*85289e9dSPhilippe Reynes 	region[0].size = pad_len;
237*85289e9dSPhilippe Reynes 	region[1].data = hash;
238*85289e9dSPhilippe Reynes 	region[1].size = hash_len;
239*85289e9dSPhilippe Reynes 	region[2].data = salt;
240*85289e9dSPhilippe Reynes 	region[2].size = salt_len;
241*85289e9dSPhilippe Reynes 
242*85289e9dSPhilippe Reynes 	ret = checksum->calculate(checksum->name, region, region_count, hprime);
243*85289e9dSPhilippe Reynes 	if (ret < 0) {
244*85289e9dSPhilippe Reynes 		debug("%s: Error in checksum calculation\n", __func__);
245*85289e9dSPhilippe Reynes 		goto out;
246*85289e9dSPhilippe Reynes 	}
247*85289e9dSPhilippe Reynes 
248*85289e9dSPhilippe Reynes out:
249*85289e9dSPhilippe Reynes 	return ret;
250*85289e9dSPhilippe Reynes }
251*85289e9dSPhilippe Reynes 
252*85289e9dSPhilippe Reynes int padding_pss_verify(struct image_sign_info *info,
253*85289e9dSPhilippe Reynes 		       uint8_t *msg, int msg_len,
254*85289e9dSPhilippe Reynes 		       const uint8_t *hash, int hash_len)
255*85289e9dSPhilippe Reynes {
256*85289e9dSPhilippe Reynes 	uint8_t *masked_db = NULL;
257*85289e9dSPhilippe Reynes 	int masked_db_len = msg_len - hash_len - 1;
258*85289e9dSPhilippe Reynes 	uint8_t *h = NULL, *hprime = NULL;
259*85289e9dSPhilippe Reynes 	int h_len = hash_len;
260*85289e9dSPhilippe Reynes 	uint8_t *db_mask = NULL;
261*85289e9dSPhilippe Reynes 	int db_mask_len = masked_db_len;
262*85289e9dSPhilippe Reynes 	uint8_t *db = NULL, *salt = NULL;
263*85289e9dSPhilippe Reynes 	int db_len = masked_db_len, salt_len = msg_len - hash_len - 2;
264*85289e9dSPhilippe Reynes 	uint8_t pad_zero[8] = { 0 };
265*85289e9dSPhilippe Reynes 	int ret, i, leftmost_bits = 1;
266*85289e9dSPhilippe Reynes 	uint8_t leftmost_mask;
267*85289e9dSPhilippe Reynes 	struct checksum_algo *checksum = info->checksum;
268*85289e9dSPhilippe Reynes 
269*85289e9dSPhilippe Reynes 	/* first, allocate everything */
270*85289e9dSPhilippe Reynes 	masked_db = malloc(masked_db_len);
271*85289e9dSPhilippe Reynes 	h = malloc(h_len);
272*85289e9dSPhilippe Reynes 	db_mask = malloc(db_mask_len);
273*85289e9dSPhilippe Reynes 	db = malloc(db_len);
274*85289e9dSPhilippe Reynes 	salt = malloc(salt_len);
275*85289e9dSPhilippe Reynes 	hprime = malloc(hash_len);
276*85289e9dSPhilippe Reynes 	if (!masked_db || !h || !db_mask || !db || !salt || !hprime) {
277*85289e9dSPhilippe Reynes 		printf("%s: can't allocate some buffer\n", __func__);
278*85289e9dSPhilippe Reynes 		ret = -ENOMEM;
279*85289e9dSPhilippe Reynes 		goto out;
280*85289e9dSPhilippe Reynes 	}
281*85289e9dSPhilippe Reynes 
282*85289e9dSPhilippe Reynes 	/* step 4: check if the last byte is 0xbc */
283*85289e9dSPhilippe Reynes 	if (msg[msg_len - 1] != 0xbc) {
284*85289e9dSPhilippe Reynes 		printf("%s: invalid pss padding (0xbc is missing)\n", __func__);
285*85289e9dSPhilippe Reynes 		ret = -EINVAL;
286*85289e9dSPhilippe Reynes 		goto out;
287*85289e9dSPhilippe Reynes 	}
288*85289e9dSPhilippe Reynes 
289*85289e9dSPhilippe Reynes 	/* step 5 */
290*85289e9dSPhilippe Reynes 	memcpy(masked_db, msg, masked_db_len);
291*85289e9dSPhilippe Reynes 	memcpy(h, msg + masked_db_len, h_len);
292*85289e9dSPhilippe Reynes 
293*85289e9dSPhilippe Reynes 	/* step 6 */
294*85289e9dSPhilippe Reynes 	leftmost_mask = (0xff >> (8 - leftmost_bits)) << (8 - leftmost_bits);
295*85289e9dSPhilippe Reynes 	if (masked_db[0] & leftmost_mask) {
296*85289e9dSPhilippe Reynes 		printf("%s: invalid pss padding ", __func__);
297*85289e9dSPhilippe Reynes 		printf("(leftmost bit of maskedDB not zero)\n");
298*85289e9dSPhilippe Reynes 		ret = -EINVAL;
299*85289e9dSPhilippe Reynes 		goto out;
300*85289e9dSPhilippe Reynes 	}
301*85289e9dSPhilippe Reynes 
302*85289e9dSPhilippe Reynes 	/* step 7 */
303*85289e9dSPhilippe Reynes 	mask_generation_function1(checksum, h, h_len, db_mask, db_mask_len);
304*85289e9dSPhilippe Reynes 
305*85289e9dSPhilippe Reynes 	/* step 8 */
306*85289e9dSPhilippe Reynes 	for (i = 0; i < db_len; i++)
307*85289e9dSPhilippe Reynes 		db[i] = masked_db[i] ^ db_mask[i];
308*85289e9dSPhilippe Reynes 
309*85289e9dSPhilippe Reynes 	/* step 9 */
310*85289e9dSPhilippe Reynes 	db[0] &= 0xff >> leftmost_bits;
311*85289e9dSPhilippe Reynes 
312*85289e9dSPhilippe Reynes 	/* step 10 */
313*85289e9dSPhilippe Reynes 	if (db[0] != 0x01) {
314*85289e9dSPhilippe Reynes 		printf("%s: invalid pss padding ", __func__);
315*85289e9dSPhilippe Reynes 		printf("(leftmost byte of db isn't 0x01)\n");
316*85289e9dSPhilippe Reynes 		ret = EINVAL;
317*85289e9dSPhilippe Reynes 		goto out;
318*85289e9dSPhilippe Reynes 	}
319*85289e9dSPhilippe Reynes 
320*85289e9dSPhilippe Reynes 	/* step 11 */
321*85289e9dSPhilippe Reynes 	memcpy(salt, &db[1], salt_len);
322*85289e9dSPhilippe Reynes 
323*85289e9dSPhilippe Reynes 	/* step 12 & 13 */
324*85289e9dSPhilippe Reynes 	compute_hash_prime(checksum, pad_zero, 8,
325*85289e9dSPhilippe Reynes 			   (uint8_t *)hash, hash_len,
326*85289e9dSPhilippe Reynes 			   salt, salt_len, hprime);
327*85289e9dSPhilippe Reynes 
328*85289e9dSPhilippe Reynes 	/* step 14 */
329*85289e9dSPhilippe Reynes 	ret = memcmp(h, hprime, hash_len);
330*85289e9dSPhilippe Reynes 
331*85289e9dSPhilippe Reynes out:
332*85289e9dSPhilippe Reynes 	free(hprime);
333*85289e9dSPhilippe Reynes 	free(salt);
334*85289e9dSPhilippe Reynes 	free(db);
335*85289e9dSPhilippe Reynes 	free(db_mask);
336*85289e9dSPhilippe Reynes 	free(h);
337*85289e9dSPhilippe Reynes 	free(masked_db);
338*85289e9dSPhilippe Reynes 
339*85289e9dSPhilippe Reynes 	return ret;
340*85289e9dSPhilippe Reynes }
341*85289e9dSPhilippe Reynes #endif
342*85289e9dSPhilippe Reynes 
343da29f299SAndrew Duda /**
344fc2f4246SRuchika Gupta  * rsa_verify_key() - Verify a signature against some data using RSA Key
34519c402afSSimon Glass  *
346fc2f4246SRuchika Gupta  * Verify a RSA PKCS1.5 signature against an expected hash using
347fc2f4246SRuchika Gupta  * the RSA Key properties in prop structure.
348fc2f4246SRuchika Gupta  *
349219050bfSPhilippe Reynes  * @info:	Specifies key and FIT information
350fc2f4246SRuchika Gupta  * @prop:	Specifies key
351fc2f4246SRuchika Gupta  * @sig:	Signature
352fc2f4246SRuchika Gupta  * @sig_len:	Number of bytes in signature
353fc2f4246SRuchika Gupta  * @hash:	Pointer to the expected hash
3540c1d74fdSAndrew Duda  * @key_len:	Number of bytes in rsa key
355fc2f4246SRuchika Gupta  * @return 0 if verified, -ve on error
35619c402afSSimon Glass  */
357219050bfSPhilippe Reynes static int rsa_verify_key(struct image_sign_info *info,
358219050bfSPhilippe Reynes 			  struct key_prop *prop, const uint8_t *sig,
359646257d1SHeiko Schocher 			  const uint32_t sig_len, const uint8_t *hash,
360219050bfSPhilippe Reynes 			  const uint32_t key_len)
36119c402afSSimon Glass {
36219c402afSSimon Glass 	int ret;
363219050bfSPhilippe Reynes 	struct checksum_algo *checksum = info->checksum;
364219050bfSPhilippe Reynes 	struct padding_algo *padding = info->padding;
365219050bfSPhilippe Reynes 	int hash_len = checksum->checksum_len;
36619c402afSSimon Glass 
367219050bfSPhilippe Reynes 	if (!prop || !sig || !hash || !checksum)
36819c402afSSimon Glass 		return -EIO;
36919c402afSSimon Glass 
370fc2f4246SRuchika Gupta 	if (sig_len != (prop->num_bits / 8)) {
37119c402afSSimon Glass 		debug("Signature is of incorrect length %d\n", sig_len);
37219c402afSSimon Glass 		return -EINVAL;
37319c402afSSimon Glass 	}
37419c402afSSimon Glass 
375219050bfSPhilippe Reynes 	debug("Checksum algorithm: %s", checksum->name);
376646257d1SHeiko Schocher 
37719c402afSSimon Glass 	/* Sanity check for stack size */
37819c402afSSimon Glass 	if (sig_len > RSA_MAX_SIG_BITS / 8) {
37919c402afSSimon Glass 		debug("Signature length %u exceeds maximum %d\n", sig_len,
38019c402afSSimon Glass 		      RSA_MAX_SIG_BITS / 8);
38119c402afSSimon Glass 		return -EINVAL;
38219c402afSSimon Glass 	}
38319c402afSSimon Glass 
384fc2f4246SRuchika Gupta 	uint8_t buf[sig_len];
38519c402afSSimon Glass 
386c937ff6dSRuchika Gupta #if !defined(USE_HOSTCC)
387008ec9b4SJoseph Chen #if CONFIG_IS_ENABLED(FIT_HW_CRYPTO)
3880fb93272SJoseph Chen 	ret = rsa_mod_exp_hw(prop, sig, sig_len, key_len, buf);
389008ec9b4SJoseph Chen #else
390008ec9b4SJoseph Chen 	struct udevice *mod_exp_dev;
391008ec9b4SJoseph Chen 
392c937ff6dSRuchika Gupta 	ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
393c937ff6dSRuchika Gupta 	if (ret) {
394c937ff6dSRuchika Gupta 		printf("RSA: Can't find Modular Exp implementation\n");
395c937ff6dSRuchika Gupta 		return -EINVAL;
396c937ff6dSRuchika Gupta 	}
397c937ff6dSRuchika Gupta 
398c937ff6dSRuchika Gupta 	ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
399008ec9b4SJoseph Chen #endif
400c937ff6dSRuchika Gupta #else
401fc2f4246SRuchika Gupta 	ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
402c937ff6dSRuchika Gupta #endif
403fc2f4246SRuchika Gupta 	if (ret) {
404fc2f4246SRuchika Gupta 		debug("Error in Modular exponentation\n");
40519c402afSSimon Glass 		return ret;
406fc2f4246SRuchika Gupta 	}
40719c402afSSimon Glass 
408219050bfSPhilippe Reynes 	ret = padding->verify(info, buf, key_len, hash, hash_len);
409da29f299SAndrew Duda 	if (ret) {
410219050bfSPhilippe Reynes 		debug("In RSAVerify(): padding check failed!\n");
411219050bfSPhilippe Reynes 		return ret;
41219c402afSSimon Glass 	}
41319c402afSSimon Glass 
41419c402afSSimon Glass 	return 0;
41519c402afSSimon Glass }
41619c402afSSimon Glass 
417fc2f4246SRuchika Gupta /**
418fc2f4246SRuchika Gupta  * rsa_verify_with_keynode() - Verify a signature against some data using
419fc2f4246SRuchika Gupta  * information in node with prperties of RSA Key like modulus, exponent etc.
420fc2f4246SRuchika Gupta  *
421fc2f4246SRuchika Gupta  * Parse sign-node and fill a key_prop structure with properties of the
422fc2f4246SRuchika Gupta  * key.  Verify a RSA PKCS1.5 signature against an expected hash using
423fc2f4246SRuchika Gupta  * the properties parsed
424fc2f4246SRuchika Gupta  *
425fc2f4246SRuchika Gupta  * @info:	Specifies key and FIT information
426fc2f4246SRuchika Gupta  * @hash:	Pointer to the expected hash
427fc2f4246SRuchika Gupta  * @sig:	Signature
428fc2f4246SRuchika Gupta  * @sig_len:	Number of bytes in signature
429fc2f4246SRuchika Gupta  * @node:	Node having the RSA Key properties
430fc2f4246SRuchika Gupta  * @return 0 if verified, -ve on error
431fc2f4246SRuchika Gupta  */
43219c402afSSimon Glass static int rsa_verify_with_keynode(struct image_sign_info *info,
433fc2f4246SRuchika Gupta 				   const void *hash, uint8_t *sig,
434fc2f4246SRuchika Gupta 				   uint sig_len, int node)
43519c402afSSimon Glass {
43619c402afSSimon Glass 	const void *blob = info->fdt_blob;
437fc2f4246SRuchika Gupta 	struct key_prop prop;
438e0f2f155SMichael van der Westhuizen 	int length;
439fc2f4246SRuchika Gupta 	int ret = 0;
44019c402afSSimon Glass 
44119c402afSSimon Glass 	if (node < 0) {
44219c402afSSimon Glass 		debug("%s: Skipping invalid node", __func__);
44319c402afSSimon Glass 		return -EBADF;
44419c402afSSimon Glass 	}
445fc2f4246SRuchika Gupta 
446fc2f4246SRuchika Gupta 	prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
447fc2f4246SRuchika Gupta 
448fc2f4246SRuchika Gupta 	prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
449fc2f4246SRuchika Gupta 
450fc2f4246SRuchika Gupta 	prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
451fc2f4246SRuchika Gupta 	if (!prop.public_exponent || length < sizeof(uint64_t))
452fc2f4246SRuchika Gupta 		prop.public_exponent = NULL;
453fc2f4246SRuchika Gupta 
454fc2f4246SRuchika Gupta 	prop.exp_len = sizeof(uint64_t);
455fc2f4246SRuchika Gupta 
456fc2f4246SRuchika Gupta 	prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
457008ec9b4SJoseph Chen 	prop.public_exponent_BN = fdt_getprop(blob, node, "rsa,exponent-BN", NULL);
458fc2f4246SRuchika Gupta 
459fc2f4246SRuchika Gupta 	prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
460fc2f4246SRuchika Gupta 
461fc2f4246SRuchika Gupta 	if (!prop.num_bits || !prop.modulus) {
46219c402afSSimon Glass 		debug("%s: Missing RSA key info", __func__);
46319c402afSSimon Glass 		return -EFAULT;
46419c402afSSimon Glass 	}
46519c402afSSimon Glass 
466008ec9b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
467008ec9b4SJoseph Chen 	prop.factor_c = fdt_getprop(blob, node, "rsa,c", NULL);
468008ec9b4SJoseph Chen 	if (!prop.factor_c)
469008ec9b4SJoseph Chen 		return -EFAULT;
470008ec9b4SJoseph Chen #else
471008ec9b4SJoseph Chen 	prop.factor_np = fdt_getprop(blob, node, "rsa,np", NULL);
472008ec9b4SJoseph Chen 	if (!prop.factor_np)
473008ec9b4SJoseph Chen 		return -EFAULT;
474008ec9b4SJoseph Chen #endif
475219050bfSPhilippe Reynes 	ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
476219050bfSPhilippe Reynes 			     info->crypto->key_len);
47719c402afSSimon Glass 
47819c402afSSimon Glass 	return ret;
47919c402afSSimon Glass }
48019c402afSSimon Glass 
48119c402afSSimon Glass int rsa_verify(struct image_sign_info *info,
48219c402afSSimon Glass 	       const struct image_region region[], int region_count,
48319c402afSSimon Glass 	       uint8_t *sig, uint sig_len)
48419c402afSSimon Glass {
48519c402afSSimon Glass 	const void *blob = info->fdt_blob;
486646257d1SHeiko Schocher 	/* Reserve memory for maximum checksum-length */
48783dd98e0SAndrew Duda 	uint8_t hash[info->crypto->key_len];
48819c402afSSimon Glass 	int ndepth, noffset;
48919c402afSSimon Glass 	int sig_node, node;
49019c402afSSimon Glass 	char name[100];
491646257d1SHeiko Schocher 	int ret;
492646257d1SHeiko Schocher 
493646257d1SHeiko Schocher 	/*
494646257d1SHeiko Schocher 	 * Verify that the checksum-length does not exceed the
495646257d1SHeiko Schocher 	 * rsa-signature-length
496646257d1SHeiko Schocher 	 */
49783dd98e0SAndrew Duda 	if (info->checksum->checksum_len >
49883dd98e0SAndrew Duda 	    info->crypto->key_len) {
499db1b5f3dSHeiko Schocher 		debug("%s: invlaid checksum-algorithm %s for %s\n",
50083dd98e0SAndrew Duda 		      __func__, info->checksum->name, info->crypto->name);
501646257d1SHeiko Schocher 		return -EINVAL;
502646257d1SHeiko Schocher 	}
50319c402afSSimon Glass 
50419c402afSSimon Glass 	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
50519c402afSSimon Glass 	if (sig_node < 0) {
50619c402afSSimon Glass 		debug("%s: No signature node found\n", __func__);
50719c402afSSimon Glass 		return -ENOENT;
50819c402afSSimon Glass 	}
50919c402afSSimon Glass 
510646257d1SHeiko Schocher 	/* Calculate checksum with checksum-algorithm */
51183dd98e0SAndrew Duda 	ret = info->checksum->calculate(info->checksum->name,
512b37b46f0SRuchika Gupta 					region, region_count, hash);
513b37b46f0SRuchika Gupta 	if (ret < 0) {
514b37b46f0SRuchika Gupta 		debug("%s: Error in checksum calculation\n", __func__);
515b37b46f0SRuchika Gupta 		return -EINVAL;
516b37b46f0SRuchika Gupta 	}
51719c402afSSimon Glass 
51819c402afSSimon Glass 	/* See if we must use a particular key */
51919c402afSSimon Glass 	if (info->required_keynode != -1) {
52019c402afSSimon Glass 		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
52119c402afSSimon Glass 			info->required_keynode);
52219c402afSSimon Glass 		if (!ret)
52319c402afSSimon Glass 			return ret;
52419c402afSSimon Glass 	}
52519c402afSSimon Glass 
52619c402afSSimon Glass 	/* Look for a key that matches our hint */
52719c402afSSimon Glass 	snprintf(name, sizeof(name), "key-%s", info->keyname);
52819c402afSSimon Glass 	node = fdt_subnode_offset(blob, sig_node, name);
52919c402afSSimon Glass 	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
53019c402afSSimon Glass 	if (!ret)
53119c402afSSimon Glass 		return ret;
53219c402afSSimon Glass 
53319c402afSSimon Glass 	/* No luck, so try each of the keys in turn */
53419c402afSSimon Glass 	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
53519c402afSSimon Glass 			(noffset >= 0) && (ndepth > 0);
53619c402afSSimon Glass 			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
53719c402afSSimon Glass 		if (ndepth == 1 && noffset != node) {
53819c402afSSimon Glass 			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
53919c402afSSimon Glass 						      noffset);
54019c402afSSimon Glass 			if (!ret)
54119c402afSSimon Glass 				break;
54219c402afSSimon Glass 		}
54319c402afSSimon Glass 	}
54419c402afSSimon Glass 
54519c402afSSimon Glass 	return ret;
54619c402afSSimon Glass }
547