1 /* Copyright 2014 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Signature validation functions
6 */
7
8 #include "2common.h"
9 #include "2rsa.h"
10 #include "2sha.h"
11 #include "2sysincludes.h"
12 #include "host_common21.h"
13
vb21_common_desc(const void * buf)14 const char *vb21_common_desc(const void *buf)
15 {
16 const struct vb21_struct_common *c = buf;
17
18 return c->desc_size ? (const char *)c + c->fixed_size : "";
19 }
20
vb21_verify_common_header(const void * parent,uint32_t parent_size)21 vb2_error_t vb21_verify_common_header(const void *parent, uint32_t parent_size)
22 {
23 const struct vb21_struct_common *c = parent;
24
25 /* Parent buffer size must be at least the claimed total size */
26 if (parent_size < c->total_size)
27 return VB2_ERROR_COMMON_TOTAL_SIZE;
28
29 /*
30 * And big enough for the fixed size, which itself must be at least as
31 * big as the common struct header.
32 */
33 if (c->total_size < c->fixed_size || c->fixed_size < sizeof(*c))
34 return VB2_ERROR_COMMON_FIXED_SIZE;
35
36 /* Make sure sizes are all multiples of 32 bits */
37 if (!vb2_aligned(c->total_size, sizeof(uint32_t)))
38 return VB2_ERROR_COMMON_TOTAL_UNALIGNED;
39 if (!vb2_aligned(c->fixed_size, sizeof(uint32_t)))
40 return VB2_ERROR_COMMON_FIXED_UNALIGNED;
41 if (!vb2_aligned(c->desc_size, sizeof(uint32_t)))
42 return VB2_ERROR_COMMON_DESC_UNALIGNED;
43
44 /* Check description */
45 if (c->desc_size > 0) {
46 /* Make sure description fits and doesn't wrap */
47 if (c->fixed_size + c->desc_size < c->fixed_size)
48 return VB2_ERROR_COMMON_DESC_WRAPS;
49 if (c->fixed_size + c->desc_size > c->total_size)
50 return VB2_ERROR_COMMON_DESC_SIZE;
51
52 /* Description must be null-terminated */
53 if (vb21_common_desc(c)[c->desc_size - 1] != 0)
54 return VB2_ERROR_COMMON_DESC_TERMINATOR;
55 }
56
57 return VB2_SUCCESS;
58 }
59
vb21_verify_common_member(const void * parent,uint32_t * min_offset,uint32_t member_offset,uint32_t member_size)60 vb2_error_t vb21_verify_common_member(const void *parent, uint32_t *min_offset,
61 uint32_t member_offset,
62 uint32_t member_size)
63 {
64 const struct vb21_struct_common *c = parent;
65 uint32_t member_end = member_offset + member_size;
66
67 /* Make sure member doesn't wrap */
68 if (member_end < member_offset)
69 return VB2_ERROR_COMMON_MEMBER_WRAPS;
70
71 /* Member offset and size must be 32-bit aligned */
72 if (!vb2_aligned(member_offset, sizeof(uint32_t)) ||
73 !vb2_aligned(member_size, sizeof(uint32_t)))
74 return VB2_ERROR_COMMON_MEMBER_UNALIGNED;
75
76 /* Initialize minimum offset if necessary */
77 if (!*min_offset)
78 *min_offset = c->fixed_size + c->desc_size;
79
80 /* Member must be after minimum offset */
81 if (member_offset < *min_offset)
82 return VB2_ERROR_COMMON_MEMBER_OVERLAP;
83
84 /* Member must end before total size */
85 if (member_end > c->total_size)
86 return VB2_ERROR_COMMON_MEMBER_SIZE;
87
88 /* Update minimum offset for subsequent checks */
89 *min_offset = member_end;
90
91 return VB2_SUCCESS;
92 }
93
vb21_verify_common_subobject(const void * parent,uint32_t * min_offset,uint32_t member_offset)94 vb2_error_t vb21_verify_common_subobject(const void *parent,
95 uint32_t *min_offset,
96 uint32_t member_offset)
97 {
98 const struct vb21_struct_common *p = parent;
99 const struct vb21_struct_common *m =
100 (const struct vb21_struct_common *)
101 ((const uint8_t *)parent + member_offset);
102 vb2_error_t rv;
103
104 /*
105 * Verify the parent has space at the member offset for the common
106 * header.
107 */
108 rv = vb21_verify_common_member(parent, min_offset, member_offset,
109 sizeof(*m));
110 if (rv)
111 return rv;
112
113 /*
114 * Now it's safe to look at the member's header, and verify any
115 * additional data for the object past its common header fits in the
116 * parent.
117 */
118 rv = vb21_verify_common_header(m, p->total_size - member_offset);
119 if (rv)
120 return rv;
121
122 /* Advance the min offset to the end of the subobject */
123 *min_offset = member_offset + m->total_size;
124
125 return VB2_SUCCESS;
126 }
127
vb2_sig_size(enum vb2_signature_algorithm sig_alg,enum vb2_hash_algorithm hash_alg)128 uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
129 enum vb2_hash_algorithm hash_alg)
130 {
131 uint32_t digest_size = vb2_digest_size(hash_alg);
132
133 /* Fail if we don't support the hash algorithm */
134 if (!digest_size)
135 return 0;
136
137 /* Handle unsigned hashes */
138 if (sig_alg == VB2_SIG_NONE)
139 return digest_size;
140
141 return vb2_rsa_sig_size(sig_alg);
142 }
143
vb2_hash_id(enum vb2_hash_algorithm hash_alg)144 const struct vb2_id *vb2_hash_id(enum vb2_hash_algorithm hash_alg)
145 {
146 switch(hash_alg) {
147 #ifdef VB2_SUPPORT_SHA1
148 case VB2_HASH_SHA1:
149 {
150 static const struct vb2_id id = VB2_ID_NONE_SHA1;
151 return &id;
152 }
153 #endif
154 #ifdef VB2_SUPPORT_SHA256
155 case VB2_HASH_SHA256:
156 {
157 static const struct vb2_id id = VB2_ID_NONE_SHA256;
158 return &id;
159 }
160 #endif
161 #ifdef VB2_SUPPORT_SHA512
162 case VB2_HASH_SHA512:
163 {
164 static const struct vb2_id id = VB2_ID_NONE_SHA512;
165 return &id;
166 }
167 #endif
168 default:
169 return NULL;
170 }
171 }
172
vb21_verify_signature(const struct vb21_signature * sig,uint32_t size)173 vb2_error_t vb21_verify_signature(const struct vb21_signature *sig,
174 uint32_t size)
175 {
176 uint32_t min_offset = 0;
177 uint32_t expect_sig_size;
178 vb2_error_t rv;
179
180 /* Check magic number */
181 if (sig->c.magic != VB21_MAGIC_SIGNATURE)
182 return VB2_ERROR_SIG_MAGIC;
183
184 /* Make sure common header is good */
185 rv = vb21_verify_common_header(sig, size);
186 if (rv)
187 return rv;
188
189 /*
190 * Check for compatible version. No need to check minor version, since
191 * that's compatible across readers matching the major version, and we
192 * haven't added any new fields.
193 */
194 if (sig->c.struct_version_major != VB21_SIGNATURE_VERSION_MAJOR)
195 return VB2_ERROR_SIG_VERSION;
196
197 /* Make sure header is big enough for signature */
198 if (sig->c.fixed_size < sizeof(*sig))
199 return VB2_ERROR_SIG_HEADER_SIZE;
200
201 /* Make sure signature data is inside */
202 rv = vb21_verify_common_member(sig, &min_offset,
203 sig->sig_offset, sig->sig_size);
204 if (rv)
205 return rv;
206
207 /* Make sure signature size is correct for the algorithm */
208 expect_sig_size = vb2_sig_size(sig->sig_alg, sig->hash_alg);
209 if (!expect_sig_size)
210 return VB2_ERROR_SIG_ALGORITHM;
211 if (sig->sig_size != expect_sig_size)
212 return VB2_ERROR_SIG_SIZE;
213
214 return VB2_SUCCESS;
215 }
216
217 /**
218 * Return the signature data for a signature
219 */
vb21_signature_data(struct vb21_signature * sig)220 static uint8_t *vb21_signature_data(struct vb21_signature *sig)
221 {
222 return (uint8_t *)sig + sig->sig_offset;
223 }
224
vb21_verify_digest(const struct vb2_public_key * key,struct vb21_signature * sig,const uint8_t * digest,const struct vb2_workbuf * wb)225 vb2_error_t vb21_verify_digest(const struct vb2_public_key *key,
226 struct vb21_signature *sig,
227 const uint8_t *digest,
228 const struct vb2_workbuf *wb)
229 {
230 uint32_t key_sig_size = vb2_sig_size(key->sig_alg, key->hash_alg);
231
232 /* If we can't figure out the signature size, key algorithm was bad */
233 if (!key_sig_size)
234 return VB2_ERROR_VDATA_ALGORITHM;
235
236 /* Make sure the signature and key algorithms match */
237 if (key->sig_alg != sig->sig_alg || key->hash_alg != sig->hash_alg)
238 return VB2_ERROR_VDATA_ALGORITHM_MISMATCH;
239
240 if (sig->sig_size != key_sig_size)
241 return VB2_ERROR_VDATA_SIG_SIZE;
242
243 if (key->sig_alg == VB2_SIG_NONE) {
244 /* Bare hash */
245 if (vb2_safe_memcmp(vb21_signature_data(sig),
246 digest, key_sig_size))
247 return VB2_ERROR_VDATA_VERIFY_DIGEST;
248
249 return VB2_SUCCESS;
250 } else {
251 /* RSA-signed digest */
252 return vb2_rsa_verify_digest(key,
253 vb21_signature_data(sig),
254 digest, wb);
255 }
256 }
257
vb21_verify_data(const void * data,uint32_t size,struct vb21_signature * sig,const struct vb2_public_key * key,const struct vb2_workbuf * wb)258 vb2_error_t vb21_verify_data(const void *data, uint32_t size,
259 struct vb21_signature *sig,
260 const struct vb2_public_key *key,
261 const struct vb2_workbuf *wb)
262 {
263 struct vb2_workbuf wblocal = *wb;
264 struct vb2_digest_context *dc;
265 uint8_t *digest;
266 uint32_t digest_size;
267 vb2_error_t rv;
268
269 if (sig->data_size != size) {
270 VB2_DEBUG("Wrong amount of data signed.\n");
271 return VB2_ERROR_VDATA_SIZE;
272 }
273
274 /* Digest goes at start of work buffer */
275 digest_size = vb2_digest_size(key->hash_alg);
276 if (!digest_size)
277 return VB2_ERROR_VDATA_DIGEST_SIZE;
278
279 digest = vb2_workbuf_alloc(&wblocal, digest_size);
280 if (!digest)
281 return VB2_ERROR_VDATA_WORKBUF_DIGEST;
282
283 /* Hashing requires temp space for the context */
284 dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc));
285 if (!dc)
286 return VB2_ERROR_VDATA_WORKBUF_HASHING;
287
288 rv = vb2_digest_init(dc, false, key->hash_alg, 0);
289 if (rv)
290 return rv;
291
292 rv = vb2_digest_extend(dc, data, size);
293 if (rv)
294 return rv;
295
296 rv = vb2_digest_finalize(dc, digest, digest_size);
297 if (rv)
298 return rv;
299
300 vb2_workbuf_free(&wblocal, sizeof(*dc));
301
302 return vb21_verify_digest(key, sig, digest, &wblocal);
303 }
304