blob: 7c253457853914d701c315a01b6912175ad7c197 [file] [log] [blame]
Randall Spangler6f1b82a2014-12-03 12:29:37 -08001/* 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
18int 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
39int 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 /*
Randall Spanglerb87d1ec2015-05-19 12:45:20 -070080 * Work buffer now contains:
81 * - vb2_shared_data
82 * - packed firmware data key
83 * - firmware preamble
84 * - hash data
85 */
86
87 /*
Randall Spangler6f1b82a2014-12-03 12:29:37 -080088 * Unpack the firmware data key to see which hashing algorithm we
89 * should use.
90 *
91 * TODO: really, the firmware body should be hashed, and not signed,
92 * because the signature we're checking is already signed as part of
93 * the firmware preamble. But until we can change the signing scripts,
94 * we're stuck with a signature here instead of a hash.
95 */
96 if (!sd->workbuf_data_key_size)
97 return VB2_ERROR_API_INIT_HASH_DATA_KEY;
98
99 rv = vb2_unpack_key(&key,
100 ctx->workbuf + sd->workbuf_data_key_offset,
101 sd->workbuf_data_key_size);
102 if (rv)
103 return rv;
104
105 sd->hash_tag = tag;
106 sd->hash_remaining_size = pre->body_signature.data_size;
107
108 if (size)
109 *size = pre->body_signature.data_size;
110
Julius Wernerf10e9092014-12-16 19:24:54 -0800111 if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) {
112 rv = vb2ex_hwcrypto_digest_init(key.hash_alg,
113 pre->body_signature.data_size);
114 if (!rv) {
115 VB2_DEBUG("Using HW crypto engine for hash_alg %d\n",
116 key.hash_alg);
117 dc->hash_alg = key.hash_alg;
118 dc->using_hwcrypto = 1;
119 return VB2_SUCCESS;
120 }
121 if (rv != VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED)
122 return rv;
123 VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n",
124 key.hash_alg);
125 } else {
126 VB2_DEBUG("HW crypto forbidden by preamble, using SW\n");
127 }
128
Randall Spangler6f1b82a2014-12-03 12:29:37 -0800129 return vb2_digest_init(dc, key.hash_alg);
130}
131
Aaron Durbin7cbd1ce2016-01-22 15:06:05 -0600132int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
133 uint32_t digest_out_size)
Randall Spangler6f1b82a2014-12-03 12:29:37 -0800134{
135 struct vb2_shared_data *sd = vb2_get_sd(ctx);
136 struct vb2_digest_context *dc = (struct vb2_digest_context *)
137 (ctx->workbuf + sd->workbuf_hash_offset);
138 struct vb2_workbuf wb;
139
140 uint8_t *digest;
141 uint32_t digest_size = vb2_digest_size(dc->hash_alg);
142
143 struct vb2_fw_preamble *pre;
144 struct vb2_public_key key;
145 int rv;
146
147 vb2_workbuf_from_ctx(ctx, &wb);
148
149 /* Get preamble pointer */
150 if (!sd->workbuf_preamble_size)
151 return VB2_ERROR_API_CHECK_HASH_PREAMBLE;
152 pre = (struct vb2_fw_preamble *)
153 (ctx->workbuf + sd->workbuf_preamble_offset);
154
155 /* Must have initialized hash digest work area */
156 if (!sd->workbuf_hash_size)
157 return VB2_ERROR_API_CHECK_HASH_WORKBUF;
158
159 /* Should have hashed the right amount of data */
160 if (sd->hash_remaining_size)
161 return VB2_ERROR_API_CHECK_HASH_SIZE;
162
163 /* Allocate the digest */
164 digest = vb2_workbuf_alloc(&wb, digest_size);
165 if (!digest)
166 return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST;
167
168 /* Finalize the digest */
Julius Wernerf10e9092014-12-16 19:24:54 -0800169 if (dc->using_hwcrypto)
170 rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size);
171 else
172 rv = vb2_digest_finalize(dc, digest, digest_size);
Randall Spangler6f1b82a2014-12-03 12:29:37 -0800173 if (rv)
174 return rv;
175
176 /* The code below is specific to the body signature */
177 if (sd->hash_tag != VB2_HASH_TAG_FW_BODY)
178 return VB2_ERROR_API_CHECK_HASH_TAG;
179
180 /*
181 * The body signature is currently a *signature* of the body data, not
182 * just its hash. So we need to verify the signature.
183 */
184
185 /* Unpack the data key */
186 if (!sd->workbuf_data_key_size)
187 return VB2_ERROR_API_CHECK_HASH_DATA_KEY;
188
189 rv = vb2_unpack_key(&key,
190 ctx->workbuf + sd->workbuf_data_key_offset,
191 sd->workbuf_data_key_size);
192 if (rv)
193 return rv;
194
195 /*
196 * Check digest vs. signature. Note that this destroys the signature.
197 * That's ok, because we only check each signature once per boot.
198 */
199 rv = vb2_verify_digest(&key, &pre->body_signature, digest, &wb);
200 if (rv)
Julius Werner187f0692015-02-10 17:08:22 -0800201 vb2_fail(ctx, VB2_RECOVERY_FW_BODY, rv);
Randall Spangler6f1b82a2014-12-03 12:29:37 -0800202
Aaron Durbin7cbd1ce2016-01-22 15:06:05 -0600203 if (digest_out != NULL) {
204 if (digest_out_size < digest_size)
205 return VB2_ERROR_API_CHECK_DIGEST_SIZE;
206 memcpy(digest_out, digest, digest_size);
207 }
208
Randall Spangler6f1b82a2014-12-03 12:29:37 -0800209 return rv;
210}
Aaron Durbin7cbd1ce2016-01-22 15:06:05 -0600211
212int vb2api_check_hash(struct vb2_context *ctx)
213{
214 return vb2api_check_hash_get_digest(ctx, NULL, 0);
215}