2 * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
3 * (steve@openssl.org) for the OpenSSL project 2014.
5 /* ====================================================================
6 * Copyright (c) 2014 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
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).
60 # error "CT is disabled"
66 #include <openssl/err.h>
67 #include <openssl/obj_mac.h>
68 #include <openssl/x509.h>
72 SCT_CTX *SCT_CTX_new(void)
74 SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx));
77 CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE);
82 void SCT_CTX_free(SCT_CTX *sctx)
86 EVP_PKEY_free(sctx->pkey);
87 OPENSSL_free(sctx->pkeyhash);
88 OPENSSL_free(sctx->ihash);
89 OPENSSL_free(sctx->certder);
90 OPENSSL_free(sctx->preder);
95 * Finds the index of the first extension with the given NID in cert.
96 * If there is more than one extension with that NID, *is_duplicated is set to
97 * 1, otherwise 0 (unless it is NULL).
99 static int ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated)
101 int ret = X509_get_ext_by_NID(cert, nid, -1);
103 if (is_duplicated != NULL)
104 *is_duplicated = ret >= 0 && X509_get_ext_by_NID(cert, nid, ret) >= 0;
110 * Modifies a certificate by deleting extensions and copying the issuer and
111 * AKID from the presigner certificate, if necessary.
112 * Returns 1 on success, 0 otherwise.
114 static int ct_x509_cert_fixup(X509 *cert, X509 *presigner)
117 int pre_akid_ext_is_dup, cert_akid_ext_is_dup;
119 if (presigner == NULL)
122 preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier,
123 &pre_akid_ext_is_dup);
124 certidx = ct_x509_get_ext(cert, NID_authority_key_identifier,
125 &cert_akid_ext_is_dup);
127 /* An error occurred whilst searching for the extension */
128 if (preidx < -1 || certidx < -1)
130 /* Invalid certificate if they contain duplicate extensions */
131 if (pre_akid_ext_is_dup || cert_akid_ext_is_dup)
133 /* AKID must be present in both certificate or absent in both */
134 if (preidx >= 0 && certidx == -1)
136 if (preidx == -1 && certidx >= 0)
138 /* Copy issuer name */
139 if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner)))
142 /* Retrieve and copy AKID encoding */
143 X509_EXTENSION *preext = X509_get_ext(presigner, preidx);
144 X509_EXTENSION *certext = X509_get_ext(cert, certidx);
145 ASN1_OCTET_STRING *preextdata;
147 /* Should never happen */
148 if (preext == NULL || certext == NULL)
150 preextdata = X509_EXTENSION_get_data(preext);
151 if (preextdata == NULL ||
152 !X509_EXTENSION_set_data(certext, preextdata))
158 int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
160 unsigned char *certder = NULL, *preder = NULL;
162 int certderlen = 0, prederlen = 0;
164 int poison_ext_is_dup, sct_ext_is_dup;
165 int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup);
167 /* Duplicate poison */
168 if (poison_ext_is_dup)
171 /* If no poison extension, store encoding */
172 if (poison_idx == -1) {
173 /* presigner must have poison */
174 if (presigner != NULL)
177 certderlen = i2d_X509(cert, &certder);
182 /* See if have precert scts extension */
183 idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup);
189 /* Can't have both poison and scts */
199 /* Take a copy of certificate so we don't modify passed version */
200 pretmp = X509_dup(cert);
204 ext = X509_delete_ext(pretmp, idx);
205 X509_EXTENSION_free(ext);
207 if (!ct_x509_cert_fixup(pretmp, presigner))
210 prederlen = i2d_re_X509_tbs(pretmp, &preder);
217 OPENSSL_free(sctx->certder);
218 sctx->certder = certder;
219 sctx->certderlen = certderlen;
221 OPENSSL_free(sctx->preder);
222 sctx->preder = preder;
223 sctx->prederlen = prederlen;
227 OPENSSL_free(certder);
228 OPENSSL_free(preder);
233 static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
237 unsigned char *md = NULL, *der = NULL;
241 /* Reuse buffer if possible */
242 if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
245 md = OPENSSL_malloc(SHA256_DIGEST_LENGTH);
250 /* Calculate key hash */
251 der_len = i2d_X509_PUBKEY(pkey, &der);
255 if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
261 *hash_len = SHA256_DIGEST_LENGTH;
272 int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
274 return ct_public_key_hash(X509_get_X509_PUBKEY(issuer), &sctx->ihash,
278 int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
280 return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
283 int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
285 EVP_PKEY *pkey = X509_PUBKEY_get(pubkey);
290 if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
295 EVP_PKEY_free(sctx->pkey);