ee8988d646348220d4497c4ea4e0e50a446be422
[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  * @algo:       Checksum algo structure having information on RSA padding 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                           struct checksum_algo *algo)
77 {
78         const uint8_t *padding;
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 = algo->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, info->algo->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->algo->checksum->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->algo->checksum->checksum_len >
208             info->algo->checksum->key_len) {
209                 debug("%s: invlaid checksum-algorithm %s for %s\n",
210                       __func__, info->algo->checksum->name, info->algo->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->algo->checksum->calculate(info->algo->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 }