Home | History | Annotate | Download | only in lib20
      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  * Common functions between firmware and kernel verified boot.
      6  * (Firmware portion)
      7  */
      8 
      9 #include "2sysincludes.h"
     10 #include "2rsa.h"
     11 #include "2sha.h"
     12 #include "vb2_common.h"
     13 
     14 uint8_t *vb2_signature_data(struct vb2_signature *sig)
     15 {
     16 	return (uint8_t *)sig + sig->sig_offset;
     17 }
     18 
     19 int vb2_verify_member_inside(const void *parent, size_t parent_size,
     20 			     const void *member, size_t member_size,
     21 			     ptrdiff_t member_data_offset,
     22 			     size_t member_data_size)
     23 {
     24 	const uintptr_t parent_end = (uintptr_t)parent + parent_size;
     25 	const ptrdiff_t member_offs = vb2_offset_of(parent, member);
     26 	const ptrdiff_t member_end_offs = member_offs + member_size;
     27 	const ptrdiff_t data_offs = member_offs + member_data_offset;
     28 	const ptrdiff_t data_end_offs = data_offs + member_data_size;
     29 
     30 	/* Make sure parent doesn't wrap */
     31 	if (parent_size < 0 || parent_end < (uintptr_t)parent)
     32 		return VB2_ERROR_INSIDE_PARENT_WRAPS;
     33 
     34 	/*
     35 	 * Make sure the member is fully contained in the parent and doesn't
     36 	 * wrap.  Use >, not >=, since member_size = 0 is possible.
     37 	 */
     38 	if (member_size < 0 || member_end_offs < member_offs)
     39 		return VB2_ERROR_INSIDE_MEMBER_WRAPS;
     40 	if (member_offs < 0 || member_offs > parent_size ||
     41 	    member_end_offs > parent_size)
     42 		return VB2_ERROR_INSIDE_MEMBER_OUTSIDE;
     43 
     44 	/* Make sure the member data is after the member */
     45 	if (member_data_size > 0 && data_offs < member_end_offs)
     46 		return VB2_ERROR_INSIDE_DATA_OVERLAP;
     47 
     48 	/* Make sure parent fully contains member data, if any */
     49 	if (member_data_size < 0 || data_end_offs < data_offs)
     50 		return VB2_ERROR_INSIDE_DATA_WRAPS;
     51 	if (data_offs < 0 || data_offs > parent_size ||
     52 	    data_end_offs > parent_size)
     53 		return VB2_ERROR_INSIDE_DATA_OUTSIDE;
     54 
     55 	return VB2_SUCCESS;
     56 }
     57 
     58 int vb2_verify_signature_inside(const void *parent,
     59 				uint32_t parent_size,
     60 				const struct vb2_signature *sig)
     61 {
     62 	return vb2_verify_member_inside(parent, parent_size,
     63 					sig, sizeof(*sig),
     64 					sig->sig_offset, sig->sig_size);
     65 }
     66 
     67 int vb2_verify_digest(const struct vb2_public_key *key,
     68 		      struct vb2_signature *sig,
     69 		      const uint8_t *digest,
     70 		      const struct vb2_workbuf *wb)
     71 {
     72 	uint8_t *sig_data = vb2_signature_data(sig);
     73 
     74 	if (sig->sig_size != vb2_rsa_sig_size(key->sig_alg)) {
     75 		VB2_DEBUG("Wrong data signature size for algorithm, "
     76 			  "sig_size=%d, expected %d for algorithm %d.\n",
     77 			  sig->sig_size, vb2_rsa_sig_size(key->sig_alg),
     78 			  key->sig_alg);
     79 		return VB2_ERROR_VDATA_SIG_SIZE;
     80 	}
     81 
     82 	return vb2_rsa_verify_digest(key, sig_data, digest, wb);
     83 }
     84 
     85 int vb2_verify_data(const uint8_t *data,
     86 		    uint32_t size,
     87 		    struct vb2_signature *sig,
     88 		    const struct vb2_public_key *key,
     89 		    const struct vb2_workbuf *wb)
     90 {
     91 	struct vb2_workbuf wblocal = *wb;
     92 	struct vb2_digest_context *dc;
     93 	uint8_t *digest;
     94 	uint32_t digest_size;
     95 	int rv;
     96 
     97 	if (sig->data_size > size) {
     98 		VB2_DEBUG("Data buffer smaller than length of signed data.\n");
     99 		return VB2_ERROR_VDATA_NOT_ENOUGH_DATA;
    100 	}
    101 
    102 	/* Digest goes at start of work buffer */
    103 	digest_size = vb2_digest_size(key->hash_alg);
    104 	if (!digest_size)
    105 		return VB2_ERROR_VDATA_DIGEST_SIZE;
    106 
    107 	digest = vb2_workbuf_alloc(&wblocal, digest_size);
    108 	if (!digest)
    109 		return VB2_ERROR_VDATA_WORKBUF_DIGEST;
    110 
    111 	/* Hashing requires temp space for the context */
    112 	dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc));
    113 	if (!dc)
    114 		return VB2_ERROR_VDATA_WORKBUF_HASHING;
    115 
    116 	rv = vb2_digest_init(dc, key->hash_alg);
    117 	if (rv)
    118 		return rv;
    119 
    120 	rv = vb2_digest_extend(dc, data, sig->data_size);
    121 	if (rv)
    122 		return rv;
    123 
    124 	rv = vb2_digest_finalize(dc, digest, digest_size);
    125 	if (rv)
    126 		return rv;
    127 
    128 	vb2_workbuf_free(&wblocal, sizeof(*dc));
    129 
    130 	return vb2_verify_digest(key, sig, digest, &wblocal);
    131 }
    132 
    133 int vb2_verify_keyblock(struct vb2_keyblock *block,
    134 			uint32_t size,
    135 			const struct vb2_public_key *key,
    136 			const struct vb2_workbuf *wb)
    137 {
    138 	struct vb2_signature *sig;
    139 	int rv;
    140 
    141 	/* Sanity checks before attempting signature of data */
    142 	if(size < sizeof(*block)) {
    143 		VB2_DEBUG("Not enough space for key block header.\n");
    144 		return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER;
    145 	}
    146 	if (memcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
    147 		VB2_DEBUG("Not a valid verified boot key block.\n");
    148 		return VB2_ERROR_KEYBLOCK_MAGIC;
    149 	}
    150 	if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
    151 		VB2_DEBUG("Incompatible key block header version.\n");
    152 		return VB2_ERROR_KEYBLOCK_HEADER_VERSION;
    153 	}
    154 	if (size < block->keyblock_size) {
    155 		VB2_DEBUG("Not enough data for key block.\n");
    156 		return VB2_ERROR_KEYBLOCK_SIZE;
    157 	}
    158 
    159 	/* Check signature */
    160 	sig = &block->keyblock_signature;
    161 
    162 	if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) {
    163 		VB2_DEBUG("Key block signature off end of block\n");
    164 		return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE;
    165 	}
    166 
    167 	/* Make sure advertised signature data sizes are sane. */
    168 	if (block->keyblock_size < sig->data_size) {
    169 		VB2_DEBUG("Signature calculated past end of block\n");
    170 		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH;
    171 	}
    172 
    173 	VB2_DEBUG("Checking key block signature...\n");
    174 	rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);
    175 	if (rv) {
    176 		VB2_DEBUG("Invalid key block signature.\n");
    177 		return VB2_ERROR_KEYBLOCK_SIG_INVALID;
    178 	}
    179 
    180 	/* Verify we signed enough data */
    181 	if (sig->data_size < sizeof(struct vb2_keyblock)) {
    182 		VB2_DEBUG("Didn't sign enough data\n");
    183 		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE;
    184 	}
    185 
    186 	/* Verify data key is inside the block and inside signed data */
    187 	if (vb2_verify_packed_key_inside(block, block->keyblock_size,
    188 					 &block->data_key)) {
    189 		VB2_DEBUG("Data key off end of key block\n");
    190 		return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE;
    191 	}
    192 	if (vb2_verify_packed_key_inside(block, sig->data_size,
    193 					 &block->data_key)) {
    194 		VB2_DEBUG("Data key off end of signed data\n");
    195 		return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED;
    196 	}
    197 
    198 	/* Success */
    199 	return VB2_SUCCESS;
    200 }
    201 
    202 int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
    203 			   uint32_t size,
    204 			   const struct vb2_public_key *key,
    205 			   const struct vb2_workbuf *wb)
    206 {
    207 	struct vb2_signature *sig = &preamble->preamble_signature;
    208 
    209 	VB2_DEBUG("Verifying preamble.\n");
    210 
    211 	/* Sanity checks before attempting signature of data */
    212 	if(size < sizeof(*preamble)) {
    213 		VB2_DEBUG("Not enough data for preamble header\n");
    214 		return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
    215 	}
    216 	if (preamble->header_version_major !=
    217 	    FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
    218 		VB2_DEBUG("Incompatible firmware preamble header version.\n");
    219 		return VB2_ERROR_PREAMBLE_HEADER_VERSION;
    220 	}
    221 
    222 	if (preamble->header_version_minor < 1) {
    223 		VB2_DEBUG("Only preamble header 2.1+ supported\n");
    224 		return VB2_ERROR_PREAMBLE_HEADER_OLD;
    225 	}
    226 
    227 	if (size < preamble->preamble_size) {
    228 		VB2_DEBUG("Not enough data for preamble.\n");
    229 		return VB2_ERROR_PREAMBLE_SIZE;
    230 	}
    231 
    232 	/* Check signature */
    233 	if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
    234 					sig)) {
    235 		VB2_DEBUG("Preamble signature off end of preamble\n");
    236 		return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
    237 	}
    238 
    239 	/* Make sure advertised signature data sizes are sane. */
    240 	if (preamble->preamble_size < sig->data_size) {
    241 		VB2_DEBUG("Signature calculated past end of the block\n");
    242 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
    243 	}
    244 
    245 	if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
    246 		VB2_DEBUG("Preamble signature validation failed\n");
    247 		return VB2_ERROR_PREAMBLE_SIG_INVALID;
    248 	}
    249 
    250 	/* Verify we signed enough data */
    251 	if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
    252 		VB2_DEBUG("Didn't sign enough data\n");
    253 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
    254 	}
    255 
    256 	/* Verify body signature is inside the signed data */
    257 	if (vb2_verify_signature_inside(preamble, sig->data_size,
    258 					&preamble->body_signature)) {
    259 		VB2_DEBUG("Firmware body signature off end of preamble\n");
    260 		return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
    261 	}
    262 
    263 	/* Verify kernel subkey is inside the signed data */
    264 	if (vb2_verify_packed_key_inside(preamble, sig->data_size,
    265 					 &preamble->kernel_subkey)) {
    266 		VB2_DEBUG("Kernel subkey off end of preamble\n");
    267 		return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE;
    268 	}
    269 
    270 	/* Success */
    271 	return VB2_SUCCESS;
    272 }
    273