blob: 099f7c1fdf5243436eb8696a396281ad0419e8a8 [file] [log] [blame]
Randall Spangler6b5b8f62014-10-31 15:18:48 -07001/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Signature validation functions
6 */
7
8#include "2sysincludes.h"
9#include "2common.h"
10#include "2rsa.h"
11#include "2sha.h"
12
13int vb2_verify_common_header(const void *parent, uint32_t parent_size)
14{
15 const struct vb2_struct_common *c = parent;
16
17 /* Parent buffer size must be at least the claimed total size */
18 if (parent_size < c->total_size)
19 return VB2_ERROR_COMMON_TOTAL_SIZE;
20
21 /*
22 * And big enough for the fixed size, which itself must be at least as
23 * big as the common struct header.
24 */
25 if (c->total_size < c->fixed_size || c->fixed_size < sizeof(*c))
26 return VB2_ERROR_COMMON_FIXED_SIZE;
27
28 /* Make sure sizes are all multiples of 32 bits */
29 if (!vb2_aligned(c->total_size, sizeof(uint32_t)))
30 return VB2_ERROR_COMMON_TOTAL_UNALIGNED;
31 if (!vb2_aligned(c->fixed_size, sizeof(uint32_t)))
32 return VB2_ERROR_COMMON_FIXED_UNALIGNED;
33 if (!vb2_aligned(c->desc_size, sizeof(uint32_t)))
34 return VB2_ERROR_COMMON_DESC_UNALIGNED;
35
36 /* Check description */
37 if (c->desc_size > 0) {
38 /* Make sure description fits and doesn't wrap */
39 if (c->fixed_size + c->desc_size < c->fixed_size)
40 return VB2_ERROR_COMMON_DESC_WRAPS;
41 if (c->fixed_size + c->desc_size > c->total_size)
42 return VB2_ERROR_COMMON_DESC_SIZE;
43
44 /* Description must be null-terminated */
45 const uint8_t *desc = (const uint8_t *)c + c->fixed_size;
46 if (desc[c->desc_size - 1] != 0)
47 return VB2_ERROR_COMMON_DESC_TERMINATOR;
48 }
49
50 return VB2_SUCCESS;
51}
52
53int vb2_verify_common_member(const void *parent,
54 uint32_t *min_offset,
55 uint32_t member_offset,
56 uint32_t member_size)
57{
58 const struct vb2_struct_common *c = parent;
59 uint32_t member_end = member_offset + member_size;
60
61 /* Make sure member doesn't wrap */
62 if (member_end < member_offset)
63 return VB2_ERROR_COMMON_MEMBER_WRAPS;
64
65 /* Member offset and size must be 32-bit aligned */
66 if (!vb2_aligned(member_offset, sizeof(uint32_t)) ||
67 !vb2_aligned(member_size, sizeof(uint32_t)))
68 return VB2_ERROR_COMMON_MEMBER_UNALIGNED;
69
70 /* Initialize minimum offset if necessary */
71 if (!*min_offset)
72 *min_offset = c->fixed_size + c->desc_size;
73
74 /* Member must be after minimum offset */
75 if (member_offset < *min_offset)
76 return VB2_ERROR_COMMON_MEMBER_OVERLAP;
77
78 /* Member must end before total size */
79 if (member_end > c->total_size)
80 return VB2_ERROR_COMMON_MEMBER_SIZE;
81
82 /* Update minimum offset for subsequent checks */
83 *min_offset = member_end;
84
85 return VB2_SUCCESS;
86}
87
88int vb2_verify_common_subobject(const void *parent,
89 uint32_t *min_offset,
90 uint32_t member_offset)
91{
92 const struct vb2_struct_common *p = parent;
93 const struct vb2_struct_common *m =
94 (const struct vb2_struct_common *)
95 ((const uint8_t *)parent + member_offset);
96 int rv;
97
98 /*
99 * Verify the parent has space at the member offset for the common
100 * header.
101 */
102 rv = vb2_verify_common_member(parent, min_offset, member_offset,
103 sizeof(*m));
104 if (rv)
105 return rv;
106
107 /*
108 * Now it's safe to look at the member's header, and verify any
109 * additional data for the object past its common header fits in the
110 * parent.
111 */
112 rv = vb2_verify_common_header(m, p->total_size - member_offset);
113 if (rv)
114 return rv;
115
116 /* Advance the min offset to the end of the subobject */
117 *min_offset = member_offset + m->total_size;
118
119 return VB2_SUCCESS;
120}
Randall Spanglerc0ce70b2014-10-31 11:19:14 -0700121
122uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
123 enum vb2_hash_algorithm hash_alg)
124{
125 uint32_t digest_size = vb2_digest_size(hash_alg);
126
127 /* Fail if we don't support the hash algorithm */
128 if (!digest_size)
129 return 0;
130
131 /* Handle unsigned hashes */
132 if (sig_alg == VB2_SIG_NONE)
133 return digest_size;
134
135 return vb2_rsa_sig_size(sig_alg);
136}
137
Randall Spanglerb885c3b2014-11-01 17:56:46 -0700138const struct vb2_guid *vb2_hash_guid(enum vb2_hash_algorithm hash_alg)
139{
140 switch(hash_alg) {
141#ifdef VB2_SUPPORT_SHA1
142 case VB2_HASH_SHA1:
143 {
144 static const struct vb2_guid guid = VB2_GUID_NONE_SHA1;
145 return &guid;
146 }
147#endif
148#ifdef VB2_SUPPORT_SHA256
149 case VB2_HASH_SHA256:
150 {
151 static const struct vb2_guid guid =
152 VB2_GUID_NONE_SHA256;
153 return &guid;
154 }
155#endif
156#ifdef VB2_SUPPORT_SHA512
157 case VB2_HASH_SHA512:
158 {
159 static const struct vb2_guid guid =
160 VB2_GUID_NONE_SHA512;
161 return &guid;
162 }
163#endif
164 default:
165 return NULL;
166 }
167}
168
Randall Spanglerc0ce70b2014-10-31 11:19:14 -0700169int vb2_verify_signature2(const struct vb2_signature2 *sig,
170 uint32_t size)
171{
172 uint32_t min_offset = 0;
173 uint32_t expect_sig_size;
174 int rv;
175
176 /* Check magic number */
177 if (sig->c.magic != VB2_MAGIC_SIGNATURE2)
178 return VB2_ERROR_SIG_MAGIC;
179
180 /* Make sure common header is good */
181 rv = vb2_verify_common_header(sig, size);
182 if (rv)
183 return rv;
184
185 /*
186 * Check for compatible version. No need to check minor version, since
187 * that's compatible across readers matching the major version, and we
188 * haven't added any new fields.
189 */
190 if (sig->c.struct_version_major != VB2_SIGNATURE2_VERSION_MAJOR)
191 return VB2_ERROR_SIG_VERSION;
192
193 /* Make sure header is big enough for signature */
194 if (sig->c.fixed_size < sizeof(*sig))
195 return VB2_ERROR_SIG_HEADER_SIZE;
196
197 /* Make sure signature data is inside */
198 rv = vb2_verify_common_member(sig, &min_offset,
199 sig->sig_offset, sig->sig_size);
200 if (rv)
201 return rv;
202
203 /* Make sure signature size is correct for the algorithm */
204 expect_sig_size = vb2_sig_size(sig->sig_alg, sig->hash_alg);
205 if (!expect_sig_size)
206 return VB2_ERROR_SIG_ALGORITHM;
207 if (sig->sig_size != expect_sig_size)
208 return VB2_ERROR_SIG_SIZE;
209
210 return VB2_SUCCESS;
211}
Randall Spanglerb885c3b2014-11-01 17:56:46 -0700212
213/**
214 * Return the signature data for a signature
215 */
216static uint8_t *vb2_signature2_data(struct vb2_signature2 *sig)
217{
218 return (uint8_t *)sig + sig->sig_offset;
219}
220
221int vb2_verify_digest2(const struct vb2_public_key *key,
222 struct vb2_signature2 *sig,
223 const uint8_t *digest,
Randall Spanglera063a432014-11-04 16:45:37 -0800224 const struct vb2_workbuf *wb)
Randall Spanglerb885c3b2014-11-01 17:56:46 -0700225{
226 uint32_t key_sig_size = vb2_sig_size(key->sig_alg, key->hash_alg);
227
228 /* If we can't figure out the signature size, key algorithm was bad */
229 if (!key_sig_size)
230 return VB2_ERROR_VDATA_ALGORITHM;
231
232 /* Make sure the signature and key algorithms match */
233 if (key->sig_alg != sig->sig_alg || key->hash_alg != sig->hash_alg)
234 return VB2_ERROR_VDATA_ALGORITHM_MISMATCH;
235
236 if (sig->sig_size != key_sig_size)
237 return VB2_ERROR_VDATA_SIG_SIZE;
238
239 if (key->sig_alg == VB2_SIG_NONE) {
240 /* Bare hash */
241 if (vb2_safe_memcmp(vb2_signature2_data(sig),
242 digest, key_sig_size))
243 return VB2_ERROR_VDATA_VERIFY_DIGEST;
244
245 return VB2_SUCCESS;
246 } else {
247 /* RSA-signed digest */
248 return vb2_rsa_verify_digest(key,
249 vb2_signature2_data(sig),
250 digest, wb);
251 }
252}
253
254int vb2_verify_data2(const void *data,
255 uint32_t size,
256 struct vb2_signature2 *sig,
257 const struct vb2_public_key *key,
Randall Spanglera063a432014-11-04 16:45:37 -0800258 const struct vb2_workbuf *wb)
Randall Spanglerb885c3b2014-11-01 17:56:46 -0700259{
260 struct vb2_workbuf wblocal = *wb;
261 struct vb2_digest_context *dc;
262 uint8_t *digest;
263 uint32_t digest_size;
264 int rv;
265
266 if (sig->data_size != size) {
267 VB2_DEBUG("Wrong amount of data signed.\n");
268 return VB2_ERROR_VDATA_SIZE;
269 }
270
271 /* Digest goes at start of work buffer */
272 digest_size = vb2_digest_size(key->hash_alg);
273 if (!digest_size)
274 return VB2_ERROR_VDATA_DIGEST_SIZE;
275
276 digest = vb2_workbuf_alloc(&wblocal, digest_size);
277 if (!digest)
278 return VB2_ERROR_VDATA_WORKBUF_DIGEST;
279
280 /* Hashing requires temp space for the context */
281 dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc));
282 if (!dc)
283 return VB2_ERROR_VDATA_WORKBUF_HASHING;
284
285 rv = vb2_digest_init(dc, key->hash_alg);
286 if (rv)
287 return rv;
288
289 rv = vb2_digest_extend(dc, data, size);
290 if (rv)
291 return rv;
292
293 rv = vb2_digest_finalize(dc, digest, digest_size);
294 if (rv)
295 return rv;
296
297 vb2_workbuf_free(&wblocal, sizeof(*dc));
298
299 return vb2_verify_digest2(key, sig, digest, &wblocal);
300}
Randall Spanglerad105ed2014-11-01 19:01:08 -0700301
302int vb2_verify_keyblock2(struct vb2_keyblock2 *block,
303 uint32_t size,
304 const struct vb2_public_key *key,
Randall Spanglera063a432014-11-04 16:45:37 -0800305 const struct vb2_workbuf *wb)
Randall Spanglerad105ed2014-11-01 19:01:08 -0700306{
307 uint32_t min_offset = 0, sig_offset;
308 int rv, i;
309
310 /* Check magic number */
311 if (block->c.magic != VB2_MAGIC_KEYBLOCK2)
312 return VB2_ERROR_KEYBLOCK_MAGIC;
313
314 /* Make sure common header is good */
315 rv = vb2_verify_common_header(block, size);
316 if (rv)
317 return rv;
318
319 /*
320 * Check for compatible version. No need to check minor version, since
321 * that's compatible across readers matching the major version, and we
322 * haven't added any new fields.
323 */
324 if (block->c.struct_version_major != VB2_KEYBLOCK2_VERSION_MAJOR)
325 return VB2_ERROR_KEYBLOCK_HEADER_VERSION;
326
327 /* Make sure header is big enough */
328 if (block->c.fixed_size < sizeof(*block))
329 return VB2_ERROR_KEYBLOCK_SIZE;
330
331 /* Make sure data key is inside */
332 rv = vb2_verify_common_subobject(block, &min_offset, block->key_offset);
333 if (rv)
334 return rv;
335
336 /* Loop over signatures */
337 sig_offset = block->sig_offset;
338 for (i = 0; i < block->sig_count; i++, sig_offset = min_offset) {
339 struct vb2_signature2 *sig;
340
341 /* Make sure signature is inside keyblock */
342 rv = vb2_verify_common_subobject(block, &min_offset,
343 sig_offset);
344 if (rv)
345 return rv;
346
347 sig = (struct vb2_signature2 *)((uint8_t *)block + sig_offset);
348
349 /* Verify the signature integrity */
350 rv = vb2_verify_signature2(sig,
351 block->c.total_size - sig_offset);
352 if (rv)
353 return rv;
354
355 /* Skip signature if it doesn't match the key GUID */
Randall Spanglerfe211722014-11-06 11:27:46 -0800356 if (memcmp(&sig->guid, key->guid, GUID_SIZE))
Randall Spanglerad105ed2014-11-01 19:01:08 -0700357 continue;
358
359 /* Make sure we signed the right amount of data */
360 if (sig->data_size != block->sig_offset)
361 return VB2_ERROR_KEYBLOCK_SIGNED_SIZE;
362
363 return vb2_verify_data2(block, block->sig_offset, sig, key, wb);
364 }
365
366 /* If we're still here, no signature matched the key GUID */
367 return VB2_ERROR_KEYBLOCK_SIG_GUID;
368}
Randall Spangler43e0a9e2014-11-04 17:50:32 -0800369
370int vb2_verify_fw_preamble2(struct vb2_fw_preamble2 *preamble,
371 uint32_t size,
372 const struct vb2_public_key *key,
373 const struct vb2_workbuf *wb)
374{
375 struct vb2_signature2 *sig;
376 uint32_t min_offset = 0, hash_offset;
377 int rv, i;
378
379 /* Check magic number */
380 if (preamble->c.magic != VB2_MAGIC_FW_PREAMBLE2)
381 return VB2_ERROR_PREAMBLE_MAGIC;
382
383 /* Make sure common header is good */
384 rv = vb2_verify_common_header(preamble, size);
385 if (rv)
386 return rv;
387
388 /*
389 * Check for compatible version. No need to check minor version, since
390 * that's compatible across readers matching the major version, and we
391 * haven't added any new fields.
392 */
393 if (preamble->c.struct_version_major != VB2_FW_PREAMBLE2_VERSION_MAJOR)
394 return VB2_ERROR_PREAMBLE_HEADER_VERSION;
395
396 /* Make sure header is big enough */
397 if (preamble->c.fixed_size < sizeof(*preamble))
398 return VB2_ERROR_PREAMBLE_SIZE;
399
400 /* Make sure all hash signatures are inside */
401 hash_offset = preamble->hash_offset;
402 for (i = 0; i < preamble->hash_count; i++, hash_offset = min_offset) {
403 /* Make sure signature is inside preamble */
404 rv = vb2_verify_common_subobject(preamble, &min_offset,
405 hash_offset);
406 if (rv)
407 return rv;
408
409 sig = (struct vb2_signature2 *)
410 ((uint8_t *)preamble + hash_offset);
411
412 /* Verify the signature integrity */
413 rv = vb2_verify_signature2(
414 sig, preamble->c.total_size - hash_offset);
415 if (rv)
416 return rv;
417
418 /* Hashes must all be unsigned */
419 if (sig->sig_alg != VB2_SIG_NONE)
420 return VB2_ERROR_PREAMBLE_HASH_SIGNED;
421 }
422
423 /* Make sure signature is inside preamble */
424 rv = vb2_verify_common_subobject(preamble, &min_offset,
425 preamble->sig_offset);
426 if (rv)
427 return rv;
428
429 /* Verify preamble signature */
430 sig = (struct vb2_signature2 *)((uint8_t *)preamble +
431 preamble->sig_offset);
432
433 rv = vb2_verify_data2(preamble, preamble->sig_offset, sig, key, wb);
434 if (rv)
435 return rv;
436
437 return VB2_SUCCESS;
438}