SPDX: Convert all of our single license tags to Linux Kernel style
[platform/kernel/u-boot.git] / lib / rsa / rsa-verify.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, Google Inc.
4  */
5
6 #ifndef USE_HOSTCC
7 #include <common.h>
8 #include <fdtdec.h>
9 #include <asm/types.h>
10 #include <asm/byteorder.h>
11 #include <linux/errno.h>
12 #include <asm/types.h>
13 #include <asm/unaligned.h>
14 #include <dm.h>
15 #else
16 #include "fdt_host.h"
17 #include "mkimage.h"
18 #include <fdt_support.h>
19 #endif
20 #include <u-boot/rsa-mod-exp.h>
21 #include <u-boot/rsa.h>
22
23 /* Default public exponent for backward compatibility */
24 #define RSA_DEFAULT_PUBEXP      65537
25
26 /**
27  * rsa_verify_padding() - Verify RSA message padding is valid
28  *
29  * Verify a RSA message's padding is consistent with PKCS1.5
30  * padding as described in the RSA PKCS#1 v2.1 standard.
31  *
32  * @msg:        Padded message
33  * @pad_len:    Number of expected padding bytes
34  * @algo:       Checksum algo structure having information on DER encoding etc.
35  * @return 0 on success, != 0 on failure
36  */
37 static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
38                               struct checksum_algo *algo)
39 {
40         int ff_len;
41         int ret;
42
43         /* first byte must be 0x00 */
44         ret = *msg++;
45         /* second byte must be 0x01 */
46         ret |= *msg++ ^ 0x01;
47         /* next ff_len bytes must be 0xff */
48         ff_len = pad_len - algo->der_len - 3;
49         ret |= *msg ^ 0xff;
50         ret |= memcmp(msg, msg+1, ff_len-1);
51         msg += ff_len;
52         /* next byte must be 0x00 */
53         ret |= *msg++;
54         /* next der_len bytes must match der_prefix */
55         ret |= memcmp(msg, algo->der_prefix, algo->der_len);
56
57         return ret;
58 }
59
60 /**
61  * rsa_verify_key() - Verify a signature against some data using RSA Key
62  *
63  * Verify a RSA PKCS1.5 signature against an expected hash using
64  * the RSA Key properties in prop structure.
65  *
66  * @prop:       Specifies key
67  * @sig:        Signature
68  * @sig_len:    Number of bytes in signature
69  * @hash:       Pointer to the expected hash
70  * @key_len:    Number of bytes in rsa key
71  * @algo:       Checksum algo structure having information on DER encoding etc.
72  * @return 0 if verified, -ve on error
73  */
74 static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
75                           const uint32_t sig_len, const uint8_t *hash,
76                           const uint32_t key_len, struct checksum_algo *algo)
77 {
78         int pad_len;
79         int ret;
80 #if !defined(USE_HOSTCC)
81         struct udevice *mod_exp_dev;
82 #endif
83
84         if (!prop || !sig || !hash || !algo)
85                 return -EIO;
86
87         if (sig_len != (prop->num_bits / 8)) {
88                 debug("Signature is of incorrect length %d\n", sig_len);
89                 return -EINVAL;
90         }
91
92         debug("Checksum algorithm: %s", algo->name);
93
94         /* Sanity check for stack size */
95         if (sig_len > RSA_MAX_SIG_BITS / 8) {
96                 debug("Signature length %u exceeds maximum %d\n", sig_len,
97                       RSA_MAX_SIG_BITS / 8);
98                 return -EINVAL;
99         }
100
101         uint8_t buf[sig_len];
102
103 #if !defined(USE_HOSTCC)
104         ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
105         if (ret) {
106                 printf("RSA: Can't find Modular Exp implementation\n");
107                 return -EINVAL;
108         }
109
110         ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
111 #else
112         ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
113 #endif
114         if (ret) {
115                 debug("Error in Modular exponentation\n");
116                 return ret;
117         }
118
119         pad_len = key_len - algo->checksum_len;
120
121         /* Check pkcs1.5 padding bytes. */
122         ret = rsa_verify_padding(buf, pad_len, algo);
123         if (ret) {
124                 debug("In RSAVerify(): Padding check failed!\n");
125                 return -EINVAL;
126         }
127
128         /* Check hash. */
129         if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
130                 debug("In RSAVerify(): Hash check failed!\n");
131                 return -EACCES;
132         }
133
134         return 0;
135 }
136
137 /**
138  * rsa_verify_with_keynode() - Verify a signature against some data using
139  * information in node with prperties of RSA Key like modulus, exponent etc.
140  *
141  * Parse sign-node and fill a key_prop structure with properties of the
142  * key.  Verify a RSA PKCS1.5 signature against an expected hash using
143  * the properties parsed
144  *
145  * @info:       Specifies key and FIT information
146  * @hash:       Pointer to the expected hash
147  * @sig:        Signature
148  * @sig_len:    Number of bytes in signature
149  * @node:       Node having the RSA Key properties
150  * @return 0 if verified, -ve on error
151  */
152 static int rsa_verify_with_keynode(struct image_sign_info *info,
153                                    const void *hash, uint8_t *sig,
154                                    uint sig_len, int node)
155 {
156         const void *blob = info->fdt_blob;
157         struct key_prop prop;
158         int length;
159         int ret = 0;
160
161         if (node < 0) {
162                 debug("%s: Skipping invalid node", __func__);
163                 return -EBADF;
164         }
165
166         prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
167
168         prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
169
170         prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
171         if (!prop.public_exponent || length < sizeof(uint64_t))
172                 prop.public_exponent = NULL;
173
174         prop.exp_len = sizeof(uint64_t);
175
176         prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
177
178         prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
179
180         if (!prop.num_bits || !prop.modulus) {
181                 debug("%s: Missing RSA key info", __func__);
182                 return -EFAULT;
183         }
184
185         ret = rsa_verify_key(&prop, sig, sig_len, hash,
186                              info->crypto->key_len, info->checksum);
187
188         return ret;
189 }
190
191 int rsa_verify(struct image_sign_info *info,
192                const struct image_region region[], int region_count,
193                uint8_t *sig, uint sig_len)
194 {
195         const void *blob = info->fdt_blob;
196         /* Reserve memory for maximum checksum-length */
197         uint8_t hash[info->crypto->key_len];
198         int ndepth, noffset;
199         int sig_node, node;
200         char name[100];
201         int ret;
202
203         /*
204          * Verify that the checksum-length does not exceed the
205          * rsa-signature-length
206          */
207         if (info->checksum->checksum_len >
208             info->crypto->key_len) {
209                 debug("%s: invlaid checksum-algorithm %s for %s\n",
210                       __func__, info->checksum->name, info->crypto->name);
211                 return -EINVAL;
212         }
213
214         sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
215         if (sig_node < 0) {
216                 debug("%s: No signature node found\n", __func__);
217                 return -ENOENT;
218         }
219
220         /* Calculate checksum with checksum-algorithm */
221         ret = info->checksum->calculate(info->checksum->name,
222                                         region, region_count, hash);
223         if (ret < 0) {
224                 debug("%s: Error in checksum calculation\n", __func__);
225                 return -EINVAL;
226         }
227
228         /* See if we must use a particular key */
229         if (info->required_keynode != -1) {
230                 ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
231                         info->required_keynode);
232                 if (!ret)
233                         return ret;
234         }
235
236         /* Look for a key that matches our hint */
237         snprintf(name, sizeof(name), "key-%s", info->keyname);
238         node = fdt_subnode_offset(blob, sig_node, name);
239         ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
240         if (!ret)
241                 return ret;
242
243         /* No luck, so try each of the keys in turn */
244         for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
245                         (noffset >= 0) && (ndepth > 0);
246                         noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
247                 if (ndepth == 1 && noffset != node) {
248                         ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
249                                                       noffset);
250                         if (!ret)
251                                 break;
252                 }
253         }
254
255         return ret;
256 }