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
19int 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
40int 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
116int 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