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