1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#ifdef OPENSSL_NO_CT 11e1051a39Sopenharmony_ci# error "CT is disabled" 12e1051a39Sopenharmony_ci#endif 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include <stddef.h> 15e1051a39Sopenharmony_ci#include <string.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci#include <openssl/obj_mac.h> 19e1051a39Sopenharmony_ci#include <openssl/x509.h> 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#include "ct_local.h" 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ciSCT_CTX *SCT_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) 24e1051a39Sopenharmony_ci{ 25e1051a39Sopenharmony_ci SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx)); 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci if (sctx == NULL) { 28e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); 29e1051a39Sopenharmony_ci return NULL; 30e1051a39Sopenharmony_ci } 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci sctx->libctx = libctx; 33e1051a39Sopenharmony_ci if (propq != NULL) { 34e1051a39Sopenharmony_ci sctx->propq = OPENSSL_strdup(propq); 35e1051a39Sopenharmony_ci if (sctx->propq == NULL) { 36e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); 37e1051a39Sopenharmony_ci OPENSSL_free(sctx); 38e1051a39Sopenharmony_ci return NULL; 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci } 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci return sctx; 43e1051a39Sopenharmony_ci} 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_civoid SCT_CTX_free(SCT_CTX *sctx) 46e1051a39Sopenharmony_ci{ 47e1051a39Sopenharmony_ci if (sctx == NULL) 48e1051a39Sopenharmony_ci return; 49e1051a39Sopenharmony_ci EVP_PKEY_free(sctx->pkey); 50e1051a39Sopenharmony_ci OPENSSL_free(sctx->pkeyhash); 51e1051a39Sopenharmony_ci OPENSSL_free(sctx->ihash); 52e1051a39Sopenharmony_ci OPENSSL_free(sctx->certder); 53e1051a39Sopenharmony_ci OPENSSL_free(sctx->preder); 54e1051a39Sopenharmony_ci OPENSSL_free(sctx->propq); 55e1051a39Sopenharmony_ci OPENSSL_free(sctx); 56e1051a39Sopenharmony_ci} 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci/* 59e1051a39Sopenharmony_ci * Finds the index of the first extension with the given NID in cert. 60e1051a39Sopenharmony_ci * If there is more than one extension with that NID, *is_duplicated is set to 61e1051a39Sopenharmony_ci * 1, otherwise 0 (unless it is NULL). 62e1051a39Sopenharmony_ci */ 63e1051a39Sopenharmony_cistatic int ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated) 64e1051a39Sopenharmony_ci{ 65e1051a39Sopenharmony_ci int ret = X509_get_ext_by_NID(cert, nid, -1); 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci if (is_duplicated != NULL) 68e1051a39Sopenharmony_ci *is_duplicated = ret >= 0 && X509_get_ext_by_NID(cert, nid, ret) >= 0; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci return ret; 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci/* 74e1051a39Sopenharmony_ci * Modifies a certificate by deleting extensions and copying the issuer and 75e1051a39Sopenharmony_ci * AKID from the presigner certificate, if necessary. 76e1051a39Sopenharmony_ci * Returns 1 on success, 0 otherwise. 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_ci__owur static int ct_x509_cert_fixup(X509 *cert, X509 *presigner) 79e1051a39Sopenharmony_ci{ 80e1051a39Sopenharmony_ci int preidx, certidx; 81e1051a39Sopenharmony_ci int pre_akid_ext_is_dup, cert_akid_ext_is_dup; 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci if (presigner == NULL) 84e1051a39Sopenharmony_ci return 1; 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier, 87e1051a39Sopenharmony_ci &pre_akid_ext_is_dup); 88e1051a39Sopenharmony_ci certidx = ct_x509_get_ext(cert, NID_authority_key_identifier, 89e1051a39Sopenharmony_ci &cert_akid_ext_is_dup); 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci /* An error occurred whilst searching for the extension */ 92e1051a39Sopenharmony_ci if (preidx < -1 || certidx < -1) 93e1051a39Sopenharmony_ci return 0; 94e1051a39Sopenharmony_ci /* Invalid certificate if they contain duplicate extensions */ 95e1051a39Sopenharmony_ci if (pre_akid_ext_is_dup || cert_akid_ext_is_dup) 96e1051a39Sopenharmony_ci return 0; 97e1051a39Sopenharmony_ci /* AKID must be present in both certificate or absent in both */ 98e1051a39Sopenharmony_ci if (preidx >= 0 && certidx == -1) 99e1051a39Sopenharmony_ci return 0; 100e1051a39Sopenharmony_ci if (preidx == -1 && certidx >= 0) 101e1051a39Sopenharmony_ci return 0; 102e1051a39Sopenharmony_ci /* Copy issuer name */ 103e1051a39Sopenharmony_ci if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner))) 104e1051a39Sopenharmony_ci return 0; 105e1051a39Sopenharmony_ci if (preidx != -1) { 106e1051a39Sopenharmony_ci /* Retrieve and copy AKID encoding */ 107e1051a39Sopenharmony_ci X509_EXTENSION *preext = X509_get_ext(presigner, preidx); 108e1051a39Sopenharmony_ci X509_EXTENSION *certext = X509_get_ext(cert, certidx); 109e1051a39Sopenharmony_ci ASN1_OCTET_STRING *preextdata; 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci /* Should never happen */ 112e1051a39Sopenharmony_ci if (preext == NULL || certext == NULL) 113e1051a39Sopenharmony_ci return 0; 114e1051a39Sopenharmony_ci preextdata = X509_EXTENSION_get_data(preext); 115e1051a39Sopenharmony_ci if (preextdata == NULL || 116e1051a39Sopenharmony_ci !X509_EXTENSION_set_data(certext, preextdata)) 117e1051a39Sopenharmony_ci return 0; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_ci return 1; 120e1051a39Sopenharmony_ci} 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ciint SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner) 123e1051a39Sopenharmony_ci{ 124e1051a39Sopenharmony_ci unsigned char *certder = NULL, *preder = NULL; 125e1051a39Sopenharmony_ci X509 *pretmp = NULL; 126e1051a39Sopenharmony_ci int certderlen = 0, prederlen = 0; 127e1051a39Sopenharmony_ci int idx = -1; 128e1051a39Sopenharmony_ci int poison_ext_is_dup, sct_ext_is_dup; 129e1051a39Sopenharmony_ci int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup); 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci /* Duplicate poison extensions are present - error */ 132e1051a39Sopenharmony_ci if (poison_ext_is_dup) 133e1051a39Sopenharmony_ci goto err; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci /* If *cert doesn't have a poison extension, it isn't a precert */ 136e1051a39Sopenharmony_ci if (poison_idx == -1) { 137e1051a39Sopenharmony_ci /* cert isn't a precert, so we shouldn't have a presigner */ 138e1051a39Sopenharmony_ci if (presigner != NULL) 139e1051a39Sopenharmony_ci goto err; 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci certderlen = i2d_X509(cert, &certder); 142e1051a39Sopenharmony_ci if (certderlen < 0) 143e1051a39Sopenharmony_ci goto err; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci /* See if cert has a precert SCTs extension */ 147e1051a39Sopenharmony_ci idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup); 148e1051a39Sopenharmony_ci /* Duplicate SCT extensions are present - error */ 149e1051a39Sopenharmony_ci if (sct_ext_is_dup) 150e1051a39Sopenharmony_ci goto err; 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci if (idx >= 0 && poison_idx >= 0) { 153e1051a39Sopenharmony_ci /* 154e1051a39Sopenharmony_ci * cert can't both contain SCTs (i.e. have an SCT extension) and be a 155e1051a39Sopenharmony_ci * precert (i.e. have a poison extension). 156e1051a39Sopenharmony_ci */ 157e1051a39Sopenharmony_ci goto err; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci if (idx == -1) { 161e1051a39Sopenharmony_ci idx = poison_idx; 162e1051a39Sopenharmony_ci } 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci /* 165e1051a39Sopenharmony_ci * If either a poison or SCT extension is present, remove it before encoding 166e1051a39Sopenharmony_ci * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see 167e1051a39Sopenharmony_ci * RFC5280) from cert, which is what the CT log signed when it produced the 168e1051a39Sopenharmony_ci * SCT. 169e1051a39Sopenharmony_ci */ 170e1051a39Sopenharmony_ci if (idx >= 0) { 171e1051a39Sopenharmony_ci /* Take a copy of certificate so we don't modify passed version */ 172e1051a39Sopenharmony_ci pretmp = X509_dup(cert); 173e1051a39Sopenharmony_ci if (pretmp == NULL) 174e1051a39Sopenharmony_ci goto err; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci X509_EXTENSION_free(X509_delete_ext(pretmp, idx)); 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci if (!ct_x509_cert_fixup(pretmp, presigner)) 179e1051a39Sopenharmony_ci goto err; 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci prederlen = i2d_re_X509_tbs(pretmp, &preder); 182e1051a39Sopenharmony_ci if (prederlen <= 0) 183e1051a39Sopenharmony_ci goto err; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci X509_free(pretmp); 187e1051a39Sopenharmony_ci 188e1051a39Sopenharmony_ci OPENSSL_free(sctx->certder); 189e1051a39Sopenharmony_ci sctx->certder = certder; 190e1051a39Sopenharmony_ci sctx->certderlen = certderlen; 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci OPENSSL_free(sctx->preder); 193e1051a39Sopenharmony_ci sctx->preder = preder; 194e1051a39Sopenharmony_ci sctx->prederlen = prederlen; 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_ci return 1; 197e1051a39Sopenharmony_cierr: 198e1051a39Sopenharmony_ci OPENSSL_free(certder); 199e1051a39Sopenharmony_ci OPENSSL_free(preder); 200e1051a39Sopenharmony_ci X509_free(pretmp); 201e1051a39Sopenharmony_ci return 0; 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci__owur static int ct_public_key_hash(SCT_CTX *sctx, X509_PUBKEY *pkey, 205e1051a39Sopenharmony_ci unsigned char **hash, size_t *hash_len) 206e1051a39Sopenharmony_ci{ 207e1051a39Sopenharmony_ci int ret = 0; 208e1051a39Sopenharmony_ci unsigned char *md = NULL, *der = NULL; 209e1051a39Sopenharmony_ci int der_len; 210e1051a39Sopenharmony_ci unsigned int md_len; 211e1051a39Sopenharmony_ci EVP_MD *sha256 = EVP_MD_fetch(sctx->libctx, "SHA2-256", sctx->propq); 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci if (sha256 == NULL) 214e1051a39Sopenharmony_ci goto err; 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_ci /* Reuse buffer if possible */ 217e1051a39Sopenharmony_ci if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) { 218e1051a39Sopenharmony_ci md = *hash; 219e1051a39Sopenharmony_ci } else { 220e1051a39Sopenharmony_ci md = OPENSSL_malloc(SHA256_DIGEST_LENGTH); 221e1051a39Sopenharmony_ci if (md == NULL) 222e1051a39Sopenharmony_ci goto err; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ci /* Calculate key hash */ 226e1051a39Sopenharmony_ci der_len = i2d_X509_PUBKEY(pkey, &der); 227e1051a39Sopenharmony_ci if (der_len <= 0) 228e1051a39Sopenharmony_ci goto err; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if (!EVP_Digest(der, der_len, md, &md_len, sha256, NULL)) 231e1051a39Sopenharmony_ci goto err; 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci if (md != *hash) { 234e1051a39Sopenharmony_ci OPENSSL_free(*hash); 235e1051a39Sopenharmony_ci *hash = md; 236e1051a39Sopenharmony_ci *hash_len = SHA256_DIGEST_LENGTH; 237e1051a39Sopenharmony_ci } 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci md = NULL; 240e1051a39Sopenharmony_ci ret = 1; 241e1051a39Sopenharmony_ci err: 242e1051a39Sopenharmony_ci EVP_MD_free(sha256); 243e1051a39Sopenharmony_ci OPENSSL_free(md); 244e1051a39Sopenharmony_ci OPENSSL_free(der); 245e1051a39Sopenharmony_ci return ret; 246e1051a39Sopenharmony_ci} 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ciint SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer) 249e1051a39Sopenharmony_ci{ 250e1051a39Sopenharmony_ci return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer)); 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ciint SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) 254e1051a39Sopenharmony_ci{ 255e1051a39Sopenharmony_ci return ct_public_key_hash(sctx, pubkey, &sctx->ihash, &sctx->ihashlen); 256e1051a39Sopenharmony_ci} 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ciint SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey) 259e1051a39Sopenharmony_ci{ 260e1051a39Sopenharmony_ci EVP_PKEY *pkey = X509_PUBKEY_get(pubkey); 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci if (pkey == NULL) 263e1051a39Sopenharmony_ci return 0; 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci if (!ct_public_key_hash(sctx, pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) { 266e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 267e1051a39Sopenharmony_ci return 0; 268e1051a39Sopenharmony_ci } 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci EVP_PKEY_free(sctx->pkey); 271e1051a39Sopenharmony_ci sctx->pkey = pkey; 272e1051a39Sopenharmony_ci return 1; 273e1051a39Sopenharmony_ci} 274e1051a39Sopenharmony_ci 275e1051a39Sopenharmony_civoid SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms) 276e1051a39Sopenharmony_ci{ 277e1051a39Sopenharmony_ci sctx->epoch_time_in_ms = time_in_ms; 278e1051a39Sopenharmony_ci} 279