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