• 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  * 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 
vb2api_fw_phase3(struct vb2_context * ctx)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 
vb2api_init_hash(struct vb2_context * ctx,uint32_t tag,uint32_t * size)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 
vb2api_check_hash(struct vb2_context * ctx)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