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 <asm/errno.h> 13 #include <asm/types.h> 14 #include <asm/unaligned.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_key() - Verify a signature against some data using RSA Key 28 * 29 * Verify a RSA PKCS1.5 signature against an expected hash using 30 * the RSA Key properties in prop structure. 31 * 32 * @prop: Specifies key 33 * @sig: Signature 34 * @sig_len: Number of bytes in signature 35 * @hash: Pointer to the expected hash 36 * @algo: Checksum algo structure having information on RSA padding etc. 37 * @return 0 if verified, -ve on error 38 */ 39 static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig, 40 const uint32_t sig_len, const uint8_t *hash, 41 struct checksum_algo *algo) 42 { 43 const uint8_t *padding; 44 int pad_len; 45 int ret; 46 47 if (!prop || !sig || !hash || !algo) 48 return -EIO; 49 50 if (sig_len != (prop->num_bits / 8)) { 51 debug("Signature is of incorrect length %d\n", sig_len); 52 return -EINVAL; 53 } 54 55 debug("Checksum algorithm: %s", algo->name); 56 57 /* Sanity check for stack size */ 58 if (sig_len > RSA_MAX_SIG_BITS / 8) { 59 debug("Signature length %u exceeds maximum %d\n", sig_len, 60 RSA_MAX_SIG_BITS / 8); 61 return -EINVAL; 62 } 63 64 uint8_t buf[sig_len]; 65 66 ret = rsa_mod_exp_sw(sig, sig_len, prop, buf); 67 if (ret) { 68 debug("Error in Modular exponentation\n"); 69 return ret; 70 } 71 72 padding = algo->rsa_padding; 73 pad_len = algo->pad_len - algo->checksum_len; 74 75 /* Check pkcs1.5 padding bytes. */ 76 if (memcmp(buf, padding, pad_len)) { 77 debug("In RSAVerify(): Padding check failed!\n"); 78 return -EINVAL; 79 } 80 81 /* Check hash. */ 82 if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) { 83 debug("In RSAVerify(): Hash check failed!\n"); 84 return -EACCES; 85 } 86 87 return 0; 88 } 89 90 /** 91 * rsa_verify_with_keynode() - Verify a signature against some data using 92 * information in node with prperties of RSA Key like modulus, exponent etc. 93 * 94 * Parse sign-node and fill a key_prop structure with properties of the 95 * key. Verify a RSA PKCS1.5 signature against an expected hash using 96 * the properties parsed 97 * 98 * @info: Specifies key and FIT information 99 * @hash: Pointer to the expected hash 100 * @sig: Signature 101 * @sig_len: Number of bytes in signature 102 * @node: Node having the RSA Key properties 103 * @return 0 if verified, -ve on error 104 */ 105 static int rsa_verify_with_keynode(struct image_sign_info *info, 106 const void *hash, uint8_t *sig, 107 uint sig_len, int node) 108 { 109 const void *blob = info->fdt_blob; 110 struct key_prop prop; 111 int length; 112 int ret = 0; 113 114 if (node < 0) { 115 debug("%s: Skipping invalid node", __func__); 116 return -EBADF; 117 } 118 119 prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0); 120 121 prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0); 122 123 prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length); 124 if (!prop.public_exponent || length < sizeof(uint64_t)) 125 prop.public_exponent = NULL; 126 127 prop.exp_len = sizeof(uint64_t); 128 129 prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL); 130 131 prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); 132 133 if (!prop.num_bits || !prop.modulus) { 134 debug("%s: Missing RSA key info", __func__); 135 return -EFAULT; 136 } 137 138 ret = rsa_verify_key(&prop, sig, sig_len, hash, info->algo->checksum); 139 140 return ret; 141 } 142 143 int rsa_verify(struct image_sign_info *info, 144 const struct image_region region[], int region_count, 145 uint8_t *sig, uint sig_len) 146 { 147 const void *blob = info->fdt_blob; 148 /* Reserve memory for maximum checksum-length */ 149 uint8_t hash[info->algo->checksum->pad_len]; 150 int ndepth, noffset; 151 int sig_node, node; 152 char name[100]; 153 int ret; 154 155 /* 156 * Verify that the checksum-length does not exceed the 157 * rsa-signature-length 158 */ 159 if (info->algo->checksum->checksum_len > 160 info->algo->checksum->pad_len) { 161 debug("%s: invlaid checksum-algorithm %s for %s\n", 162 __func__, info->algo->checksum->name, info->algo->name); 163 return -EINVAL; 164 } 165 166 sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); 167 if (sig_node < 0) { 168 debug("%s: No signature node found\n", __func__); 169 return -ENOENT; 170 } 171 172 /* Calculate checksum with checksum-algorithm */ 173 info->algo->checksum->calculate(region, region_count, hash); 174 175 /* See if we must use a particular key */ 176 if (info->required_keynode != -1) { 177 ret = rsa_verify_with_keynode(info, hash, sig, sig_len, 178 info->required_keynode); 179 if (!ret) 180 return ret; 181 } 182 183 /* Look for a key that matches our hint */ 184 snprintf(name, sizeof(name), "key-%s", info->keyname); 185 node = fdt_subnode_offset(blob, sig_node, name); 186 ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node); 187 if (!ret) 188 return ret; 189 190 /* No luck, so try each of the keys in turn */ 191 for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth); 192 (noffset >= 0) && (ndepth > 0); 193 noffset = fdt_next_node(info->fit, noffset, &ndepth)) { 194 if (ndepth == 1 && noffset != node) { 195 ret = rsa_verify_with_keynode(info, hash, sig, sig_len, 196 noffset); 197 if (!ret) 198 break; 199 } 200 } 201 202 return ret; 203 } 204