1 /*	$OpenBSD: ct_sct_ctx.c,v 1.6 2022/06/30 11:14:47 tb 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 <stddef.h>
65 #include <string.h>
66 
67 #include <openssl/err.h>
68 #include <openssl/objects.h>
69 #include <openssl/x509.h>
70 
71 #include "ct_local.h"
72 
73 SCT_CTX *
74 SCT_CTX_new(void)
75 {
76 	SCT_CTX *sctx = calloc(1, sizeof(*sctx));
77 
78 	if (sctx == NULL)
79 		CTerror(ERR_R_MALLOC_FAILURE);
80 
81 	return sctx;
82 }
83 
84 void
85 SCT_CTX_free(SCT_CTX *sctx)
86 {
87 	if (sctx == NULL)
88 		return;
89 	EVP_PKEY_free(sctx->pkey);
90 	free(sctx->pkeyhash);
91 	free(sctx->ihash);
92 	free(sctx->certder);
93 	free(sctx->preder);
94 	free(sctx);
95 }
96 
97 /*
98  * Finds the index of the first extension with the given NID in cert.
99  * If there is more than one extension with that NID, *is_duplicated is set to
100  * 1, otherwise 0 (unless it is NULL).
101  */
102 static int
103 ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated)
104 {
105 	int ret = X509_get_ext_by_NID(cert, nid, -1);
106 
107 	if (is_duplicated != NULL)
108 		*is_duplicated = ret >= 0 &&
109 		    X509_get_ext_by_NID(cert, nid, ret) >= 0;
110 
111 	return ret;
112 }
113 
114 /*
115  * Modifies a certificate by deleting extensions and copying the issuer and
116  * AKID from the presigner certificate, if necessary.
117  * Returns 1 on success, 0 otherwise.
118  */
119 static int
120 ct_x509_cert_fixup(X509 *cert, X509 *presigner)
121 {
122 	int preidx, certidx;
123 	int pre_akid_ext_is_dup, cert_akid_ext_is_dup;
124 
125 	if (presigner == NULL)
126 		return 1;
127 
128 	preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier,
129 	    &pre_akid_ext_is_dup);
130 	certidx = ct_x509_get_ext(cert, NID_authority_key_identifier,
131 	    &cert_akid_ext_is_dup);
132 
133 	/* An error occurred whilst searching for the extension */
134 	if (preidx < -1 || certidx < -1)
135 		return 0;
136 	/* Invalid certificate if they contain duplicate extensions */
137 	if (pre_akid_ext_is_dup || cert_akid_ext_is_dup)
138 		return 0;
139 	/* AKID must be present in both certificate or absent in both */
140 	if (preidx >= 0 && certidx == -1)
141 		return 0;
142 	if (preidx == -1 && certidx >= 0)
143 		return 0;
144 	/* Copy issuer name */
145 	if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner)))
146 		return 0;
147 	if (preidx != -1) {
148 		/* Retrieve and copy AKID encoding */
149 		X509_EXTENSION *preext = X509_get_ext(presigner, preidx);
150 		X509_EXTENSION *certext = X509_get_ext(cert, certidx);
151 		ASN1_OCTET_STRING *preextdata;
152 
153 		/* Should never happen */
154 		if (preext == NULL || certext == NULL)
155 			return 0;
156 		preextdata = X509_EXTENSION_get_data(preext);
157 		if (preextdata == NULL ||
158 		    !X509_EXTENSION_set_data(certext, preextdata))
159 			return 0;
160 	}
161 	return 1;
162 }
163 
164 int
165 SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
166 {
167 	unsigned char *certder = NULL, *preder = NULL;
168 	X509 *pretmp = NULL;
169 	int certderlen = 0, prederlen = 0;
170 	int idx = -1;
171 	int poison_ext_is_dup, sct_ext_is_dup;
172 	int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup);
173 
174 	/* Duplicate poison extensions are present - error */
175 	if (poison_ext_is_dup)
176 		goto err;
177 
178 	/* If *cert doesn't have a poison extension, it isn't a precert */
179 	if (poison_idx == -1) {
180 		/* cert isn't a precert, so we shouldn't have a presigner */
181 		if (presigner != NULL)
182 			goto err;
183 
184 		certderlen = i2d_X509(cert, &certder);
185 		if (certderlen < 0)
186 			goto err;
187 	}
188 
189 	/* See if cert has a precert SCTs extension */
190 	idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup);
191 	/* Duplicate SCT extensions are present - error */
192 	if (sct_ext_is_dup)
193 		goto err;
194 
195 	if (idx >= 0 && poison_idx >= 0) {
196 		/*
197 		 * cert can't both contain SCTs (i.e. have an SCT extension) and be a
198 		 * precert (i.e. have a poison extension).
199 		 */
200 		goto err;
201 	}
202 
203 	if (idx == -1) {
204 		idx = poison_idx;
205 	}
206 
207 	/*
208 	 * If either a poison or SCT extension is present, remove it before encoding
209 	 * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see
210 	 * RFC5280) from cert, which is what the CT log signed when it produced the
211 	 * SCT.
212 	 */
213 	if (idx >= 0) {
214 		X509_EXTENSION *ext;
215 
216 		/* Take a copy of certificate so we don't modify passed version */
217 		pretmp = X509_dup(cert);
218 		if (pretmp == NULL)
219 			goto err;
220 
221 		ext = X509_delete_ext(pretmp, idx);
222 		X509_EXTENSION_free(ext);
223 
224 		if (!ct_x509_cert_fixup(pretmp, presigner))
225 			goto err;
226 
227 		prederlen = i2d_re_X509_tbs(pretmp, &preder);
228 		if (prederlen <= 0)
229 			goto err;
230 	}
231 
232 	X509_free(pretmp);
233 
234 	free(sctx->certder);
235 	sctx->certder = certder;
236 	sctx->certderlen = certderlen;
237 
238 	free(sctx->preder);
239 	sctx->preder = preder;
240 	sctx->prederlen = prederlen;
241 
242 	return 1;
243  err:
244 	free(certder);
245 	free(preder);
246 	X509_free(pretmp);
247 	return 0;
248 }
249 
250 static int
251 ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, size_t *hash_len)
252 {
253 	int ret = 0;
254 	unsigned char *md = NULL, *der = NULL;
255 	int der_len;
256 	unsigned int md_len;
257 
258 	/* Reuse buffer if possible */
259 	if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
260 		md = *hash;
261 	} else {
262 		md = malloc(SHA256_DIGEST_LENGTH);
263 		if (md == NULL)
264 			goto err;
265 	}
266 
267 	/* Calculate key hash */
268 	der_len = i2d_X509_PUBKEY(pkey, &der);
269 	if (der_len <= 0)
270 		goto err;
271 
272 	if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
273 		goto err;
274 
275 	if (md != *hash) {
276 		free(*hash);
277 		*hash = md;
278 		*hash_len = SHA256_DIGEST_LENGTH;
279 	}
280 
281 	md = NULL;
282 	ret = 1;
283  err:
284 	free(md);
285 	free(der);
286 	return ret;
287 }
288 
289 int
290 SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
291 {
292 	return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer));
293 }
294 
295 int
296 SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
297 {
298 	return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
299 }
300 
301 int
302 SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
303 {
304 	EVP_PKEY *pkey = X509_PUBKEY_get(pubkey);
305 
306 	if (pkey == NULL)
307 		return 0;
308 
309 	if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
310 		EVP_PKEY_free(pkey);
311 		return 0;
312 	}
313 
314 	EVP_PKEY_free(sctx->pkey);
315 	sctx->pkey = pkey;
316 	return 1;
317 }
318 
319 void
320 SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms)
321 {
322 	sctx->epoch_time_in_ms = time_in_ms;
323 }
324