Blame view

lib/rsa/rsa-verify.c 6.59 KB
19c402afa   Simon Glass   image: Add RSA su...
1
2
3
  /*
   * Copyright (c) 2013, Google Inc.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
4
   * SPDX-License-Identifier:	GPL-2.0+
19c402afa   Simon Glass   image: Add RSA su...
5
   */
29a23f9d6   Heiko Schocher   tools, fit_check_...
6
  #ifndef USE_HOSTCC
19c402afa   Simon Glass   image: Add RSA su...
7
8
  #include <common.h>
  #include <fdtdec.h>
29a23f9d6   Heiko Schocher   tools, fit_check_...
9
  #include <asm/types.h>
19c402afa   Simon Glass   image: Add RSA su...
10
  #include <asm/byteorder.h>
1221ce459   Masahiro Yamada   treewide: replace...
11
  #include <linux/errno.h>
29a23f9d6   Heiko Schocher   tools, fit_check_...
12
  #include <asm/types.h>
19c402afa   Simon Glass   image: Add RSA su...
13
  #include <asm/unaligned.h>
c937ff6dc   Ruchika Gupta   lib/rsa: Modify r...
14
  #include <dm.h>
29a23f9d6   Heiko Schocher   tools, fit_check_...
15
16
17
18
19
  #else
  #include "fdt_host.h"
  #include "mkimage.h"
  #include <fdt_support.h>
  #endif
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
20
  #include <u-boot/rsa-mod-exp.h>
2b9912e6a   Jeroen Hofstee   includes: move op...
21
  #include <u-boot/rsa.h>
29a23f9d6   Heiko Schocher   tools, fit_check_...
22

e0f2f1553   Michael van der Westhuizen   Implement general...
23
24
  /* Default public exponent for backward compatibility */
  #define RSA_DEFAULT_PUBEXP	65537
19c402afa   Simon Glass   image: Add RSA su...
25
  /**
da29f2991   Andrew Duda   rsa: Verify RSA p...
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
   * rsa_verify_padding() - Verify RSA message padding is valid
   *
   * Verify a RSA message's padding is consistent with PKCS1.5
   * padding as described in the RSA PKCS#1 v2.1 standard.
   *
   * @msg:	Padded message
   * @pad_len:	Number of expected padding bytes
   * @algo:	Checksum algo structure having information on DER encoding etc.
   * @return 0 on success, != 0 on failure
   */
  static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
  			      struct checksum_algo *algo)
  {
  	int ff_len;
  	int ret;
  
  	/* first byte must be 0x00 */
  	ret = *msg++;
  	/* second byte must be 0x01 */
  	ret |= *msg++ ^ 0x01;
  	/* next ff_len bytes must be 0xff */
  	ff_len = pad_len - algo->der_len - 3;
  	ret |= *msg ^ 0xff;
  	ret |= memcmp(msg, msg+1, ff_len-1);
  	msg += ff_len;
  	/* next byte must be 0x00 */
  	ret |= *msg++;
  	/* next der_len bytes must match der_prefix */
  	ret |= memcmp(msg, algo->der_prefix, algo->der_len);
  
  	return ret;
  }
  
  /**
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
60
   * rsa_verify_key() - Verify a signature against some data using RSA Key
19c402afa   Simon Glass   image: Add RSA su...
61
   *
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
62
63
   * Verify a RSA PKCS1.5 signature against an expected hash using
   * the RSA Key properties in prop structure.
19c402afa   Simon Glass   image: Add RSA su...
64
   *
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
65
66
67
68
   * @prop:	Specifies key
   * @sig:	Signature
   * @sig_len:	Number of bytes in signature
   * @hash:	Pointer to the expected hash
0c1d74fda   Andrew Duda   image: Add crypto...
69
70
   * @key_len:	Number of bytes in rsa key
   * @algo:	Checksum algo structure having information on DER encoding etc.
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
71
   * @return 0 if verified, -ve on error
19c402afa   Simon Glass   image: Add RSA su...
72
   */
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
73
  static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
646257d1f   Heiko Schocher   rsa: add sha256-r...
74
  			  const uint32_t sig_len, const uint8_t *hash,
0c1d74fda   Andrew Duda   image: Add crypto...
75
  			  const uint32_t key_len, struct checksum_algo *algo)
