1
2
3
4
5
6
7
8
9
10
11#include "avb_rsa.h"
12#include "avb_sha.h"
13#include "avb_util.h"
14#include "avb_vbmeta_image.h"
15#include <malloc.h>
16
17typedef struct IAvbKey {
18 unsigned int len;
19 uint32_t n0inv;
20 uint32_t* n;
21 uint32_t* rr;
22} IAvbKey;
23
24static IAvbKey* iavb_parse_key_data(const uint8_t* data, size_t length) {
25 AvbRSAPublicKeyHeader h;
26 IAvbKey* key = NULL;
27 size_t expected_length;
28 unsigned int i;
29 const uint8_t* n;
30 const uint8_t* rr;
31
32 if (!avb_rsa_public_key_header_validate_and_byteswap(
33 (const AvbRSAPublicKeyHeader*)data, &h)) {
34 avb_error("Invalid key.\n");
35 goto fail;
36 }
37
38 if (!(h.key_num_bits == 2048 || h.key_num_bits == 4096 ||
39 h.key_num_bits == 8192)) {
40 avb_error("Unexpected key length.\n");
41 goto fail;
42 }
43
44 expected_length = sizeof(AvbRSAPublicKeyHeader) + 2 * h.key_num_bits / 8;
45 if (length != expected_length) {
46 avb_error("Key does not match expected length.\n");
47 goto fail;
48 }
49
50 n = data + sizeof(AvbRSAPublicKeyHeader);
51 rr = data + sizeof(AvbRSAPublicKeyHeader) + h.key_num_bits / 8;
52
53
54
55
56 key = (IAvbKey*)(avb_malloc(sizeof(IAvbKey) + 2 * h.key_num_bits / 8));
57 if (key == NULL) {
58 goto fail;
59 }
60
61 key->len = h.key_num_bits / 32;
62 key->n0inv = h.n0inv;
63 key->n = (uint32_t*)(key + 1);
64 key->rr = key->n + key->len;
65
66
67
68
69
70 for (i = 0; i < key->len; i++) {
71 key->n[i] = avb_be32toh(((uint32_t*)n)[key->len - i - 1]);
72 key->rr[i] = avb_be32toh(((uint32_t*)rr)[key->len - i - 1]);
73 }
74 return key;
75
76fail:
77 if (key != NULL) {
78 avb_free(key);
79 }
80 return NULL;
81}
82
83static void iavb_free_parsed_key(IAvbKey* key) {
84 avb_free(key);
85}
86
87
88static void subM(const IAvbKey* key, uint32_t* a) {
89 int64_t A = 0;
90 uint32_t i;
91 for (i = 0; i < key->len; ++i) {
92 A += (uint64_t)a[i] - key->n[i];
93 a[i] = (uint32_t)A;
94 A >>= 32;
95 }
96}
97
98
99static int geM(const IAvbKey* key, uint32_t* a) {
100 uint32_t i;
101 for (i = key->len; i;) {
102 --i;
103 if (a[i] < key->n[i]) {
104 return 0;
105 }
106 if (a[i] > key->n[i]) {
107 return 1;
108 }
109 }
110 return 1;
111}
112
113
114static void montMulAdd(const IAvbKey* key,
115 uint32_t* c,
116 const uint32_t a,
117 const uint32_t* b) {
118 uint64_t A = (uint64_t)a * b[0] + c[0];
119 uint32_t d0 = (uint32_t)A * key->n0inv;
120 uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
121 uint32_t i;
122
123 for (i = 1; i < key->len; ++i) {
124 A = (A >> 32) + (uint64_t)a * b[i] + c[i];
125 B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
126 c[i - 1] = (uint32_t)B;
127 }
128
129 A = (A >> 32) + (B >> 32);
130
131 c[i - 1] = (uint32_t)A;
132
133 if (A >> 32) {
134 subM(key, c);
135 }
136}
137
138
139static void montMul(const IAvbKey* key, uint32_t* c, uint32_t* a, uint32_t* b) {
140 uint32_t i;
141 for (i = 0; i < key->len; ++i) {
142 c[i] = 0;
143 }
144 for (i = 0; i < key->len; ++i) {
145 montMulAdd(key, c, a[i], b);
146 }
147}
148
149
150
151
152static void modpowF4(const IAvbKey* key, uint8_t* inout) {
153 uint32_t* a = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
154 uint32_t* aR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
155 uint32_t* aaR = (uint32_t*)avb_malloc(key->len * sizeof(uint32_t));
156 if (a == NULL || aR == NULL || aaR == NULL) {
157 goto out;
158 }
159
160 uint32_t* aaa = aaR;
161 int i;
162
163
164 for (i = 0; i < (int)key->len; ++i) {
165 uint32_t tmp = (inout[((key->len - 1 - i) * 4) + 0] << 24) |
166 (inout[((key->len - 1 - i) * 4) + 1] << 16) |
167 (inout[((key->len - 1 - i) * 4) + 2] << 8) |
168 (inout[((key->len - 1 - i) * 4) + 3] << 0);
169 a[i] = tmp;
170 }
171
172 montMul(key, aR, a, key->rr);
173 for (i = 0; i < 16; i += 2) {
174 montMul(key, aaR, aR, aR);
175 montMul(key, aR, aaR, aaR);
176 }
177 montMul(key, aaa, aR, a);
178
179
180 if (geM(key, aaa)) {
181 subM(key, aaa);
182 }
183
184
185 for (i = (int)key->len - 1; i >= 0; --i) {
186 uint32_t tmp = aaa[i];
187 *inout++ = (uint8_t)(tmp >> 24);
188 *inout++ = (uint8_t)(tmp >> 16);
189 *inout++ = (uint8_t)(tmp >> 8);
190 *inout++ = (uint8_t)(tmp >> 0);
191 }
192
193out:
194 if (a != NULL) {
195 avb_free(a);
196 }
197 if (aR != NULL) {
198 avb_free(aR);
199 }
200 if (aaR != NULL) {
201 avb_free(aaR);
202 }
203}
204
205
206
207
208bool avb_rsa_verify(const uint8_t* key,
209 size_t key_num_bytes,
210 const uint8_t* sig,
211 size_t sig_num_bytes,
212 const uint8_t* hash,
213 size_t hash_num_bytes,
214 const uint8_t* padding,
215 size_t padding_num_bytes) {
216 uint8_t* buf = NULL;
217 IAvbKey* parsed_key = NULL;
218 bool success = false;
219
220 if (key == NULL || sig == NULL || hash == NULL || padding == NULL) {
221 avb_error("Invalid input.\n");
222 goto out;
223 }
224
225 parsed_key = iavb_parse_key_data(key, key_num_bytes);
226 if (parsed_key == NULL) {
227 avb_error("Error parsing key.\n");
228 goto out;
229 }
230
231 if (sig_num_bytes != (parsed_key->len * sizeof(uint32_t))) {
232 avb_error("Signature length does not match key length.\n");
233 goto out;
234 }
235
236 if (padding_num_bytes != sig_num_bytes - hash_num_bytes) {
237 avb_error("Padding length does not match hash and signature lengths.\n");
238 goto out;
239 }
240
241 buf = (uint8_t*)avb_malloc(sig_num_bytes);
242 if (buf == NULL) {
243 avb_error("Error allocating memory.\n");
244 goto out;
245 }
246 avb_memcpy(buf, sig, sig_num_bytes);
247
248 modpowF4(parsed_key, buf);
249
250
251
252
253
254
255 if (avb_safe_memcmp(buf, padding, padding_num_bytes)) {
256 avb_error("Padding check failed.\n");
257 goto out;
258 }
259
260
261 if (avb_safe_memcmp(buf + padding_num_bytes, hash, hash_num_bytes)) {
262 avb_error("Hash check failed.\n");
263 goto out;
264 }
265
266 success = true;
267
268out:
269 if (parsed_key != NULL) {
270 iavb_free_parsed_key(parsed_key);
271 }
272 if (buf != NULL) {
273 avb_free(buf);
274 }
275 return success;
276}
277