Home | History | Annotate | Download | only in lib21
      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 "2common.h"
     12 #include "2misc.h"
     13 #include "2nvstorage.h"
     14 #include "2secdata.h"
     15 #include "2sha.h"
     16 #include "2rsa.h"
     17 #include "vb2_common.h"
     18 
     19 int vb2api_fw_phase3(struct vb2_context *ctx)
     20 {
     21 	int rv;
     22 
     23 	/* Verify firmware keyblock */
     24 	rv = vb2_load_fw_keyblock(ctx);
     25 	if (rv) {
     26 		vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
     27 		return rv;
     28 	}
     29 
     30 	/* Verify firmware preamble */
     31 	rv = vb2_load_fw_preamble(ctx);
     32 	if (rv) {
     33 		vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
     34 		return rv;
     35 	}
     36 
     37 	return VB2_SUCCESS;
     38 }
     39 
     40 int vb2api_init_hash2(struct vb2_context *ctx,
     41 		      const struct vb2_guid *guid,
     42 		      uint32_t *size)
     43 {
     44 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
     45 	const struct vb2_fw_preamble *pre;
     46 	const struct vb2_signature *sig = NULL;
     47 	struct vb2_digest_context *dc;
     48 	struct vb2_workbuf wb;
     49 	uint32_t hash_offset;
     50 	int i, rv;
     51 
     52 	vb2_workbuf_from_ctx(ctx, &wb);
     53 
     54 	/* Get preamble pointer */
     55 	if (!sd->workbuf_preamble_size)
     56 		return VB2_ERROR_API_INIT_HASH_PREAMBLE;
     57 	pre = (const struct vb2_fw_preamble *)
     58 		(ctx->workbuf + sd->workbuf_preamble_offset);
     59 
     60 	/* Find the matching signature */
     61 	hash_offset = pre->hash_offset;
     62 	for (i = 0; i < pre->hash_count; i++) {
     63 		sig = (const struct vb2_signature *)
     64 			((uint8_t *)pre + hash_offset);
     65 
     66 		if (!memcmp(guid, &sig->guid, sizeof(*guid)))
     67 			break;
     68 
     69 		hash_offset += sig->c.total_size;
     70 	}
     71 	if (i >= pre->hash_count)
     72 		return VB2_ERROR_API_INIT_HASH_GUID;  /* No match */
     73 
     74 	/* Allocate workbuf space for the hash */
     75 	if (sd->workbuf_hash_size) {
     76 		dc = (struct vb2_digest_context *)
     77 			(ctx->workbuf + sd->workbuf_hash_offset);
     78 	} else {
     79 		uint32_t dig_size = sizeof(*dc);
     80 
     81 		dc = vb2_workbuf_alloc(&wb, dig_size);
     82 		if (!dc)
     83 			return VB2_ERROR_API_INIT_HASH_WORKBUF;
     84 
     85 		sd->workbuf_hash_offset = vb2_offset_of(ctx->workbuf, dc);
     86 		sd->workbuf_hash_size = dig_size;
     87 		ctx->workbuf_used = sd->workbuf_hash_offset + dig_size;
     88 	}
     89 
     90 	sd->hash_tag = vb2_offset_of(ctx->workbuf, sig);
     91 	sd->hash_remaining_size = sig->data_size;
     92 
     93 	if (size)
     94 		*size = sig->data_size;
     95 
     96 	if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) {
     97 		rv = vb2ex_hwcrypto_digest_init(sig->hash_alg, sig->data_size);
     98 		if (!rv) {
     99 			VB2_DEBUG("Using HW crypto engine for hash_alg %d\n",
    100 				  sig->hash_alg);
    101 			dc->hash_alg = sig->hash_alg;
    102 			dc->using_hwcrypto = 1;
    103 			return VB2_SUCCESS;
    104 		}
    105 		if (rv != VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED)
    106 			return rv;
    107 		VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n",
    108 			  sig->hash_alg);
    109 	} else {
    110 		VB2_DEBUG("HW crypto forbidden by preamble, using SW\n");
    111 	}
    112 
    113 	return vb2_digest_init(dc, sig->hash_alg);
    114 }
    115 
    116 int vb2api_check_hash(struct vb2_context *ctx)
    117 {
    118 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
    119 	struct vb2_digest_context *dc = (struct vb2_digest_context *)
    120 		(ctx->workbuf + sd->workbuf_hash_offset);
    121 	struct vb2_workbuf wb;
    122 
    123 	uint8_t *digest;
    124 	uint32_t digest_size = vb2_digest_size(dc->hash_alg);
    125 
    126 	const struct vb2_signature *sig;
    127 
    128 	int rv;
    129 
    130 	vb2_workbuf_from_ctx(ctx, &wb);
    131 
    132 	/* Get signature pointer */
    133 	if (!sd->hash_tag)
    134 		return VB2_ERROR_API_CHECK_HASH_TAG;
    135 	sig = (const struct vb2_signature *)(ctx->workbuf + sd->hash_tag);
    136 
    137 	/* Must have initialized hash digest work area */
    138 	if (!sd->workbuf_hash_size)
    139 		return VB2_ERROR_API_CHECK_HASH_WORKBUF;
    140 
    141 	/* Should have hashed the right amount of data */
    142 	if (sd->hash_remaining_size)
    143 		return VB2_ERROR_API_CHECK_HASH_SIZE;
    144 
    145 	/* Allocate the digest */
    146 	digest = vb2_workbuf_alloc(&wb, digest_size);
    147 	if (!digest)
    148 		return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST;
    149 
    150 	/* Finalize the digest */
    151 	if (dc->using_hwcrypto)
    152 		rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size);
    153 	else
    154 		rv = vb2_digest_finalize(dc, digest, digest_size);
    155 	if (rv)
    156 		return rv;
    157 
    158 	/* Compare with the signature */
    159 	if (vb2_safe_memcmp(digest, (const uint8_t *)sig + sig->sig_offset,
    160 			    digest_size))
    161 		return VB2_ERROR_API_CHECK_HASH_SIG;
    162 
    163 	// TODO: the old check-hash function called vb2_fail() on any mismatch.
    164 	// I don't think it should do that; the caller should.
    165 
    166 	return VB2_SUCCESS;
    167 }
    168