19c402afa   Simon Glass   image: Add RSA su...
76
  {
19c402afa   Simon Glass   image: Add RSA su...
77
78
  	int pad_len;
  	int ret;
c937ff6dc   Ruchika Gupta   lib/rsa: Modify r...
79
80
81
  #if !defined(USE_HOSTCC)
  	struct udevice *mod_exp_dev;
  #endif
19c402afa   Simon Glass   image: Add RSA su...
82

fc2f4246b   Ruchika Gupta   rsa: Split the rs...
83
  	if (!prop || !sig || !hash || !algo)
19c402afa   Simon Glass   image: Add RSA su...
84
  		return -EIO;
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
85
  	if (sig_len != (prop->num_bits / 8)) {
19c402afa   Simon Glass   image: Add RSA su...
86
87
88
89
  		debug("Signature is of incorrect length %d
  ", sig_len);
  		return -EINVAL;
  	}
646257d1f   Heiko Schocher   rsa: add sha256-r...
90
  	debug("Checksum algorithm: %s", algo->name);
19c402afa   Simon Glass   image: Add RSA su...
91
92
93
94
95
96
97
  	/* Sanity check for stack size */
  	if (sig_len > RSA_MAX_SIG_BITS / 8) {
  		debug("Signature length %u exceeds maximum %d
  ", sig_len,
  		      RSA_MAX_SIG_BITS / 8);
  		return -EINVAL;
  	}
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
98
  	uint8_t buf[sig_len];
19c402afa   Simon Glass   image: Add RSA su...
99

c937ff6dc   Ruchika Gupta   lib/rsa: Modify r...
100
101
102
103
104
105
106
107
108
109
  #if !defined(USE_HOSTCC)
  	ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
  	if (ret) {
  		printf("RSA: Can't find Modular Exp implementation
  ");
  		return -EINVAL;
  	}
  
  	ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
  #else
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
110
  	ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
c937ff6dc   Ruchika Gupta   lib/rsa: Modify r...
111
  #endif
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
112
113
114
  	if (ret) {
  		debug("Error in Modular exponentation
  ");
19c402afa   Simon Glass   image: Add RSA su...
115
  		return ret;
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
116
  	}
19c402afa   Simon Glass   image: Add RSA su...
117

0c1d74fda   Andrew Duda   image: Add crypto...
118
  	pad_len = key_len - algo->checksum_len;
19c402afa   Simon Glass   image: Add RSA su...
119
120
  
  	/* Check pkcs1.5 padding bytes. */
da29f2991   Andrew Duda   rsa: Verify RSA p...
121
122
  	ret = rsa_verify_padding(buf, pad_len, algo);
  	if (ret) {
19c402afa   Simon Glass   image: Add RSA su...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  		debug("In RSAVerify(): Padding check failed!
  ");
  		return -EINVAL;
  	}
  
  	/* Check hash. */
  	if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
  		debug("In RSAVerify(): Hash check failed!
  ");
  		return -EACCES;
  	}
  
  	return 0;
  }
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  /**
   * rsa_verify_with_keynode() - Verify a signature against some data using
   * information in node with prperties of RSA Key like modulus, exponent etc.
   *
   * Parse sign-node and fill a key_prop structure with properties of the
   * key.  Verify a RSA PKCS1.5 signature against an expected hash using
   * the properties parsed
   *
   * @info:	Specifies key and FIT information
   * @hash:	Pointer to the expected hash
   * @sig:	Signature
   * @sig_len:	Number of bytes in signature
   * @node:	Node having the RSA Key properties
   * @return 0 if verified, -ve on error
   */
19c402afa   Simon Glass   image: Add RSA su...
152
  static int rsa_verify_with_keynode(struct image_sign_info *info,
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
153
154
  				   const void *hash, uint8_t *sig,
  				   uint sig_len, int node)
19c402afa   Simon Glass   image: Add RSA su...
155
156
  {
  	const void *blob = info->fdt_blob;
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
157
  	struct key_prop prop;
e0f2f1553   Michael van der Westhuizen   Implement general...
158
  	int length;
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
159
  	int ret = 0;
19c402afa   Simon Glass   image: Add RSA su...
160
161
162
163
164
  
  	if (node < 0) {
  		debug("%s: Skipping invalid node", __func__);
  		return -EBADF;
  	}
19c402afa   Simon Glass   image: Add RSA su...
165

fc2f4246b   Ruchika Gupta   rsa: Split the rs...
166
  	prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
19c402afa   Simon Glass   image: Add RSA su...
167

fc2f4246b   Ruchika Gupta   rsa: Split the rs...
168
  	prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
19c402afa   Simon Glass   image: Add RSA su...
169

fc2f4246b   Ruchika Gupta   rsa: Split the rs...
170
171
172
173
174
175
176
177
178
179
180
181
182
  	prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
  	if (!prop.public_exponent || length < sizeof(uint64_t))
  		prop.public_exponent = NULL;
  
  	prop.exp_len = sizeof(uint64_t);
  
  	prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
  
  	prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
  
  	if (!prop.num_bits || !prop.modulus) {
  		debug("%s: Missing RSA key info", __func__);
  		return -EFAULT;
19c402afa   Simon Glass   image: Add RSA su...
183
  	}
0c1d74fda   Andrew Duda   image: Add crypto...
184
  	ret = rsa_verify_key(&prop, sig, sig_len, hash,
83dd98e01   Andrew Duda   image: Combine im...
185
  			     info->crypto->key_len, info->checksum);
fc2f4246b   Ruchika Gupta   rsa: Split the rs...
186
187
  
  	return ret;
19c402afa   Simon Glass   image: Add RSA su...
188
189
190
191
192
193
194
  }
  
  int rsa_verify(struct image_sign_info *info,
  	       const struct image_region region[], int region_count,
  	       uint8_t *sig, uint sig_len)
  {
  	const void *blob = info->fdt_blob;
646257d1f   Heiko Schocher   rsa: add sha256-r...
195
  	/* Reserve memory for maximum checksum-length */
83dd98e01   Andrew Duda   image: Combine im...
196
  	uint8_t hash[info->crypto->key_len];
19c402afa   Simon Glass   image: Add RSA su...
197
198
199
  	int ndepth, noffset;
  	int sig_node, node;
  	char name[100];
646257d1f   Heiko Schocher   rsa: add sha256-r...
200
201
202
203
204
205
  	int ret;
  
  	/*
  	 * Verify that the checksum-length does not exceed the
  	 * rsa-signature-length
  	 */
83dd98e01   Andrew Duda   image: Combine im...
206
207
  	if (info->checksum->checksum_len >
  	    info->crypto->key_len) {
db1b5f3d2   Heiko Schocher   rsa: add sha256,r...
208
209
  		debug("%s: invlaid checksum-algorithm %s for %s
  ",
83dd98e01   Andrew Duda   image: Combine im...
210
  		      __func__, info->checksum->name, info->crypto->name);
646257d1f   Heiko Schocher   rsa: add sha256-r...
211
212
  		return -EINVAL;
  	}
19c402afa   Simon Glass   image: Add RSA su...
213
214
215
216
217
218
219
  
  	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
  	if (sig_node < 0) {
  		debug("%s: No signature node found
  ", __func__);
  		return -ENOENT;
  	}
646257d1f   Heiko Schocher   rsa: add sha256-r...
220
  	/* Calculate checksum with checksum-algorithm */
83dd98e01   Andrew Duda   image: Combine im...
221
  	ret = info->checksum->calculate(info->checksum->name,
b37b46f04   Ruchika Gupta   rsa: Use checksum...
222
223
224
225
226
227
  					region, region_count, hash);
  	if (ret < 0) {
  		debug("%s: Error in checksum calculation
  ", __func__);
  		return -EINVAL;
  	}
19c402afa   Simon Glass   image: Add RSA su...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  
  	/* See if we must use a particular key */
  	if (info->required_keynode != -1) {
  		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
  			info->required_keynode);
  		if (!ret)
  			return ret;
  	}
  
  	/* Look for a key that matches our hint */
  	snprintf(name, sizeof(name), "key-%s", info->keyname);
  	node = fdt_subnode_offset(blob, sig_node, name);
  	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
  	if (!ret)
  		return ret;
  
  	/* No luck, so try each of the keys in turn */
  	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
  			(noffset >= 0) && (ndepth > 0);
  			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
  		if (ndepth == 1 && noffset != node) {
  			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
  						      noffset);
  			if (!ret)
  				break;
  		}
  	}
  
  	return ret;
  }