• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
vb2_common_desc(const void * buf)14 const 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 
vb2_verify_common_header(const void * parent,uint32_t parent_size)21 int 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 
vb2_verify_common_member(const void * parent,uint32_t * min_offset,uint32_t member_offset,uint32_t member_size)60 int 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 
vb2_verify_common_subobject(const void * parent,uint32_t * min_offset,uint32_t member_offset)95 int 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 
vb2_sig_size(enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg)129 uint32_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 
vb2_hash_guid(enum vb2_hash_algorithm hash_alg)145 const 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 
vb2_verify_signature(const struct vb2_signature * sig,uint32_t size)176 int 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  */
vb2_signature_data(struct vb2_signature * sig)222 static uint8_t *vb2_signature_data(struct vb2_signature *sig)
223 {
224 	return (uint8_t *)sig + sig->sig_offset;
225 }
226 
vb2_verify_digest(const struct vb2_public_key * key,struct vb2_signature * sig,const uint8_t * digest,const struct vb2_workbuf * wb)227 int 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 
vb2_verify_data(const void * data,uint32_t size,struct vb2_signature * sig,const struct vb2_public_key * key,const struct vb2_workbuf * wb)260 int 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 
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)308 int 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 
vb2_verify_fw_preamble(struct vb2_fw_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)376 int 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