blob: 1007b6979a4f58c32303b76c2dcf7f74f34b2d21 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass35191a32013-06-13 15:10:02 -07002/*
3 * Copyright (c) 2013, Google Inc.
Simon Glass35191a32013-06-13 15:10:02 -07004 */
5
Heiko Schocherd7b42322014-03-03 12:19:30 +01006#ifndef USE_HOSTCC
Simon Glass35191a32013-06-13 15:10:02 -07007#include <fdtdec.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <malloc.h>
Heiko Schocherd7b42322014-03-03 12:19:30 +010010#include <asm/types.h>
Simon Glass35191a32013-06-13 15:10:02 -070011#include <asm/byteorder.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090012#include <linux/errno.h>
Heiko Schocherd7b42322014-03-03 12:19:30 +010013#include <asm/types.h>
Simon Glass35191a32013-06-13 15:10:02 -070014#include <asm/unaligned.h>
Ruchika Guptaa0d3ca62015-01-23 16:01:54 +053015#include <dm.h>
Heiko Schocherd7b42322014-03-03 12:19:30 +010016#else
17#include "fdt_host.h"
18#include "mkimage.h"
Tom Rini8fac3d42023-12-14 07:16:54 -050019#include <linux/kconfig.h>
Heiko Schocherd7b42322014-03-03 12:19:30 +010020#include <fdt_support.h>
21#endif
Ruchika Guptab92ebab2015-01-23 16:01:50 +053022#include <u-boot/rsa-mod-exp.h>
Jeroen Hofsteebfe88fe2014-06-12 22:27:12 +020023#include <u-boot/rsa.h>
Heiko Schocherd7b42322014-03-03 12:19:30 +010024
Michael van der Westhuizen89f4ed12014-07-02 10:17:26 +020025/* Default public exponent for backward compatibility */
26#define RSA_DEFAULT_PUBEXP 65537
27
Simon Glass35191a32013-06-13 15:10:02 -070028/**
Andrew Duda3db9ff02016-11-08 18:53:40 +000029 * rsa_verify_padding() - Verify RSA message padding is valid
30 *
31 * Verify a RSA message's padding is consistent with PKCS1.5
32 * padding as described in the RSA PKCS#1 v2.1 standard.
33 *
34 * @msg: Padded message
35 * @pad_len: Number of expected padding bytes
36 * @algo: Checksum algo structure having information on DER encoding etc.
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010037 * Return: 0 on success, != 0 on failure
Andrew Duda3db9ff02016-11-08 18:53:40 +000038 */
39static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
40 struct checksum_algo *algo)
41{
42 int ff_len;
43 int ret;
44
45 /* first byte must be 0x00 */
46 ret = *msg++;
47 /* second byte must be 0x01 */
48 ret |= *msg++ ^ 0x01;
49 /* next ff_len bytes must be 0xff */
50 ff_len = pad_len - algo->der_len - 3;
51 ret |= *msg ^ 0xff;
52 ret |= memcmp(msg, msg+1, ff_len-1);
53 msg += ff_len;
54 /* next byte must be 0x00 */
55 ret |= *msg++;
56 /* next der_len bytes must match der_prefix */
57 ret |= memcmp(msg, algo->der_prefix, algo->der_len);
58
59 return ret;
60}
61
Philippe Reynes12468352018-11-14 13:51:00 +010062int padding_pkcs_15_verify(struct image_sign_info *info,
SESA6444251304b462022-03-09 01:27:15 -080063 const uint8_t *msg, int msg_len,
Philippe Reynes12468352018-11-14 13:51:00 +010064 const uint8_t *hash, int hash_len)
65{
66 struct checksum_algo *checksum = info->checksum;
67 int ret, pad_len = msg_len - checksum->checksum_len;
68
Simon Glass101d3492021-11-12 12:28:02 -070069 /* Check pkcs1.5 padding bytes */
Philippe Reynes12468352018-11-14 13:51:00 +010070 ret = rsa_verify_padding(msg, pad_len, checksum);
71 if (ret) {
72 debug("In RSAVerify(): Padding check failed!\n");
73 return -EINVAL;
74 }
75
Simon Glass101d3492021-11-12 12:28:02 -070076 /* Check hash */
Philippe Reynes12468352018-11-14 13:51:00 +010077 if (memcmp((uint8_t *)msg + pad_len, hash, msg_len - pad_len)) {
78 debug("In RSAVerify(): Hash check failed!\n");
79 return -EACCES;
80 }
81
82 return 0;
83}
84
Alexandru Gagniucf3b5e582021-08-18 17:49:02 -050085#ifndef USE_HOSTCC
86U_BOOT_PADDING_ALGO(pkcs_15) = {
87 .name = "pkcs-1.5",
88 .verify = padding_pkcs_15_verify,
89};
90#endif
91
Simon Glasseffa4522021-09-25 19:43:23 -060092#if CONFIG_IS_ENABLED(FIT_RSASSA_PSS)
Philippe Reynes47d73f02018-11-14 13:51:01 +010093static void u32_i2osp(uint32_t val, uint8_t *buf)
94{
95 buf[0] = (uint8_t)((val >> 24) & 0xff);
96 buf[1] = (uint8_t)((val >> 16) & 0xff);
97 buf[2] = (uint8_t)((val >> 8) & 0xff);
98 buf[3] = (uint8_t)((val >> 0) & 0xff);
99}
100
101/**
102 * mask_generation_function1() - generate an octet string
103 *
104 * Generate an octet string used to check rsa signature.
105 * It use an input octet string and a hash function.
106 *
107 * @checksum: A Hash function
108 * @seed: Specifies an input variable octet string
109 * @seed_len: Size of the input octet string
110 * @output: Specifies the output octet string
111 * @output_len: Size of the output octet string
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100112 * Return: 0 if the octet string was correctly generated, others on error
Philippe Reynes47d73f02018-11-14 13:51:01 +0100113 */
114static int mask_generation_function1(struct checksum_algo *checksum,
SESA6444251304b462022-03-09 01:27:15 -0800115 const uint8_t *seed, int seed_len,
Philippe Reynes47d73f02018-11-14 13:51:01 +0100116 uint8_t *output, int output_len)
117{
118 struct image_region region[2];
119 int ret = 0, i, i_output = 0, region_count = 2;
120 uint32_t counter = 0;
121 uint8_t buf_counter[4], *tmp;
122 int hash_len = checksum->checksum_len;
123
124 memset(output, 0, output_len);
125
126 region[0].data = seed;
127 region[0].size = seed_len;
128 region[1].data = &buf_counter[0];
129 region[1].size = 4;
130
131 tmp = malloc(hash_len);
132 if (!tmp) {
133 debug("%s: can't allocate array tmp\n", __func__);
134 ret = -ENOMEM;
135 goto out;
136 }
137
138 while (i_output < output_len) {
139 u32_i2osp(counter, &buf_counter[0]);
140
141 ret = checksum->calculate(checksum->name,
142 region, region_count,
143 tmp);
144 if (ret < 0) {
145 debug("%s: Error in checksum calculation\n", __func__);
146 goto out;
147 }
148
149 i = 0;
150 while ((i_output < output_len) && (i < hash_len)) {
151 output[i_output] = tmp[i];
152 i_output++;
153 i++;
154 }
155
156 counter++;
157 }
158
159out:
160 free(tmp);
161
162 return ret;
163}
164
165static int compute_hash_prime(struct checksum_algo *checksum,
SESA6444251304b462022-03-09 01:27:15 -0800166 const uint8_t *pad, int pad_len,
167 const uint8_t *hash, int hash_len,
168 const uint8_t *salt, int salt_len,
Philippe Reynes47d73f02018-11-14 13:51:01 +0100169 uint8_t *hprime)
170{
171 struct image_region region[3];
172 int ret, region_count = 3;
173
174 region[0].data = pad;
175 region[0].size = pad_len;
176 region[1].data = hash;
177 region[1].size = hash_len;
178 region[2].data = salt;
179 region[2].size = salt_len;
180
181 ret = checksum->calculate(checksum->name, region, region_count, hprime);
182 if (ret < 0) {
183 debug("%s: Error in checksum calculation\n", __func__);
184 goto out;
185 }
186
187out:
188 return ret;
189}
190
Heiko Stuebner1944dc12020-06-18 16:23:26 +0200191/*
192 * padding_pss_verify() - verify the pss padding of a signature
193 *
SESA64442538945ac2022-03-09 01:27:17 -0800194 * Works with any salt length
Heiko Stuebner1944dc12020-06-18 16:23:26 +0200195 *
SESA644425732d2702022-03-09 01:27:16 -0800196 * msg is a concatenation of : masked_db + h + 0xbc
197 * Once unmasked, db is a concatenation of : [0x00]* + 0x01 + salt
198 * Length of 0-padding at begin of db depends on salt length.
199 *
Heiko Stuebner1944dc12020-06-18 16:23:26 +0200200 * @info: Specifies key and FIT information
201 * @msg: byte array of message, len equal to msg_len
202 * @msg_len: Message length
203 * @hash: Pointer to the expected hash
204 * @hash_len: Length of the hash
Heinrich Schuchardtdf5117a2022-08-31 21:13:40 +0200205 *
206 * Return: 0 if padding is correct, non-zero otherwise
Heiko Stuebner1944dc12020-06-18 16:23:26 +0200207 */
Philippe Reynes47d73f02018-11-14 13:51:01 +0100208int padding_pss_verify(struct image_sign_info *info,
SESA6444251304b462022-03-09 01:27:15 -0800209 const uint8_t *msg, int msg_len,
Philippe Reynes47d73f02018-11-14 13:51:01 +0100210 const uint8_t *hash, int hash_len)
211{
SESA644425732d2702022-03-09 01:27:16 -0800212 const uint8_t *masked_db = NULL;
Philippe Reynes47d73f02018-11-14 13:51:01 +0100213 uint8_t *db_mask = NULL;
SESA644425732d2702022-03-09 01:27:16 -0800214 uint8_t *db = NULL;
215 int db_len = msg_len - hash_len - 1;
216 const uint8_t *h = NULL;
217 uint8_t *hprime = NULL;
218 int h_len = hash_len;
SESA64442538945ac2022-03-09 01:27:17 -0800219 uint8_t *db_nopad = NULL, *salt = NULL;
220 int db_padlen, salt_len;
Philippe Reynes47d73f02018-11-14 13:51:01 +0100221 uint8_t pad_zero[8] = { 0 };
222 int ret, i, leftmost_bits = 1;
223 uint8_t leftmost_mask;
224 struct checksum_algo *checksum = info->checksum;
225
Heinrich Schuchardtdf5117a2022-08-31 21:13:40 +0200226 if (db_len <= 0)
227 return -EINVAL;
228
Philippe Reynes47d73f02018-11-14 13:51:01 +0100229 /* first, allocate everything */
SESA644425732d2702022-03-09 01:27:16 -0800230 db_mask = malloc(db_len);
Philippe Reynes47d73f02018-11-14 13:51:01 +0100231 db = malloc(db_len);
Philippe Reynes47d73f02018-11-14 13:51:01 +0100232 hprime = malloc(hash_len);
SESA644425732d2702022-03-09 01:27:16 -0800233 if (!db_mask || !db || !hprime) {
Philippe Reynes47d73f02018-11-14 13:51:01 +0100234 printf("%s: can't allocate some buffer\n", __func__);
235 ret = -ENOMEM;
236 goto out;
237 }
238
239 /* step 4: check if the last byte is 0xbc */
240 if (msg[msg_len - 1] != 0xbc) {
241 printf("%s: invalid pss padding (0xbc is missing)\n", __func__);
242 ret = -EINVAL;
243 goto out;
244 }
245
246 /* step 5 */
SESA644425732d2702022-03-09 01:27:16 -0800247 masked_db = &msg[0];
248 h = &msg[db_len];
Philippe Reynes47d73f02018-11-14 13:51:01 +0100249
250 /* step 6 */
251 leftmost_mask = (0xff >> (8 - leftmost_bits)) << (8 - leftmost_bits);
252 if (masked_db[0] & leftmost_mask) {
253 printf("%s: invalid pss padding ", __func__);
254 printf("(leftmost bit of maskedDB not zero)\n");
255 ret = -EINVAL;
256 goto out;
257 }
258
259 /* step 7 */
SESA644425732d2702022-03-09 01:27:16 -0800260 mask_generation_function1(checksum, h, h_len, db_mask, db_len);
Philippe Reynes47d73f02018-11-14 13:51:01 +0100261
262 /* step 8 */
263 for (i = 0; i < db_len; i++)
264 db[i] = masked_db[i] ^ db_mask[i];
265
266 /* step 9 */
267 db[0] &= 0xff >> leftmost_bits;
268
269 /* step 10 */
SESA64442538945ac2022-03-09 01:27:17 -0800270 db_padlen = 0;
271 while (db[db_padlen] == 0x00 && db_padlen < (db_len - 1))
272 db_padlen++;
273 db_nopad = &db[db_padlen];
274 if (db_nopad[0] != 0x01) {
Philippe Reynes47d73f02018-11-14 13:51:01 +0100275 printf("%s: invalid pss padding ", __func__);
SESA64442538945ac2022-03-09 01:27:17 -0800276 printf("(leftmost byte of db after 0-padding isn't 0x01)\n");
Philippe Reynes47d73f02018-11-14 13:51:01 +0100277 ret = EINVAL;
278 goto out;
279 }
280
281 /* step 11 */
SESA64442538945ac2022-03-09 01:27:17 -0800282 salt_len = db_len - db_padlen - 1;
283 salt = &db_nopad[1];
Philippe Reynes47d73f02018-11-14 13:51:01 +0100284
285 /* step 12 & 13 */
286 compute_hash_prime(checksum, pad_zero, 8,
SESA6444251304b462022-03-09 01:27:15 -0800287 hash, hash_len,
Philippe Reynes47d73f02018-11-14 13:51:01 +0100288 salt, salt_len, hprime);
289
290 /* step 14 */
291 ret = memcmp(h, hprime, hash_len);
292
293out:
294 free(hprime);
Philippe Reynes47d73f02018-11-14 13:51:01 +0100295 free(db);
296 free(db_mask);
Philippe Reynes47d73f02018-11-14 13:51:01 +0100297
298 return ret;
299}
Alexandru Gagniucf3b5e582021-08-18 17:49:02 -0500300
301#ifndef USE_HOSTCC
302U_BOOT_PADDING_ALGO(pss) = {
303 .name = "pss",
304 .verify = padding_pss_verify,
305};
306#endif
307
Philippe Reynes47d73f02018-11-14 13:51:01 +0100308#endif
309
Andrew Duda3db9ff02016-11-08 18:53:40 +0000310/**
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530311 * rsa_verify_key() - Verify a signature against some data using RSA Key
Simon Glass35191a32013-06-13 15:10:02 -0700312 *
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530313 * Verify a RSA PKCS1.5 signature against an expected hash using
314 * the RSA Key properties in prop structure.
Simon Glass35191a32013-06-13 15:10:02 -0700315 *
Philippe Reynes12468352018-11-14 13:51:00 +0100316 * @info: Specifies key and FIT information
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530317 * @prop: Specifies key
318 * @sig: Signature
319 * @sig_len: Number of bytes in signature
320 * @hash: Pointer to the expected hash
Andrew Duda06ca6d62016-11-08 18:53:41 +0000321 * @key_len: Number of bytes in rsa key
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100322 * Return: 0 if verified, -ve on error
Simon Glass35191a32013-06-13 15:10:02 -0700323 */
Philippe Reynes12468352018-11-14 13:51:00 +0100324static int rsa_verify_key(struct image_sign_info *info,
325 struct key_prop *prop, const uint8_t *sig,
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100326 const uint32_t sig_len, const uint8_t *hash,
Philippe Reynes12468352018-11-14 13:51:00 +0100327 const uint32_t key_len)
Simon Glass35191a32013-06-13 15:10:02 -0700328{
Simon Glass35191a32013-06-13 15:10:02 -0700329 int ret;
Ruchika Guptaa0d3ca62015-01-23 16:01:54 +0530330#if !defined(USE_HOSTCC)
331 struct udevice *mod_exp_dev;
332#endif
Philippe Reynes12468352018-11-14 13:51:00 +0100333 struct checksum_algo *checksum = info->checksum;
334 struct padding_algo *padding = info->padding;
Philippe Reynes42332272019-03-19 10:55:40 +0100335 int hash_len;
Simon Glass35191a32013-06-13 15:10:02 -0700336
Philippe Reynesfd40a9b2021-10-15 11:28:47 +0200337 if (!prop || !sig || !hash || !checksum || !padding)
Simon Glass35191a32013-06-13 15:10:02 -0700338 return -EIO;
339
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530340 if (sig_len != (prop->num_bits / 8)) {
Simon Glass35191a32013-06-13 15:10:02 -0700341 debug("Signature is of incorrect length %d\n", sig_len);
342 return -EINVAL;
343 }
344
Philippe Reynes12468352018-11-14 13:51:00 +0100345 debug("Checksum algorithm: %s", checksum->name);
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100346
Simon Glass35191a32013-06-13 15:10:02 -0700347 /* Sanity check for stack size */
348 if (sig_len > RSA_MAX_SIG_BITS / 8) {
349 debug("Signature length %u exceeds maximum %d\n", sig_len,
350 RSA_MAX_SIG_BITS / 8);
351 return -EINVAL;
352 }
353
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530354 uint8_t buf[sig_len];
Philippe Reynes42332272019-03-19 10:55:40 +0100355 hash_len = checksum->checksum_len;
Simon Glass35191a32013-06-13 15:10:02 -0700356
Ruchika Guptaa0d3ca62015-01-23 16:01:54 +0530357#if !defined(USE_HOSTCC)
358 ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
359 if (ret) {
360 printf("RSA: Can't find Modular Exp implementation\n");
361 return -EINVAL;
362 }
363
364 ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
365#else
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530366 ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
Ruchika Guptaa0d3ca62015-01-23 16:01:54 +0530367#endif
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530368 if (ret) {
369 debug("Error in Modular exponentation\n");
Simon Glass35191a32013-06-13 15:10:02 -0700370 return ret;
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530371 }
Simon Glass35191a32013-06-13 15:10:02 -0700372
Philippe Reynes12468352018-11-14 13:51:00 +0100373 ret = padding->verify(info, buf, key_len, hash, hash_len);
Andrew Duda3db9ff02016-11-08 18:53:40 +0000374 if (ret) {
Philippe Reynes12468352018-11-14 13:51:00 +0100375 debug("In RSAVerify(): padding check failed!\n");
376 return ret;
Simon Glass35191a32013-06-13 15:10:02 -0700377 }
378
379 return 0;
380}
381
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900382/**
383 * rsa_verify_with_pkey() - Verify a signature against some data using
384 * only modulus and exponent as RSA key properties.
385 * @info: Specifies key information
386 * @hash: Pointer to the expected hash
387 * @sig: Signature
388 * @sig_len: Number of bytes in signature
389 *
390 * Parse a RSA public key blob in DER format pointed to in @info and fill
391 * a key_prop structure with properties of the key. Then verify a RSA PKCS1.5
392 * signature against an expected hash using the calculated properties.
393 *
394 * Return 0 if verified, -ve on error
395 */
AKASHI Takahiro30962bf2020-06-16 14:26:48 +0900396int rsa_verify_with_pkey(struct image_sign_info *info,
397 const void *hash, uint8_t *sig, uint sig_len)
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900398{
399 struct key_prop *prop;
400 int ret;
401
Simon Glasseffa4522021-09-25 19:43:23 -0600402 if (!CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY))
403 return -EACCES;
404
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900405 /* Public key is self-described to fill key_prop */
406 ret = rsa_gen_key_prop(info->key, info->keylen, &prop);
407 if (ret) {
408 debug("Generating necessary parameter for decoding failed\n");
409 return ret;
410 }
411
412 ret = rsa_verify_key(info, prop, sig, sig_len, hash,
413 info->crypto->key_len);
414
415 rsa_free_key_prop(prop);
416
417 return ret;
418}
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900419
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900420#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530421/**
422 * rsa_verify_with_keynode() - Verify a signature against some data using
423 * information in node with prperties of RSA Key like modulus, exponent etc.
424 *
425 * Parse sign-node and fill a key_prop structure with properties of the
426 * key. Verify a RSA PKCS1.5 signature against an expected hash using
427 * the properties parsed
428 *
429 * @info: Specifies key and FIT information
430 * @hash: Pointer to the expected hash
431 * @sig: Signature
432 * @sig_len: Number of bytes in signature
433 * @node: Node having the RSA Key properties
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100434 * Return: 0 if verified, -ve on error
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530435 */
Simon Glass35191a32013-06-13 15:10:02 -0700436static int rsa_verify_with_keynode(struct image_sign_info *info,
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530437 const void *hash, uint8_t *sig,
438 uint sig_len, int node)
Simon Glass35191a32013-06-13 15:10:02 -0700439{
440 const void *blob = info->fdt_blob;
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530441 struct key_prop prop;
Michael van der Westhuizen89f4ed12014-07-02 10:17:26 +0200442 int length;
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530443 int ret = 0;
Matthieu CASTET335b01c2020-09-23 19:11:44 +0200444 const char *algo;
Simon Glass35191a32013-06-13 15:10:02 -0700445
446 if (node < 0) {
447 debug("%s: Skipping invalid node", __func__);
448 return -EBADF;
449 }
Simon Glass35191a32013-06-13 15:10:02 -0700450
Matthieu CASTET335b01c2020-09-23 19:11:44 +0200451 algo = fdt_getprop(blob, node, "algo", NULL);
Sean Andersonb6710802021-02-16 11:40:15 -0500452 if (strcmp(info->name, algo)) {
453 debug("%s: Wrong algo: have %s, expected %s", __func__,
454 info->name, algo);
Matthieu CASTET335b01c2020-09-23 19:11:44 +0200455 return -EFAULT;
Sean Andersonb6710802021-02-16 11:40:15 -0500456 }
Matthieu CASTET335b01c2020-09-23 19:11:44 +0200457
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530458 prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
Simon Glass35191a32013-06-13 15:10:02 -0700459
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530460 prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
Simon Glass35191a32013-06-13 15:10:02 -0700461
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530462 prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
463 if (!prop.public_exponent || length < sizeof(uint64_t))
464 prop.public_exponent = NULL;
465
466 prop.exp_len = sizeof(uint64_t);
467
468 prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
469
470 prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
471
Jan Kiszka3637b8b2020-05-07 20:36:13 +0200472 if (!prop.num_bits || !prop.modulus || !prop.rr) {
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530473 debug("%s: Missing RSA key info", __func__);
474 return -EFAULT;
Simon Glass35191a32013-06-13 15:10:02 -0700475 }
476
Philippe Reynes12468352018-11-14 13:51:00 +0100477 ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
478 info->crypto->key_len);
Ruchika Guptab92ebab2015-01-23 16:01:50 +0530479
480 return ret;
Simon Glass35191a32013-06-13 15:10:02 -0700481}
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900482#else
483static int rsa_verify_with_keynode(struct image_sign_info *info,
484 const void *hash, uint8_t *sig,
485 uint sig_len, int node)
486{
487 return -EACCES;
488}
489#endif
Simon Glass35191a32013-06-13 15:10:02 -0700490
Heiko Stuebnerb4044092020-05-22 16:20:33 +0200491int rsa_verify_hash(struct image_sign_info *info,
492 const uint8_t *hash, uint8_t *sig, uint sig_len)
Simon Glass35191a32013-06-13 15:10:02 -0700493{
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900494 int ret = -EACCES;
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100495
Tom Rini18a5bd02022-12-06 13:51:21 -0500496 /*
497 * Since host tools, like mkimage, make use of openssl library for
498 * RSA encryption, rsa_verify_with_pkey()/rsa_gen_key_prop() are
499 * of no use and should not be compiled in.
500 */
501 if (!tools_build() && CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY) &&
502 !info->fdt_blob) {
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900503 /* don't rely on fdt properties */
504 ret = rsa_verify_with_pkey(info, hash, sig, sig_len);
Simon Glass101d3492021-11-12 12:28:02 -0700505 if (ret)
506 debug("%s: rsa_verify_with_pkey() failed\n", __func__);
AKASHI Takahiro75822f42020-02-21 15:12:59 +0900507 return ret;
508 }
509
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900510 if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
511 const void *blob = info->fdt_blob;
512 int ndepth, noffset;
513 int sig_node, node;
514 char name[100];
Simon Glass35191a32013-06-13 15:10:02 -0700515
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900516 sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
517 if (sig_node < 0) {
518 debug("%s: No signature node found\n", __func__);
519 return -ENOENT;
520 }
Simon Glass35191a32013-06-13 15:10:02 -0700521
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900522 /* See if we must use a particular key */
523 if (info->required_keynode != -1) {
Simon Glass35191a32013-06-13 15:10:02 -0700524 ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900525 info->required_keynode);
Simon Glass101d3492021-11-12 12:28:02 -0700526 if (ret)
527 debug("%s: Failed to verify required_keynode\n",
528 __func__);
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900529 return ret;
530 }
531
532 /* Look for a key that matches our hint */
533 snprintf(name, sizeof(name), "key-%s", info->keyname);
534 node = fdt_subnode_offset(blob, sig_node, name);
535 ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
536 if (!ret)
537 return ret;
Simon Glass101d3492021-11-12 12:28:02 -0700538 debug("%s: Could not verify key '%s', trying all\n", __func__,
539 name);
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900540
541 /* No luck, so try each of the keys in turn */
Philippe Reynes7258c3f2021-01-12 19:18:54 +0100542 for (ndepth = 0, noffset = fdt_next_node(blob, sig_node,
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900543 &ndepth);
544 (noffset >= 0) && (ndepth > 0);
Philippe Reynes7258c3f2021-01-12 19:18:54 +0100545 noffset = fdt_next_node(blob, noffset, &ndepth)) {
AKASHI Takahiro2223c7d2020-02-21 15:12:55 +0900546 if (ndepth == 1 && noffset != node) {
547 ret = rsa_verify_with_keynode(info, hash,
548 sig, sig_len,
549 noffset);
550 if (!ret)
551 break;
552 }
Simon Glass35191a32013-06-13 15:10:02 -0700553 }
554 }
Simon Glass101d3492021-11-12 12:28:02 -0700555 debug("%s: Failed to verify by any means\n", __func__);
Simon Glass35191a32013-06-13 15:10:02 -0700556
557 return ret;
558}
Heiko Stuebnerb4044092020-05-22 16:20:33 +0200559
560int rsa_verify(struct image_sign_info *info,
561 const struct image_region region[], int region_count,
562 uint8_t *sig, uint sig_len)
563{
564 /* Reserve memory for maximum checksum-length */
565 uint8_t hash[info->crypto->key_len];
Heinrich Schuchardt574fab92020-10-08 20:53:13 +0200566 int ret;
Heiko Stuebnerb4044092020-05-22 16:20:33 +0200567
568 /*
569 * Verify that the checksum-length does not exceed the
570 * rsa-signature-length
571 */
572 if (info->checksum->checksum_len >
573 info->crypto->key_len) {
Thomas Perrot4e1e2a22021-07-19 16:04:44 +0200574 debug("%s: invalid checksum-algorithm %s for %s\n",
Heiko Stuebnerb4044092020-05-22 16:20:33 +0200575 __func__, info->checksum->name, info->crypto->name);
576 return -EINVAL;
577 }
578
579 /* Calculate checksum with checksum-algorithm */
580 ret = info->checksum->calculate(info->checksum->name,
581 region, region_count, hash);
582 if (ret < 0) {
583 debug("%s: Error in checksum calculation\n", __func__);
584 return -EINVAL;
585 }
586
587 return rsa_verify_hash(info, hash, sig, sig_len);
588}
Alexandru Gagniuc92c5fdc2021-07-14 17:05:40 -0500589
590#ifndef USE_HOSTCC
591
592U_BOOT_CRYPTO_ALGO(rsa2048) = {
593 .name = "rsa2048",
594 .key_len = RSA2048_BYTES,
595 .verify = rsa_verify,
596};
597
Jamin Lin5975ad72022-01-19 16:23:21 +0800598U_BOOT_CRYPTO_ALGO(rsa3072) = {
599 .name = "rsa3072",
600 .key_len = RSA3072_BYTES,
601 .verify = rsa_verify,
602};
603
Alexandru Gagniuc92c5fdc2021-07-14 17:05:40 -0500604U_BOOT_CRYPTO_ALGO(rsa4096) = {
605 .name = "rsa4096",
606 .key_len = RSA4096_BYTES,
607 .verify = rsa_verify,
608};
609
610#endif