xref: /openbsd-src/lib/libcrypto/ct/ct_oct.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: ct_oct.c,v 1.4 2021/12/05 09:37:46 tb Exp $ */
2 /*
3  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
4  *
5  * Licensed under the OpenSSL license (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10 
11 #ifdef OPENSSL_NO_CT
12 # error "CT is disabled"
13 #endif
14 
15 #include <limits.h>
16 #include <string.h>
17 
18 #include <openssl/asn1.h>
19 #include <openssl/buffer.h>
20 #include <openssl/ct.h>
21 #include <openssl/err.h>
22 
23 #include "ct_local.h"
24 
25 int
26 o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
27 {
28 	size_t siglen;
29 	size_t len_remaining = len;
30 	const unsigned char *p;
31 
32 	if (sct->version != SCT_VERSION_V1) {
33 		CTerror(CT_R_UNSUPPORTED_VERSION);
34 		return -1;
35 	}
36 	/*
37 	 * digitally-signed struct header: (1 byte) Hash algorithm (1 byte)
38 	 * Signature algorithm (2 bytes + ?) Signature
39 	 *
40 	 * This explicitly rejects empty signatures: they're invalid for
41 	 * all supported algorithms.
42 	 */
43 	if (len <= 4) {
44 		CTerror(CT_R_SCT_INVALID_SIGNATURE);
45 		return -1;
46 	}
47 
48 	p = *in;
49 	/* Get hash and signature algorithm */
50 	sct->hash_alg = *p++;
51 	sct->sig_alg = *p++;
52 	if (SCT_get_signature_nid(sct) == NID_undef) {
53 		CTerror(CT_R_SCT_INVALID_SIGNATURE);
54 		return -1;
55 	}
56 	/*
57 	 * Retrieve signature and check it is consistent with the buffer
58 	 * length
59 	 */
60 	n2s(p, siglen);
61 	len_remaining -= (p - *in);
62 	if (siglen > len_remaining) {
63 		CTerror(CT_R_SCT_INVALID_SIGNATURE);
64 		return -1;
65 	}
66 
67 	if (SCT_set1_signature(sct, p, siglen) != 1)
68 		return -1;
69 	len_remaining -= siglen;
70 	*in = p + siglen;
71 
72 	return len - len_remaining;
73 }
74 
75 SCT *
76 o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
77 {
78 	SCT *sct = NULL;
79 	const unsigned char *p;
80 
81 	/*
82 	 * XXX paging Dr Sing. please report to this function for an emergency
83 	 * CBS/CBB implantation surgery. Stat.
84 	 */
85 
86 	if (len == 0 || len > MAX_SCT_SIZE) {
87 		CTerror(CT_R_SCT_INVALID);
88 		goto err;
89 	}
90 
91 	if ((sct = SCT_new()) == NULL)
92 		goto err;
93 
94 	p = *in;
95 
96 	sct->version = *p;
97 	if (sct->version == SCT_VERSION_V1) {
98 		int sig_len;
99 		size_t len2;
100 		/*-
101 		 * Fixed-length header:
102 		 *   struct {
103 		 *     Version sct_version;     (1 byte)
104 		 *     log_id id;               (32 bytes)
105 		 *     uint64 timestamp;        (8 bytes)
106 		 *     CtExtensions extensions; (2 bytes + ?)
107 		 *   }
108 		 */
109 		if (len < 43) {
110 			CTerror(CT_R_SCT_INVALID);
111 			goto err;
112 		}
113 		len -= 43;
114 		p++;
115 		sct->log_id = malloc(CT_V1_HASHLEN);
116 		if (sct->log_id == NULL)
117 			goto err;
118 		memcpy(sct->log_id, p, CT_V1_HASHLEN);
119 		sct->log_id_len = CT_V1_HASHLEN;
120 		p += CT_V1_HASHLEN;
121 
122 		n2l8(p, sct->timestamp);
123 
124 		n2s(p, len2);
125 		if (len < len2) {
126 			CTerror(CT_R_SCT_INVALID);
127 			goto err;
128 		}
129 		if (len2 > 0) {
130 			sct->ext = malloc(len2);
131 			if (sct->ext == NULL)
132 				goto err;
133 			memcpy(sct->ext, p, len2);
134 		}
135 		sct->ext_len = len2;
136 		p += len2;
137 		len -= len2;
138 
139 		sig_len = o2i_SCT_signature(sct, &p, len);
140 		if (sig_len <= 0) {
141 			CTerror(CT_R_SCT_INVALID);
142 			goto err;
143 		}
144 		len -= sig_len;
145 		*in = p + len;
146 	} else {
147 		/* If not V1 just cache encoding */
148 		sct->sct = malloc(len);
149 		if (sct->sct == NULL)
150 			goto err;
151 		memcpy(sct->sct, p, len);
152 		sct->sct_len = len;
153 		*in = p + len;
154 	}
155 
156 	if (psct != NULL) {
157 		SCT_free(*psct);
158 		*psct = sct;
159 	}
160 
161 	return sct;
162  err:
163 	SCT_free(sct);
164 	return NULL;
165 }
166 
167 int
168 i2o_SCT_signature(const SCT *sct, unsigned char **out)
169 {
170 	size_t len;
171 	unsigned char *p = NULL, *pstart = NULL;
172 
173 	if (!SCT_signature_is_complete(sct)) {
174 		CTerror(CT_R_SCT_INVALID_SIGNATURE);
175 		goto err;
176 	}
177 
178 	if (sct->version != SCT_VERSION_V1) {
179 		CTerror(CT_R_UNSUPPORTED_VERSION);
180 		goto err;
181 	}
182 
183 	/*
184 	 * (1 byte) Hash algorithm
185 	 * (1 byte) Signature algorithm
186 	 * (2 bytes + ?) Signature
187 	 */
188 	len = 4 + sct->sig_len;
189 
190 	if (out != NULL) {
191 		if (*out != NULL) {
192 			p = *out;
193 			*out += len;
194 		} else {
195 			pstart = p = malloc(len);
196 			if (p == NULL) {
197 				CTerror(ERR_R_MALLOC_FAILURE);
198 				goto err;
199 			}
200 			*out = p;
201 		}
202 
203 		*p++ = sct->hash_alg;
204 		*p++ = sct->sig_alg;
205 		s2n(sct->sig_len, p);
206 		memcpy(p, sct->sig, sct->sig_len);
207 	}
208 
209 	return len;
210  err:
211 	free(pstart);
212 	return -1;
213 }
214 
215 int
216 i2o_SCT(const SCT *sct, unsigned char **out)
217 {
218 	size_t len;
219 	unsigned char *p = NULL, *pstart = NULL;
220 
221 	if (!SCT_is_complete(sct)) {
222 		CTerror(CT_R_SCT_NOT_SET);
223 		goto err;
224 	}
225 	/*
226 	 * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes)
227 	 * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions
228 	 * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2
229 	 * bytes + ?) Signature
230 	 */
231 	if (sct->version == SCT_VERSION_V1)
232 		len = 43 + sct->ext_len + 4 + sct->sig_len;
233 	else
234 		len = sct->sct_len;
235 
236 	if (out == NULL)
237 		return len;
238 
239 	if (*out != NULL) {
240 		p = *out;
241 		*out += len;
242 	} else {
243 		pstart = p = malloc(len);
244 		if (p == NULL) {
245 			CTerror(ERR_R_MALLOC_FAILURE);
246 			goto err;
247 		}
248 		*out = p;
249 	}
250 
251 	if (sct->version == SCT_VERSION_V1) {
252 		*p++ = sct->version;
253 		memcpy(p, sct->log_id, CT_V1_HASHLEN);
254 		p += CT_V1_HASHLEN;
255 		l2n8(sct->timestamp, p);
256 		s2n(sct->ext_len, p);
257 		if (sct->ext_len > 0) {
258 			memcpy(p, sct->ext, sct->ext_len);
259 			p += sct->ext_len;
260 		}
261 		if (i2o_SCT_signature(sct, &p) <= 0)
262 			goto err;
263 	} else {
264 		memcpy(p, sct->sct, len);
265 	}
266 
267 	return len;
268  err:
269 	free(pstart);
270 	return -1;
271 }
272 
273 STACK_OF(SCT) *
274 o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, size_t len)
275 {
276 	STACK_OF(SCT) *sk = NULL;
277 	size_t list_len, sct_len;
278 
279 	if (len < 2 || len > MAX_SCT_LIST_SIZE) {
280 		CTerror(CT_R_SCT_LIST_INVALID);
281 		return NULL;
282 	}
283 
284 	n2s(*pp, list_len);
285 	if (list_len != len - 2) {
286 		CTerror(CT_R_SCT_LIST_INVALID);
287 		return NULL;
288 	}
289 
290 	if (a == NULL || *a == NULL) {
291 		sk = sk_SCT_new_null();
292 		if (sk == NULL)
293 			return NULL;
294 	} else {
295 		SCT *sct;
296 
297 		/* Use the given stack, but empty it first. */
298 		sk = *a;
299 		while ((sct = sk_SCT_pop(sk)) != NULL)
300 			SCT_free(sct);
301 	}
302 
303 	while (list_len > 0) {
304 		SCT *sct;
305 
306 		if (list_len < 2) {
307 			CTerror(CT_R_SCT_LIST_INVALID);
308 			goto err;
309 		}
310 		n2s(*pp, sct_len);
311 		list_len -= 2;
312 
313 		if (sct_len == 0 || sct_len > list_len) {
314 			CTerror(CT_R_SCT_LIST_INVALID);
315 			goto err;
316 		}
317 		list_len -= sct_len;
318 
319 		if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL)
320 			goto err;
321 		if (!sk_SCT_push(sk, sct)) {
322 			SCT_free(sct);
323 			goto err;
324 		}
325 	}
326 
327 	if (a != NULL && *a == NULL)
328 		*a = sk;
329 	return sk;
330 
331  err:
332 	if (a == NULL || *a == NULL)
333 		SCT_LIST_free(sk);
334 	return NULL;
335 }
336 
337 int
338 i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
339 {
340 	int len, sct_len, i, is_pp_new = 0;
341 	size_t len2;
342 	unsigned char *p = NULL, *p2;
343 
344 	if (pp != NULL) {
345 		if (*pp == NULL) {
346 			if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
347 				CTerror(CT_R_SCT_LIST_INVALID);
348 				return -1;
349 			}
350 			if ((*pp = malloc(len)) == NULL) {
351 				CTerror(ERR_R_MALLOC_FAILURE);
352 				return -1;
353 			}
354 			is_pp_new = 1;
355 		}
356 		p = *pp + 2;
357 	}
358 
359 	len2 = 2;
360 	for (i = 0; i < sk_SCT_num(a); i++) {
361 		if (pp != NULL) {
362 			p2 = p;
363 			p += 2;
364 			if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1)
365 				goto err;
366 			s2n(sct_len, p2);
367 		} else {
368 			if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1)
369 				goto err;
370 		}
371 		len2 += 2 + sct_len;
372 	}
373 
374 	if (len2 > MAX_SCT_LIST_SIZE)
375 		goto err;
376 
377 	if (pp != NULL) {
378 		p = *pp;
379 		s2n(len2 - 2, p);
380 		if (!is_pp_new)
381 			*pp += len2;
382 	}
383 	return len2;
384 
385  err:
386 	if (is_pp_new) {
387 		free(*pp);
388 		*pp = NULL;
389 	}
390 	return -1;
391 }
392 
393 STACK_OF(SCT) *
394 d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
395 {
396 	ASN1_OCTET_STRING *oct = NULL;
397 	STACK_OF(SCT) *sk = NULL;
398 	const unsigned char *p;
399 
400 	p = *pp;
401 	if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL)
402 		return NULL;
403 
404 	p = oct->data;
405 	if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL)
406 		*pp += len;
407 
408 	ASN1_OCTET_STRING_free(oct);
409 	return sk;
410 }
411 
412 int
413 i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out)
414 {
415 	ASN1_OCTET_STRING oct;
416 	int len;
417 
418 	oct.data = NULL;
419 	if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1)
420 		return -1;
421 
422 	len = i2d_ASN1_OCTET_STRING(&oct, out);
423 	free(oct.data);
424 	return len;
425 }
426