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