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  * Externally-callable APIs
      6  * (Firmware portion)
      7  */
      8 
      9 #include "2sysincludes.h"
     10 #include "2api.h"
     11 #include "2misc.h"
     12 #include "2nvstorage.h"
     13 #include "2secdata.h"
     14 #include "2sha.h"
     15 #include "2rsa.h"
     16 #include "vb2_common.h"
     17 
     18 int vb2api_fw_phase3(struct vb2_context *ctx)
     19 {
     20 	int rv;
     21 
     22 	/* Verify firmware keyblock */
     23 	rv = vb2_load_fw_keyblock(ctx);
     24 	if (rv) {
     25 		vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
     26 		return rv;
     27 	}
     28 
     29 	/* Verify firmware preamble */
     30 	rv = vb2_load_fw_preamble(ctx);
     31 	if (rv) {
     32 		vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
     33 		return rv;
     34 	}
     35 
     36 	return VB2_SUCCESS;
     37 }
     38 
     39 int vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, uint32_t *size)
     40 {
     41 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
     42 	const struct vb2_fw_preamble *pre;
     43 	struct vb2_digest_context *dc;
     44 	struct vb2_public_key key;
     45 	struct vb2_workbuf wb;
     46 	int rv;
     47 
     48 	vb2_workbuf_from_ctx(ctx, &wb);
     49 
     50 	if (tag == VB2_HASH_TAG_INVALID)
     51 		return VB2_ERROR_API_INIT_HASH_TAG;
     52 
     53 	/* Get preamble pointer */
     54 	if (!sd->workbuf_preamble_size)
     55 		return VB2_ERROR_API_INIT_HASH_PREAMBLE;
     56 	pre = (const struct vb2_fw_preamble *)
     57 		(ctx->workbuf + sd->workbuf_preamble_offset);
     58 
     59 	/* For now, we only support the firmware body tag */
     60 	if (tag != VB2_HASH_TAG_FW_BODY)
     61 		return VB2_ERROR_API_INIT_HASH_TAG;
     62 
     63 	/* Allocate workbuf space for the hash */
     64 	if (sd->workbuf_hash_size) {
     65 		dc = (struct vb2_digest_context *)
     66 			(ctx->workbuf + sd->workbuf_hash_offset);
     67 	} else {
     68 		uint32_t dig_size = sizeof(*dc);
     69 
     70 		dc = vb2_workbuf_alloc(&wb, dig_size);
     71 		if (!dc)
     72 			return VB2_ERROR_API_INIT_HASH_WORKBUF;
     73 
     74 		sd->workbuf_hash_offset = vb2_offset_of(ctx->workbuf, dc);
     75 		sd->workbuf_hash_size = dig_size;
     76 		ctx->workbuf_used = sd->workbuf_hash_offset + dig_size;
     77 	}
     78 
     79 	/*
     80 	 * Unpack the firmware data key to see which hashing algorithm we
     81 	 * should use.
     82 	 *
     83 	 * TODO: really, the firmware body should be hashed, and not signed,
     84 	 * because the signature we're checking is already signed as part of
     85 	 * the firmware preamble.  But until we can change the signing scripts,
     86 	 * we're stuck with a signature here instead of a hash.
     87 	 */
     88 	if (!sd->workbuf_data_key_size)
     89 		return VB2_ERROR_API_INIT_HASH_DATA_KEY;
     90 
     91 	rv = vb2_unpack_key(&key,
     92 			    ctx->workbuf + sd->workbuf_data_key_offset,
     93 			    sd->workbuf_data_key_size);
     94 	if (rv)
     95 		return rv;
     96 
     97 	sd->hash_tag = tag;
     98 	sd->hash_remaining_size = pre->body_signature.data_size;
     99 
    100 	if (size)
    101 		*size = pre->body_signature.data_size;
    102 
    103 	if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) {
    104 		rv = vb2ex_hwcrypto_digest_init(key.hash_alg,
    105 						pre->body_signature.data_size);
    106 		if (!rv) {
    107 			VB2_DEBUG("Using HW crypto engine for hash_alg %d\n",
    108 				  key.hash_alg);
    109 			dc->hash_alg = key.hash_alg;
    110 			dc->using_hwcrypto = 1;
    111 			return VB2_SUCCESS;
    112 		}
    113 		if (rv != VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED)
    114 			return rv;
    115 		VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n",
    116 			  key.hash_alg);
    117 	} else {
    118 		VB2_DEBUG("HW crypto forbidden by preamble, using SW\n");
    119 	}
    120 
    121 	return vb2_digest_init(dc, key.hash_alg);
    122 }
    123 
    124 int vb2api_check_hash(struct vb2_context *ctx)
    125 {
    126 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
    127 	struct vb2_digest_context *dc = (struct vb2_digest_context *)
    128 		(ctx->workbuf + sd->workbuf_hash_offset);
    129 	struct vb2_workbuf wb;
    130 
    131 	uint8_t *digest;
    132 	uint32_t digest_size = vb2_digest_size(dc->hash_alg);
    133 
    134 	struct vb2_fw_preamble *pre;
    135 	struct vb2_public_key key;
    136 	int rv;
    137 
    138 	vb2_workbuf_from_ctx(ctx, &wb);
    139 
    140 	/* Get preamble pointer */
    141 	if (!sd->workbuf_preamble_size)
    142 		return VB2_ERROR_API_CHECK_HASH_PREAMBLE;
    143 	pre = (struct vb2_fw_preamble *)
    144 		(ctx->workbuf + sd->workbuf_preamble_offset);
    145 
    146 	/* Must have initialized hash digest work area */
    147 	if (!sd->workbuf_hash_size)
    148 		return VB2_ERROR_API_CHECK_HASH_WORKBUF;
    149 
    150 	/* Should have hashed the right amount of data */
    151 	if (sd->hash_remaining_size)
    152 		return VB2_ERROR_API_CHECK_HASH_SIZE;
    153 
    154 	/* Allocate the digest */
    155 	digest = vb2_workbuf_alloc(&wb, digest_size);
    156 	if (!digest)
    157 		return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST;
    158 
    159 	/* Finalize the digest */
    160 	if (dc->using_hwcrypto)
    161 		rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size);
    162 	else
    163 		rv = vb2_digest_finalize(dc, digest, digest_size);
    164 	if (rv)
    165 		return rv;
    166 
    167 	/* The code below is specific to the body signature */
    168 	if (sd->hash_tag != VB2_HASH_TAG_FW_BODY)
    169 		return VB2_ERROR_API_CHECK_HASH_TAG;
    170 
    171 	/*
    172 	 * The body signature is currently a *signature* of the body data, not
    173 	 * just its hash.  So we need to verify the signature.
    174 	 */
    175 
    176 	/* Unpack the data key */
    177 	if (!sd->workbuf_data_key_size)
    178 		return VB2_ERROR_API_CHECK_HASH_DATA_KEY;
    179 
    180 	rv = vb2_unpack_key(&key,
    181 			    ctx->workbuf + sd->workbuf_data_key_offset,
    182 			    sd->workbuf_data_key_size);
    183 	if (rv)
    184 		return rv;
    185 
    186 	/*
    187 	 * Check digest vs. signature.  Note that this destroys the signature.
    188 	 * That's ok, because we only check each signature once per boot.
    189 	 */
    190 	rv = vb2_verify_digest(&key, &pre->body_signature, digest, &wb);
    191 	if (rv)
    192 		vb2_fail(ctx, VB2_RECOVERY_FW_BODY, rv);
    193 
    194 	return rv;
    195 }
    196