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