]>
Commit | Line | Data |
---|---|---|
5ad29c54 AE |
1 | /* |
2 | * Written by Rob Stradling (rob@comodo.com) and Stephen Henson | |
3 | * (steve@openssl.org) for the OpenSSL project 2014. | |
4 | */ | |
5 | /* ==================================================================== | |
6 | * Copyright (c) 2014 The OpenSSL Project. All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in | |
17 | * the documentation and/or other materials provided with the | |
18 | * distribution. | |
19 | * | |
20 | * 3. All advertising materials mentioning features or use of this | |
21 | * software must display the following acknowledgment: | |
22 | * "This product includes software developed by the OpenSSL Project | |
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 | * | |
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 | * endorse or promote products derived from this software without | |
27 | * prior written permission. For written permission, please contact | |
28 | * licensing@OpenSSL.org. | |
29 | * | |
30 | * 5. Products derived from this software may not be called "OpenSSL" | |
31 | * nor may "OpenSSL" appear in their names without prior written | |
32 | * permission of the OpenSSL Project. | |
33 | * | |
34 | * 6. Redistributions of any form whatsoever must retain the following | |
35 | * acknowledgment: | |
36 | * "This product includes software developed by the OpenSSL Project | |
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 | * ==================================================================== | |
52 | * | |
53 | * This product includes cryptographic software written by Eric Young | |
54 | * (eay@cryptsoft.com). This product includes software written by Tim | |
55 | * Hudson (tjh@cryptsoft.com). | |
56 | * | |
57 | */ | |
5ad29c54 | 58 | |
0cea8832 RP |
59 | #ifdef OPENSSL_NO_CT |
60 | # error "CT is disabled" | |
61 | #endif | |
5ad29c54 | 62 | |
0cea8832 RP |
63 | #include <limits.h> |
64 | #include <string.h> | |
65 | ||
66 | #include <openssl/asn1.h> | |
67 | #include <openssl/buffer.h> | |
68 | #include <openssl/ct.h> | |
69 | #include <openssl/err.h> | |
70 | ||
71 | #include "ct_locl.h" | |
72 | ||
73 | #define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \ | |
74 | (((unsigned int)((c)[1])) )),c+=2) | |
75 | ||
76 | #define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ | |
77 | c[1]=(unsigned char)(((s) )&0xff)),c+=2) | |
5ad29c54 | 78 | |
0cea8832 RP |
79 | #define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \ |
80 | l|=((uint64_t)(*((c)++)))<<48, \ | |
81 | l|=((uint64_t)(*((c)++)))<<40, \ | |
82 | l|=((uint64_t)(*((c)++)))<<32, \ | |
83 | l|=((uint64_t)(*((c)++)))<<24, \ | |
84 | l|=((uint64_t)(*((c)++)))<<16, \ | |
85 | l|=((uint64_t)(*((c)++)))<< 8, \ | |
86 | l|=((uint64_t)(*((c)++)))) | |
87 | ||
88 | #define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ | |
89 | *((c)++)=(unsigned char)(((l)>>48)&0xff), \ | |
90 | *((c)++)=(unsigned char)(((l)>>40)&0xff), \ | |
91 | *((c)++)=(unsigned char)(((l)>>32)&0xff), \ | |
92 | *((c)++)=(unsigned char)(((l)>>24)&0xff), \ | |
93 | *((c)++)=(unsigned char)(((l)>>16)&0xff), \ | |
94 | *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ | |
95 | *((c)++)=(unsigned char)(((l) )&0xff)) | |
5ad29c54 AE |
96 | |
97 | int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len) | |
98 | { | |
99 | size_t siglen; | |
100 | size_t len_remaining = len; | |
101 | const unsigned char *p = *in; | |
102 | ||
0cea8832 | 103 | if (sct->version != SCT_VERSION_V1) { |
5ad29c54 AE |
104 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); |
105 | return -1; | |
106 | } | |
107 | /* | |
108 | * digitally-signed struct header: (1 byte) Hash algorithm (1 byte) | |
109 | * Signature algorithm (2 bytes + ?) Signature | |
110 | * | |
111 | * This explicitly rejects empty signatures: they're invalid for | |
112 | * all supported algorithms. | |
113 | */ | |
114 | if (len <= 4) { | |
115 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | |
116 | return -1; | |
117 | } | |
118 | ||
119 | /* Get hash and signature algorithm */ | |
120 | sct->hash_alg = *p++; | |
121 | sct->sig_alg = *p++; | |
122 | if (SCT_get_signature_nid(sct) == NID_undef) { | |
123 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | |
124 | return -1; | |
125 | } | |
126 | /* Retrieve signature and check it is consistent with the buffer length */ | |
127 | n2s(p, siglen); | |
128 | len_remaining -= (p - *in); | |
129 | if (siglen > len_remaining) { | |
130 | CTerr(CT_F_O2I_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); | |
131 | return -1; | |
132 | } | |
133 | ||
134 | if (SCT_set1_signature(sct, p, siglen) != 1) | |
135 | return -1; | |
136 | len_remaining -= siglen; | |
137 | *in = p + siglen; | |
138 | ||
139 | return len - len_remaining; | |
140 | } | |
141 | ||
142 | SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len) | |
143 | { | |
144 | SCT *sct = NULL; | |
145 | const unsigned char *p; | |
146 | ||
147 | if (len == 0 || len > MAX_SCT_SIZE) { | |
148 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | |
149 | goto err; | |
150 | } | |
151 | ||
152 | if ((sct = SCT_new()) == NULL) | |
153 | goto err; | |
154 | ||
155 | p = *in; | |
156 | ||
157 | sct->version = *p; | |
0cea8832 | 158 | if (sct->version == SCT_VERSION_V1) { |
5ad29c54 AE |
159 | int sig_len; |
160 | size_t len2; | |
161 | /* | |
162 | * Fixed-length header: struct { (1 byte) Version sct_version; (32 | |
163 | * bytes) log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) | |
164 | * CtExtensions extensions; | |
165 | */ | |
166 | if (len < 43) { | |
167 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | |
168 | goto err; | |
169 | } | |
170 | len -= 43; | |
171 | p++; | |
0cea8832 | 172 | sct->log_id = BUF_memdup(p, CT_V1_HASHLEN); |
5ad29c54 AE |
173 | if (sct->log_id == NULL) |
174 | goto err; | |
0cea8832 RP |
175 | sct->log_id_len = CT_V1_HASHLEN; |
176 | p += CT_V1_HASHLEN; | |
5ad29c54 AE |
177 | |
178 | n2l8(p, sct->timestamp); | |
179 | ||
180 | n2s(p, len2); | |
181 | if (len < len2) { | |
182 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | |
183 | goto err; | |
184 | } | |
185 | if (len2 > 0) { | |
186 | sct->ext = BUF_memdup(p, len2); | |
187 | if (sct->ext == NULL) | |
188 | goto err; | |
189 | } | |
190 | sct->ext_len = len2; | |
191 | p += len2; | |
192 | len -= len2; | |
193 | ||
194 | sig_len = o2i_SCT_signature(sct, &p, len); | |
195 | if (sig_len <= 0) { | |
196 | CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); | |
197 | goto err; | |
198 | } | |
199 | len -= sig_len; | |
200 | *in = p + len; | |
201 | } else { | |
202 | /* If not V1 just cache encoding */ | |
203 | sct->sct = BUF_memdup(p, len); | |
204 | if (sct->sct == NULL) | |
205 | goto err; | |
206 | sct->sct_len = len; | |
207 | *in = p + len; | |
208 | } | |
209 | ||
210 | if (psct != NULL) { | |
211 | SCT_free(*psct); | |
212 | *psct = sct; | |
213 | } | |
214 | ||
215 | return sct; | |
216 | err: | |
217 | SCT_free(sct); | |
218 | return NULL; | |
219 | } | |
220 | ||
221 | int i2o_SCT_signature(const SCT *sct, unsigned char **out) | |
222 | { | |
223 | size_t len; | |
224 | unsigned char *p = NULL; | |
225 | ||
0cea8832 | 226 | if (!SCT_signature_is_complete(sct)) { |
5ad29c54 AE |
227 | CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_SCT_INVALID_SIGNATURE); |
228 | goto err; | |
229 | } | |
230 | ||
0cea8832 | 231 | if (sct->version != SCT_VERSION_V1) { |
5ad29c54 AE |
232 | CTerr(CT_F_I2O_SCT_SIGNATURE, CT_R_UNSUPPORTED_VERSION); |
233 | goto err; | |
234 | } | |
235 | ||
236 | /* | |
237 | * (1 byte) Hash algorithm | |
238 | * (1 byte) Signature algorithm | |
239 | * (2 bytes + ?) Signature | |
240 | */ | |
241 | len = 4 + sct->sig_len; | |
242 | ||
243 | if (out != NULL) { | |
244 | if (*out != NULL) { | |
245 | p = *out; | |
246 | *out += len; | |
247 | } else { | |
248 | p = OPENSSL_malloc(len); | |
249 | if (p == NULL) { | |
250 | CTerr(CT_F_I2O_SCT_SIGNATURE, ERR_R_MALLOC_FAILURE); | |
251 | goto err; | |
252 | } | |
253 | *out = p; | |
254 | } | |
255 | ||
256 | *p++ = sct->hash_alg; | |
257 | *p++ = sct->sig_alg; | |
258 | s2n(sct->sig_len, p); | |
259 | memcpy(p, sct->sig, sct->sig_len); | |
260 | } | |
261 | ||
262 | return len; | |
263 | err: | |
264 | OPENSSL_free(p); | |
265 | return -1; | |
266 | } | |
267 | ||
268 | int i2o_SCT(const SCT *sct, unsigned char **out) | |
269 | { | |
270 | size_t len; | |
271 | unsigned char *p = NULL; | |
272 | ||
0cea8832 | 273 | if (!SCT_is_complete(sct)) { |
5ad29c54 AE |
274 | CTerr(CT_F_I2O_SCT, CT_R_SCT_NOT_SET); |
275 | goto err; | |
276 | } | |
277 | /* | |
278 | * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes) | |
279 | * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions | |
280 | * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2 | |
281 | * bytes + ?) Signature | |
282 | */ | |
0cea8832 | 283 | if (sct->version == SCT_VERSION_V1) |
5ad29c54 AE |
284 | len = 43 + sct->ext_len + 4 + sct->sig_len; |
285 | else | |
286 | len = sct->sct_len; | |
287 | ||
288 | if (out == NULL) | |
289 | return len; | |
290 | ||
291 | if (*out != NULL) { | |
292 | p = *out; | |
293 | *out += len; | |
294 | } else { | |
295 | p = OPENSSL_malloc(len); | |
296 | if (p == NULL) { | |
297 | CTerr(CT_F_I2O_SCT, ERR_R_MALLOC_FAILURE); | |
298 | goto err; | |
299 | } | |
300 | *out = p; | |
301 | } | |
302 | ||
0cea8832 | 303 | if (sct->version == SCT_VERSION_V1) { |
5ad29c54 | 304 | *p++ = sct->version; |
0cea8832 RP |
305 | memcpy(p, sct->log_id, CT_V1_HASHLEN); |
306 | p += CT_V1_HASHLEN; | |
5ad29c54 AE |
307 | l2n8(sct->timestamp, p); |
308 | s2n(sct->ext_len, p); | |
309 | if (sct->ext_len > 0) { | |
310 | memcpy(p, sct->ext, sct->ext_len); | |
311 | p += sct->ext_len; | |
312 | } | |
313 | if (i2o_SCT_signature(sct, &p) <= 0) | |
314 | goto err; | |
315 | } else { | |
316 | memcpy(p, sct->sct, len); | |
317 | } | |
318 | ||
319 | return len; | |
320 | err: | |
321 | OPENSSL_free(p); | |
322 | return -1; | |
323 | } | |
324 | ||
325 | void SCT_LIST_free(STACK_OF(SCT) *a) | |
326 | { | |
327 | sk_SCT_pop_free(a, SCT_free); | |
328 | } | |
329 | ||
330 | STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, | |
331 | size_t len) | |
332 | { | |
333 | STACK_OF(SCT) *sk = NULL; | |
334 | size_t list_len, sct_len; | |
335 | ||
336 | if (len < 2 || len > MAX_SCT_LIST_SIZE) { | |
337 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | |
338 | return NULL; | |
339 | } | |
340 | ||
341 | n2s(*pp, list_len); | |
342 | if (list_len != len - 2) { | |
343 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | |
344 | return NULL; | |
345 | } | |
346 | ||
347 | if (a == NULL || *a == NULL) { | |
348 | sk = sk_SCT_new_null(); | |
349 | if (sk == NULL) | |
350 | return NULL; | |
351 | } else { | |
352 | SCT *sct; | |
353 | ||
354 | /* Use the given stack, but empty it first. */ | |
355 | sk = *a; | |
356 | while ((sct = sk_SCT_pop(sk)) != NULL) | |
357 | SCT_free(sct); | |
358 | } | |
359 | ||
360 | while (list_len > 0) { | |
361 | SCT *sct; | |
362 | ||
363 | if (list_len < 2) { | |
364 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | |
365 | goto err; | |
366 | } | |
367 | n2s(*pp, sct_len); | |
368 | list_len -= 2; | |
369 | ||
370 | if (sct_len == 0 || sct_len > list_len) { | |
371 | CTerr(CT_F_O2I_SCT_LIST, CT_R_SCT_LIST_INVALID); | |
372 | goto err; | |
373 | } | |
374 | list_len -= sct_len; | |
375 | ||
376 | if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL) | |
377 | goto err; | |
378 | if (!sk_SCT_push(sk, sct)) { | |
379 | SCT_free(sct); | |
380 | goto err; | |
381 | } | |
382 | } | |
383 | ||
384 | if (a != NULL && *a == NULL) | |
385 | *a = sk; | |
386 | return sk; | |
387 | ||
388 | err: | |
389 | if (a == NULL || *a == NULL) | |
390 | SCT_LIST_free(sk); | |
391 | return NULL; | |
392 | } | |
393 | ||
0cea8832 | 394 | int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp) |
5ad29c54 AE |
395 | { |
396 | int len, sct_len, i, is_pp_new = 0; | |
397 | size_t len2; | |
398 | unsigned char *p = NULL, *p2; | |
399 | ||
400 | if (pp != NULL) { | |
401 | if (*pp == NULL) { | |
402 | if ((len = i2o_SCT_LIST(a, NULL)) == -1) { | |
403 | CTerr(CT_F_I2O_SCT_LIST, CT_R_SCT_LIST_INVALID); | |
404 | return -1; | |
405 | } | |
406 | if ((*pp = OPENSSL_malloc(len)) == NULL) { | |
407 | CTerr(CT_F_I2O_SCT_LIST, ERR_R_MALLOC_FAILURE); | |
408 | return -1; | |
409 | } | |
410 | is_pp_new = 1; | |
411 | } | |
412 | p = *pp + 2; | |
413 | } | |
414 | ||
415 | len2 = 2; | |
416 | for (i = 0; i < sk_SCT_num(a); i++) { | |
417 | if (pp != NULL) { | |
418 | p2 = p; | |
419 | p += 2; | |
420 | if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1) | |
421 | goto err; | |
422 | s2n(sct_len, p2); | |
423 | } else { | |
424 | if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1) | |
425 | goto err; | |
426 | } | |
427 | len2 += 2 + sct_len; | |
428 | } | |
429 | ||
430 | if (len2 > MAX_SCT_LIST_SIZE) | |
431 | goto err; | |
432 | ||
433 | if (pp != NULL) { | |
434 | p = *pp; | |
435 | s2n(len2 - 2, p); | |
436 | } | |
437 | if (!is_pp_new) | |
438 | *pp += len2; | |
439 | return len2; | |
440 | ||
441 | err: | |
442 | if (is_pp_new) { | |
443 | OPENSSL_free(*pp); | |
444 | *pp = NULL; | |
445 | } | |
446 | return -1; | |
447 | } | |
448 | ||
0cea8832 RP |
449 | STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, |
450 | long len) | |
5ad29c54 AE |
451 | { |
452 | ASN1_OCTET_STRING *oct = NULL; | |
453 | STACK_OF(SCT) *sk = NULL; | |
454 | const unsigned char *p; | |
455 | ||
456 | p = *pp; | |
457 | if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL) | |
458 | return NULL; | |
459 | ||
460 | p = oct->data; | |
461 | if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL) | |
462 | *pp += len; | |
463 | ||
464 | ASN1_OCTET_STRING_free(oct); | |
465 | return sk; | |
466 | } | |
467 | ||
0cea8832 | 468 | int i2d_SCT_LIST(STACK_OF(SCT) *a, unsigned char **out) |
5ad29c54 AE |
469 | { |
470 | ASN1_OCTET_STRING oct; | |
471 | int len; | |
472 | ||
473 | oct.data = NULL; | |
474 | if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1) | |
475 | return -1; | |
476 | ||
477 | len = i2d_ASN1_OCTET_STRING(&oct, out); | |
478 | OPENSSL_free(oct.data); | |
479 | return len; | |
480 | } |