check in v3.8.1 source

This commit is contained in:
2023-09-03 18:24:16 -07:00
parent fbb21ed921
commit b31c897352
1205 changed files with 561101 additions and 0 deletions

226
crypto/ct/ct_b64.c Normal file
View File

@@ -0,0 +1,226 @@
/* $OpenBSD: ct_b64.c,v 1.7 2023/07/08 07:22:58 beck Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <limits.h>
#include <string.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "bytestring.h"
#include "ct_local.h"
/*
* Decodes the base64 string |in| into |out|.
* A new string will be malloc'd and assigned to |out|. This will be owned by
* the caller. Do not provide a pre-allocated string in |out|.
*/
static int
ct_base64_decode(const char *in, unsigned char **out)
{
size_t inlen = strlen(in);
int outlen, i;
unsigned char *outbuf = NULL;
if (inlen == 0) {
*out = NULL;
return 0;
}
outlen = (inlen / 4) * 3;
outbuf = malloc(outlen);
if (outbuf == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen);
if (outlen < 0) {
CTerror(CT_R_BASE64_DECODE_ERROR);
goto err;
}
/*
* Subtract padding bytes from |outlen|.
* Any more than 2 is malformed.
*/
i = 0;
while (in[--inlen] == '=') {
--outlen;
if (++i > 2)
goto err;
}
*out = outbuf;
return outlen;
err:
free(outbuf);
return -1;
}
SCT *
SCT_new_from_base64(unsigned char version, const char *logid_base64,
ct_log_entry_type_t entry_type, uint64_t timestamp,
const char *extensions_base64, const char *signature_base64)
{
unsigned char *dec = NULL;
int declen;
SCT *sct;
CBS cbs;
if ((sct = SCT_new()) == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
/*
* RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we
* can only construct SCT versions that have been defined.
*/
if (!SCT_set_version(sct, version)) {
CTerror(CT_R_SCT_UNSUPPORTED_VERSION);
goto err;
}
declen = ct_base64_decode(logid_base64, &dec);
if (declen < 0) {
CTerror(X509_R_BASE64_DECODE_ERROR);
goto err;
}
if (!SCT_set0_log_id(sct, dec, declen))
goto err;
dec = NULL;
declen = ct_base64_decode(extensions_base64, &dec);
if (declen < 0) {
CTerror(X509_R_BASE64_DECODE_ERROR);
goto err;
}
SCT_set0_extensions(sct, dec, declen);
dec = NULL;
declen = ct_base64_decode(signature_base64, &dec);
if (declen < 0) {
CTerror(X509_R_BASE64_DECODE_ERROR);
goto err;
}
CBS_init(&cbs, dec, declen);
if (!o2i_SCT_signature(sct, &cbs))
goto err;
free(dec);
dec = NULL;
SCT_set_timestamp(sct, timestamp);
if (!SCT_set_log_entry_type(sct, entry_type))
goto err;
return sct;
err:
free(dec);
SCT_free(sct);
return NULL;
}
LCRYPTO_ALIAS(SCT_new_from_base64);
/*
* Allocate, build and returns a new |ct_log| from input |pkey_base64|
* It returns 1 on success,
* 0 on decoding failure, or invalid parameter if any
* -1 on internal (malloc) failure
*/
int
CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *name)
{
unsigned char *pkey_der = NULL;
int pkey_der_len;
const unsigned char *p;
EVP_PKEY *pkey = NULL;
if (ct_log == NULL) {
CTerror(ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der);
if (pkey_der_len < 0) {
CTerror(CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
p = pkey_der;
pkey = d2i_PUBKEY(NULL, &p, pkey_der_len);
free(pkey_der);
if (pkey == NULL) {
CTerror(CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
*ct_log = CTLOG_new(pkey, name);
if (*ct_log == NULL) {
EVP_PKEY_free(pkey);
return 0;
}
return 1;
}
LCRYPTO_ALIAS(CTLOG_new_from_base64);

147
crypto/ct/ct_err.c Normal file
View File

@@ -0,0 +1,147 @@
/* $OpenBSD: ct_err.c,v 1.7 2022/07/12 14:42:48 kn Exp $ */
/* ====================================================================
* Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <openssl/ct.h>
#include <openssl/err.h>
#ifndef OPENSSL_NO_ERR
static ERR_STRING_DATA CT_str_functs[] = {
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW, 0), "CTLOG_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_BASE64, 0),
"CTLOG_new_from_base64"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_NEW_FROM_CONF, 0),
"ctlog_new_from_conf"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_CTX_NEW, 0),
"ctlog_store_load_ctx_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_FILE, 0),
"CTLOG_STORE_load_file"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_LOAD_LOG, 0),
"ctlog_store_load_log"},
{ERR_PACK(ERR_LIB_CT, CT_F_CTLOG_STORE_NEW, 0), "CTLOG_STORE_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_CT_BASE64_DECODE, 0), "ct_base64_decode"},
{ERR_PACK(ERR_LIB_CT, CT_F_CT_POLICY_EVAL_CTX_NEW, 0),
"CT_POLICY_EVAL_CTX_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_CT_V1_LOG_ID_FROM_PKEY, 0),
"ct_v1_log_id_from_pkey"},
{ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT, 0), "i2o_SCT"},
{ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_LIST, 0), "i2o_SCT_LIST"},
{ERR_PACK(ERR_LIB_CT, CT_F_I2O_SCT_SIGNATURE, 0), "i2o_SCT_signature"},
{ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT, 0), "o2i_SCT"},
{ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_LIST, 0), "o2i_SCT_LIST"},
{ERR_PACK(ERR_LIB_CT, CT_F_O2I_SCT_SIGNATURE, 0), "o2i_SCT_signature"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_NEW, 0), "SCT_CTX_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_CTX_VERIFY, 0), "SCT_CTX_verify"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW, 0), "SCT_new"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_NEW_FROM_BASE64, 0),
"SCT_new_from_base64"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET0_LOG_ID, 0), "SCT_set0_log_id"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_EXTENSIONS, 0),
"SCT_set1_extensions"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_LOG_ID, 0), "SCT_set1_log_id"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET1_SIGNATURE, 0),
"SCT_set1_signature"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_LOG_ENTRY_TYPE, 0),
"SCT_set_log_entry_type"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_SIGNATURE_NID, 0),
"SCT_set_signature_nid"},
{ERR_PACK(ERR_LIB_CT, CT_F_SCT_SET_VERSION, 0), "SCT_set_version"},
{0, NULL}
};
static ERR_STRING_DATA CT_str_reasons[] = {
{ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR),
"base64 decode error"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_INVALID_LOG_ID_LENGTH),
"invalid log id length"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID), "log conf invalid"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID_KEY),
"log conf invalid key"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_DESCRIPTION),
"log conf missing description"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_KEY),
"log conf missing key"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_KEY_INVALID), "log key invalid"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_FUTURE_TIMESTAMP),
"sct future timestamp"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID), "sct invalid"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID_SIGNATURE),
"sct invalid signature"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LIST_INVALID), "sct list invalid"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LOG_ID_MISMATCH),
"sct log id mismatch"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_NOT_SET), "sct not set"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_UNSUPPORTED_VERSION),
"sct unsupported version"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNRECOGNIZED_SIGNATURE_NID),
"unrecognized signature nid"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_ENTRY_TYPE),
"unsupported entry type"},
{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_VERSION),
"unsupported version"},
{0, NULL}
};
#endif
int
ERR_load_CT_strings(void)
{
if (ERR_func_error_string(CT_str_functs[0].error) == NULL) {
ERR_load_strings(0, CT_str_functs);
ERR_load_strings(0, CT_str_reasons);
}
return 1;
}

260
crypto/ct/ct_local.h Normal file
View File

@@ -0,0 +1,260 @@
/* $OpenBSD: ct_local.h,v 1.8 2021/12/20 17:19:19 jsing Exp $ */
/*
* Written by Rob Percival (robpercival@google.com) for the OpenSSL project.
*/
/* ====================================================================
* Copyright (c) 2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stddef.h>
#include <openssl/ct.h>
#include <openssl/evp.h>
#include <openssl/safestack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "bytestring.h"
/* Number of bytes in an SCT v1 LogID - see RFC 6962 section 3.2. */
#define CT_V1_LOG_ID_LEN 32
/* Maximum size of an SCT - see RFC 6962 section 3.3. */
#define MAX_SCT_SIZE 65535
#define MAX_SCT_LIST_SIZE MAX_SCT_SIZE
/*
* Macros to write integers in network-byte order.
*/
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
c[1]=(unsigned char)(((s) )&0xff)),c+=2)
#define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \
c[1]=(unsigned char)(((l)>> 8)&0xff), \
c[2]=(unsigned char)(((l) )&0xff)),c+=3)
#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
*((c)++)=(unsigned char)(((l)>>48)&0xff), \
*((c)++)=(unsigned char)(((l)>>40)&0xff), \
*((c)++)=(unsigned char)(((l)>>32)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
/* Signed Certificate Timestamp */
struct sct_st {
sct_version_t version;
/* If version is not SCT_VERSION_V1, this contains the encoded SCT */
unsigned char *sct;
size_t sct_len;
/*
* If version is SCT_VERSION_V1, fields below contain components of
* the SCT
*/
unsigned char *log_id;
size_t log_id_len;
/*
* Note, we cannot distinguish between an unset timestamp, and one
* that is set to 0. However since CT didn't exist in 1970, no real
* SCT should ever be set as such.
*/
uint64_t timestamp;
unsigned char *ext;
size_t ext_len;
unsigned char hash_alg;
unsigned char sig_alg;
unsigned char *sig;
size_t sig_len;
/* Log entry type */
ct_log_entry_type_t entry_type;
/* Where this SCT was found, e.g. certificate, OCSP response, etc. */
sct_source_t source;
/* The result of the last attempt to validate this SCT. */
sct_validation_status_t validation_status;
};
/* Miscellaneous data that is useful when verifying an SCT */
struct sct_ctx_st {
/* Public key */
EVP_PKEY *pkey;
/* Hash of public key */
unsigned char *pkeyhash;
size_t pkeyhashlen;
/* For pre-certificate: issuer public key hash */
unsigned char *ihash;
size_t ihashlen;
/* certificate encoding */
unsigned char *certder;
size_t certderlen;
/* pre-certificate encoding */
unsigned char *preder;
size_t prederlen;
/*
* milliseconds since epoch (to check that the SCT isn't from the
* future)
*/
uint64_t epoch_time_in_ms;
};
/* Context when evaluating whether a Certificate Transparency policy is met */
struct ct_policy_eval_ctx_st {
X509 *cert;
X509 *issuer;
CTLOG_STORE *log_store;
/*
* milliseconds since epoch (to check that the SCT isn't from the
* future)
*/
uint64_t epoch_time_in_ms;
};
/*
* Creates a new context for verifying an SCT.
*/
SCT_CTX *SCT_CTX_new(void);
/*
* Deletes an SCT verification context.
*/
void SCT_CTX_free(SCT_CTX *sctx);
/*
* Sets the certificate that the SCT was created for.
* If *cert does not have a poison extension, presigner must be NULL.
* If *cert does not have a poison extension, it may have a single SCT
* (NID_ct_precert_scts) extension.
* If either *cert or *presigner have an AKID (NID_authority_key_identifier)
* extension, both must have one.
* Returns 1 on success, 0 on failure.
*/
int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner);
/*
* Sets the issuer of the certificate that the SCT was created for.
* This is just a convenience method to save extracting the public key and
* calling SCT_CTX_set1_issuer_pubkey().
* Issuer must not be NULL.
* Returns 1 on success, 0 on failure.
*/
int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer);
/*
* Sets the public key of the issuer of the certificate that the SCT was created
* for.
* The public key must not be NULL.
* Returns 1 on success, 0 on failure.
*/
int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
/*
* Sets the public key of the CT log that the SCT is from.
* Returns 1 on success, 0 on failure.
*/
int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
/*
* Sets the time to evaluate the SCT against, in milliseconds since the Unix
* epoch. If the SCT's timestamp is after this time, it will be interpreted as
* having been issued in the future. RFC6962 states that "TLS clients MUST
* reject SCTs whose timestamp is in the future", so an SCT will not validate
* in this case.
*/
void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms);
/*
* Verifies an SCT with the given context.
* Returns 1 if the SCT verifies successfully; any other value indicates
* failure. See EVP_DigestVerifyFinal() for the meaning of those values.
*/
int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct);
/*
* Does this SCT have the minimum fields populated to be usable?
* Returns 1 if so, 0 otherwise.
*/
int SCT_is_complete(const SCT *sct);
/*
* Does this SCT have the signature-related fields populated?
* Returns 1 if so, 0 otherwise.
* This checks that the signature and hash algorithms are set to supported
* values and that the signature field is set.
*/
int SCT_signature_is_complete(const SCT *sct);
/*
* TODO(RJPercival): Create an SCT_signature struct and make i2o_SCT_signature
* and o2i_SCT_signature conform to the i2d/d2i conventions.
*/
/*
* Serialize (to TLS format) an |sct| signature and write it to |out|.
* If |out| is null, no signature will be output but the length will be returned.
* If |out| points to a null pointer, a string will be allocated to hold the
* TLS-format signature. It is the responsibility of the caller to free it.
* If |out| points to an allocated string, the signature will be written to it.
* The length of the signature in TLS format will be returned.
*/
int i2o_SCT_signature(const SCT *sct, unsigned char **out);
/*
* Parses an SCT signature in TLS format and populates the |sct| with it.
* |in| should be a pointer to a string containing the TLS-format signature.
* |in| will be advanced to the end of the signature if parsing succeeds.
* |len| should be the length of the signature in |in|.
* Returns the number of bytes parsed, or a negative integer if an error occurs.
* If an error occurs, the SCT's signature NID may be updated whilst the
* signature field itself remains unset.
*/
int o2i_SCT_signature(SCT *sct, CBS *cbs);
/*
* Handlers for Certificate Transparency X509v3/OCSP extensions
*/
extern const X509V3_EXT_METHOD v3_ct_scts[3];

375
crypto/ct/ct_log.c Normal file
View File

@@ -0,0 +1,375 @@
/* $OpenBSD: ct_log.c,v 1.6 2023/07/08 07:22:58 beck Exp $ */
/* Author: Adam Eijdenberg <adam.eijdenberg@gmail.com>. */
/* ====================================================================
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/safestack.h>
#include "cryptlib.h"
/*
* Information about a CT log server.
*/
struct ctlog_st {
char *name;
uint8_t log_id[CT_V1_HASHLEN];
EVP_PKEY *public_key;
};
/*
* A store for multiple CTLOG instances.
* It takes ownership of any CTLOG instances added to it.
*/
struct ctlog_store_st {
STACK_OF(CTLOG) *logs;
};
/* The context when loading a CT log list from a CONF file. */
typedef struct ctlog_store_load_ctx_st {
CTLOG_STORE *log_store;
CONF *conf;
size_t invalid_log_entries;
} CTLOG_STORE_LOAD_CTX;
/*
* Creates an empty context for loading a CT log store.
* It should be populated before use.
*/
static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void);
/*
* Deletes a CT log store load context.
* Does not delete any of the fields.
*/
static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX *ctx);
static CTLOG_STORE_LOAD_CTX *
ctlog_store_load_ctx_new(void)
{
CTLOG_STORE_LOAD_CTX *ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL)
CTerror(ERR_R_MALLOC_FAILURE);
return ctx;
}
static void
ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX *ctx)
{
free(ctx);
}
/* Converts a log's public key into a SHA256 log ID */
static int
ct_v1_log_id_from_pkey(EVP_PKEY *pkey, unsigned char log_id[CT_V1_HASHLEN])
{
int ret = 0;
unsigned char *pkey_der = NULL;
int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
if (pkey_der_len <= 0) {
CTerror(CT_R_LOG_KEY_INVALID);
goto err;
}
SHA256(pkey_der, pkey_der_len, log_id);
ret = 1;
err:
free(pkey_der);
return ret;
}
CTLOG_STORE *
CTLOG_STORE_new(void)
{
CTLOG_STORE *ret = calloc(1, sizeof(*ret));
if (ret == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->logs = sk_CTLOG_new_null();
if (ret->logs == NULL)
goto err;
return ret;
err:
free(ret);
return NULL;
}
LCRYPTO_ALIAS(CTLOG_STORE_new);
void
CTLOG_STORE_free(CTLOG_STORE *store)
{
if (store != NULL) {
sk_CTLOG_pop_free(store->logs, CTLOG_free);
free(store);
}
}
LCRYPTO_ALIAS(CTLOG_STORE_free);
static int
ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section)
{
const char *description = NCONF_get_string(conf, section,
"description");
char *pkey_base64;
if (description == NULL) {
CTerror(CT_R_LOG_CONF_MISSING_DESCRIPTION);
return 0;
}
pkey_base64 = NCONF_get_string(conf, section, "key");
if (pkey_base64 == NULL) {
CTerror(CT_R_LOG_CONF_MISSING_KEY);
return 0;
}
return CTLOG_new_from_base64(ct_log, pkey_base64, description);
}
int
CTLOG_STORE_load_default_file(CTLOG_STORE *store)
{
return CTLOG_STORE_load_file(store, CTLOG_FILE);
}
LCRYPTO_ALIAS(CTLOG_STORE_load_default_file);
/*
* Called by CONF_parse_list, which stops if this returns <= 0,
* Otherwise, one bad log entry would stop loading of any of
* the following log entries.
* It may stop parsing and returns -1 on any internal (malloc) error.
*/
static int
ctlog_store_load_log(const char *log_name, int log_name_len, void *arg)
{
CTLOG_STORE_LOAD_CTX *load_ctx = arg;
CTLOG *ct_log = NULL;
/* log_name may not be null-terminated, so fix that before using it */
char *tmp;
int ret = 0;
/* log_name will be NULL for empty list entries */
if (log_name == NULL)
return 1;
tmp = strndup(log_name, log_name_len);
if (tmp == NULL)
goto mem_err;
ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp);
free(tmp);
if (ret < 0) {
/* Propagate any internal error */
return ret;
}
if (ret == 0) {
/* If we can't load this log, record that fact and skip it */
++load_ctx->invalid_log_entries;
return 1;
}
if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) {
goto mem_err;
}
return 1;
mem_err:
CTLOG_free(ct_log);
CTerror(ERR_R_MALLOC_FAILURE);
return -1;
}
int
CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
{
int ret = 0;
char *enabled_logs;
CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new();
if (load_ctx == NULL)
return 0;
load_ctx->log_store = store;
load_ctx->conf = NCONF_new(NULL);
if (load_ctx->conf == NULL)
goto end;
if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
CTerror(CT_R_LOG_CONF_INVALID);
goto end;
}
enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
if (enabled_logs == NULL) {
CTerror(CT_R_LOG_CONF_INVALID);
goto end;
}
if (!CONF_parse_list(enabled_logs, ',', 1, ctlog_store_load_log, load_ctx) ||
load_ctx->invalid_log_entries > 0) {
CTerror(CT_R_LOG_CONF_INVALID);
goto end;
}
ret = 1;
end:
NCONF_free(load_ctx->conf);
ctlog_store_load_ctx_free(load_ctx);
return ret;
}
LCRYPTO_ALIAS(CTLOG_STORE_load_file);
/*
* Initialize a new CTLOG object.
* Takes ownership of the public key.
* Copies the name.
*/
CTLOG *
CTLOG_new(EVP_PKEY *public_key, const char *name)
{
CTLOG *ret = calloc(1, sizeof(*ret));
if (ret == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->name = strdup(name);
if (ret->name == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1)
goto err;
ret->public_key = public_key;
return ret;
err:
CTLOG_free(ret);
return NULL;
}
LCRYPTO_ALIAS(CTLOG_new);
/* Frees CT log and associated structures */
void
CTLOG_free(CTLOG *log)
{
if (log != NULL) {
free(log->name);
EVP_PKEY_free(log->public_key);
free(log);
}
}
LCRYPTO_ALIAS(CTLOG_free);
const char *
CTLOG_get0_name(const CTLOG *log)
{
return log->name;
}
LCRYPTO_ALIAS(CTLOG_get0_name);
void
CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, size_t *log_id_len)
{
*log_id = log->log_id;
*log_id_len = CT_V1_HASHLEN;
}
LCRYPTO_ALIAS(CTLOG_get0_log_id);
EVP_PKEY *
CTLOG_get0_public_key(const CTLOG *log)
{
return log->public_key;
}
LCRYPTO_ALIAS(CTLOG_get0_public_key);
/*
* Given a log ID, finds the matching log.
* Returns NULL if no match found.
*/
const CTLOG *
CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, const uint8_t *log_id,
size_t log_id_len)
{
int i;
for (i = 0; i < sk_CTLOG_num(store->logs); ++i) {
const CTLOG *log = sk_CTLOG_value(store->logs, i);
if (memcmp(log->log_id, log_id, log_id_len) == 0)
return log;
}
return NULL;
}
LCRYPTO_ALIAS(CTLOG_STORE_get0_log_by_id);

464
crypto/ct/ct_oct.c Normal file
View File

@@ -0,0 +1,464 @@
/* $OpenBSD: ct_oct.c,v 1.9 2023/07/08 07:22:58 beck Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifdef OPENSSL_NO_CT
# error "CT is disabled"
#endif
#include <limits.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/buffer.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include "bytestring.h"
#include "ct_local.h"
int
o2i_SCT_signature(SCT *sct, CBS *cbs)
{
uint8_t hash_alg, sig_alg;
CBS signature;
if (sct->version != SCT_VERSION_V1) {
CTerror(CT_R_UNSUPPORTED_VERSION);
return 0;
}
/*
* Parse a digitally-signed element - see RFC 6962 section 3.2 and
* RFC 5246 sections 4.7 and 7.4.1.4.1.
*/
if (!CBS_get_u8(cbs, &hash_alg))
goto err_invalid;
if (!CBS_get_u8(cbs, &sig_alg))
goto err_invalid;
if (!CBS_get_u16_length_prefixed(cbs, &signature))
goto err_invalid;
if (CBS_len(cbs) != 0)
goto err_invalid;
/*
* Reject empty signatures since they are invalid for all supported
* algorithms (this really should be done by SCT_set1_signature()).
*/
if (CBS_len(&signature) == 0)
goto err_invalid;
sct->hash_alg = hash_alg;
sct->sig_alg = sig_alg;
if (SCT_get_signature_nid(sct) == NID_undef)
goto err_invalid;
if (!SCT_set1_signature(sct, CBS_data(&signature), CBS_len(&signature)))
return 0;
return 1;
err_invalid:
CTerror(CT_R_SCT_INVALID_SIGNATURE);
return 0;
}
static int
o2i_SCT_internal(SCT **out_sct, CBS *cbs)
{
SCT *sct = NULL;
uint8_t version;
*out_sct = NULL;
if ((sct = SCT_new()) == NULL)
goto err;
if (CBS_len(cbs) > MAX_SCT_SIZE)
goto err_invalid;
if (!CBS_peek_u8(cbs, &version))
goto err_invalid;
sct->version = version;
if (version == SCT_VERSION_V1) {
CBS extensions, log_id;
uint64_t timestamp;
/*
* Parse a v1 SignedCertificateTimestamp - see RFC 6962
* section 3.2.
*/
if (!CBS_get_u8(cbs, &version))
goto err_invalid;
if (!CBS_get_bytes(cbs, &log_id, CT_V1_LOG_ID_LEN))
goto err_invalid;
if (!CBS_get_u64(cbs, &timestamp))
goto err_invalid;
if (!CBS_get_u16_length_prefixed(cbs, &extensions))
goto err_invalid;
if (!CBS_stow(&log_id, &sct->log_id, &sct->log_id_len))
goto err;
sct->timestamp = timestamp;
if (!CBS_stow(&extensions, &sct->ext, &sct->ext_len))
goto err;
if (!o2i_SCT_signature(sct, cbs))
goto err;
if (CBS_len(cbs) != 0)
goto err_invalid;
} else {
/* If not V1 just cache encoding. */
if (!CBS_stow(cbs, &sct->sct, &sct->sct_len))
goto err;
}
*out_sct = sct;
return 1;
err_invalid:
CTerror(CT_R_SCT_INVALID);
err:
SCT_free(sct);
return 0;
}
SCT *
o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
{
SCT *sct;
CBS cbs;
CBS_init(&cbs, *in, len);
if (psct != NULL) {
SCT_free(*psct);
*psct = NULL;
}
if (!o2i_SCT_internal(&sct, &cbs))
return NULL;
if (psct != NULL)
*psct = sct;
*in = CBS_data(&cbs);
return sct;
}
LCRYPTO_ALIAS(o2i_SCT);
int
i2o_SCT_signature(const SCT *sct, unsigned char **out)
{
size_t len;
unsigned char *p = NULL, *pstart = NULL;
if (!SCT_signature_is_complete(sct)) {
CTerror(CT_R_SCT_INVALID_SIGNATURE);
goto err;
}
if (sct->version != SCT_VERSION_V1) {
CTerror(CT_R_UNSUPPORTED_VERSION);
goto err;
}
/*
* (1 byte) Hash algorithm
* (1 byte) Signature algorithm
* (2 bytes + ?) Signature
*/
len = 4 + sct->sig_len;
if (out != NULL) {
if (*out != NULL) {
p = *out;
*out += len;
} else {
pstart = p = malloc(len);
if (p == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
*out = p;
}
*p++ = sct->hash_alg;
*p++ = sct->sig_alg;
s2n(sct->sig_len, p);
memcpy(p, sct->sig, sct->sig_len);
}
return len;
err:
free(pstart);
return -1;
}
int
i2o_SCT(const SCT *sct, unsigned char **out)
{
size_t len;
unsigned char *p = NULL, *pstart = NULL;
if (!SCT_is_complete(sct)) {
CTerror(CT_R_SCT_NOT_SET);
goto err;
}
/*
* Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes)
* log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions
* extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2
* bytes + ?) Signature
*/
if (sct->version == SCT_VERSION_V1)
len = 43 + sct->ext_len + 4 + sct->sig_len;
else
len = sct->sct_len;
if (out == NULL)
return len;
if (*out != NULL) {
p = *out;
*out += len;
} else {
pstart = p = malloc(len);
if (p == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
*out = p;
}
if (sct->version == SCT_VERSION_V1) {
*p++ = sct->version;
memcpy(p, sct->log_id, CT_V1_HASHLEN);
p += CT_V1_HASHLEN;
l2n8(sct->timestamp, p);
s2n(sct->ext_len, p);
if (sct->ext_len > 0) {
memcpy(p, sct->ext, sct->ext_len);
p += sct->ext_len;
}
if (i2o_SCT_signature(sct, &p) <= 0)
goto err;
} else {
memcpy(p, sct->sct, len);
}
return len;
err:
free(pstart);
return -1;
}
LCRYPTO_ALIAS(i2o_SCT);
STACK_OF(SCT) *
o2i_SCT_LIST(STACK_OF(SCT) **out_scts, const unsigned char **pp, size_t len)
{
CBS cbs, cbs_scts, cbs_sct;
STACK_OF(SCT) *scts = NULL;
CBS_init(&cbs, *pp, len);
if (CBS_len(&cbs) > MAX_SCT_LIST_SIZE)
goto err_invalid;
if (!CBS_get_u16_length_prefixed(&cbs, &cbs_scts))
goto err_invalid;
if (CBS_len(&cbs) != 0)
goto err_invalid;
if (out_scts != NULL) {
SCT_LIST_free(*out_scts);
*out_scts = NULL;
}
if ((scts = sk_SCT_new_null()) == NULL)
return NULL;
while (CBS_len(&cbs_scts) > 0) {
SCT *sct;
if (!CBS_get_u16_length_prefixed(&cbs_scts, &cbs_sct))
goto err_invalid;
if (!o2i_SCT_internal(&sct, &cbs_sct))
goto err;
if (!sk_SCT_push(scts, sct)) {
SCT_free(sct);
goto err;
}
}
if (out_scts != NULL)
*out_scts = scts;
*pp = CBS_data(&cbs);
return scts;
err_invalid:
CTerror(CT_R_SCT_LIST_INVALID);
err:
SCT_LIST_free(scts);
return NULL;
}
LCRYPTO_ALIAS(o2i_SCT_LIST);
int
i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
{
int len, sct_len, i, is_pp_new = 0;
size_t len2;
unsigned char *p = NULL, *p2;
if (pp != NULL) {
if (*pp == NULL) {
if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
CTerror(CT_R_SCT_LIST_INVALID);
return -1;
}
if ((*pp = malloc(len)) == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return -1;
}
is_pp_new = 1;
}
p = *pp + 2;
}
len2 = 2;
for (i = 0; i < sk_SCT_num(a); i++) {
if (pp != NULL) {
p2 = p;
p += 2;
if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1)
goto err;
s2n(sct_len, p2);
} else {
if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1)
goto err;
}
len2 += 2 + sct_len;
}
if (len2 > MAX_SCT_LIST_SIZE)
goto err;
if (pp != NULL) {
p = *pp;
s2n(len2 - 2, p);
if (!is_pp_new)
*pp += len2;
}
return len2;
err:
if (is_pp_new) {
free(*pp);
*pp = NULL;
}
return -1;
}
LCRYPTO_ALIAS(i2o_SCT_LIST);
STACK_OF(SCT) *
d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
{
ASN1_OCTET_STRING *oct = NULL;
STACK_OF(SCT) *sk = NULL;
const unsigned char *p;
p = *pp;
if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL)
return NULL;
p = oct->data;
if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL)
*pp += len;
ASN1_OCTET_STRING_free(oct);
return sk;
}
LCRYPTO_ALIAS(d2i_SCT_LIST);
int
i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out)
{
ASN1_OCTET_STRING oct;
int len;
oct.data = NULL;
if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1)
return -1;
len = i2d_ASN1_OCTET_STRING(&oct, out);
free(oct.data);
return len;
}
LCRYPTO_ALIAS(i2d_SCT_LIST);

163
crypto/ct/ct_policy.c Normal file
View File

@@ -0,0 +1,163 @@
/* $OpenBSD: ct_policy.c,v 1.6 2023/07/08 07:22:58 beck Exp $ */
/*
* Implementations of Certificate Transparency SCT policies.
* Written by Rob Percival (robpercival@google.com) for the OpenSSL project.
*/
/* ====================================================================
* Copyright (c) 2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#ifdef OPENSSL_NO_CT
# error "CT is disabled"
#endif
#include <openssl/ct.h>
#include <openssl/err.h>
#include <time.h>
#include "ct_local.h"
/*
* Number of seconds in the future that an SCT timestamp can be, by default,
* without being considered invalid. This is added to time() when setting a
* default value for CT_POLICY_EVAL_CTX.epoch_time_in_ms.
* It can be overridden by calling CT_POLICY_EVAL_CTX_set_time().
*/
static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300;
CT_POLICY_EVAL_CTX *
CT_POLICY_EVAL_CTX_new(void)
{
CT_POLICY_EVAL_CTX *ctx = calloc(1, sizeof(CT_POLICY_EVAL_CTX));
if (ctx == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
/* time(NULL) shouldn't ever fail, so don't bother checking for -1. */
ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) *
1000;
return ctx;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_new);
void
CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx)
{
if (ctx == NULL)
return;
X509_free(ctx->cert);
X509_free(ctx->issuer);
free(ctx);
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_free);
int
CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert)
{
if (!X509_up_ref(cert))
return 0;
ctx->cert = cert;
return 1;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set1_cert);
int
CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer)
{
if (!X509_up_ref(issuer))
return 0;
ctx->issuer = issuer;
return 1;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set1_issuer);
void
CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
CTLOG_STORE *log_store)
{
ctx->log_store = log_store;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE);
void
CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms)
{
ctx->epoch_time_in_ms = time_in_ms;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set_time);
X509 *
CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx)
{
return ctx->cert;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_cert);
X509 *
CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx)
{
return ctx->issuer;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_issuer);
const CTLOG_STORE *
CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx)
{
return ctx->log_store;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_log_store);
uint64_t
CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx)
{
return ctx->epoch_time_in_ms;
}
LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get_time);

211
crypto/ct/ct_prn.c Normal file
View File

@@ -0,0 +1,211 @@
/* $OpenBSD: ct_prn.c,v 1.7 2023/07/08 07:22:58 beck Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifdef OPENSSL_NO_CT
# error "CT is disabled"
#endif
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include "ct_local.h"
/*
* XXX public api in OpenSSL 1.1.0 but this is the only thing that uses it.
* so I am stuffing it here for the moment.
*/
static int
BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
int datalen)
{
int i, j = 0;
if (datalen < 1)
return 1;
for (i = 0; i < datalen - 1; i++) {
if (i && !j)
BIO_printf(out, "%*s", indent, "");
BIO_printf(out, "%02X:", data[i]);
j = (j + 1) % width;
if (!j)
BIO_printf(out, "\n");
}
if (i && !j)
BIO_printf(out, "%*s", indent, "");
BIO_printf(out, "%02X", data[datalen - 1]);
return 1;
}
static void
SCT_signature_algorithms_print(const SCT *sct, BIO *out)
{
int nid = SCT_get_signature_nid(sct);
if (nid == NID_undef)
BIO_printf(out, "%02X%02X", sct->hash_alg, sct->sig_alg);
else
BIO_printf(out, "%s", OBJ_nid2ln(nid));
}
static void
timestamp_print(uint64_t timestamp, BIO *out)
{
ASN1_GENERALIZEDTIME *gen = ASN1_GENERALIZEDTIME_new();
char genstr[20];
if (gen == NULL)
return;
ASN1_GENERALIZEDTIME_adj(gen, (time_t)0, (int)(timestamp / 86400000),
(timestamp % 86400000) / 1000);
/*
* Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15
* characters long with a final Z. Update it with fractional seconds.
*/
snprintf(genstr, sizeof(genstr), "%.14sZ", ASN1_STRING_get0_data(gen));
if (ASN1_GENERALIZEDTIME_set_string(gen, genstr))
ASN1_GENERALIZEDTIME_print(out, gen);
ASN1_GENERALIZEDTIME_free(gen);
}
const char *
SCT_validation_status_string(const SCT *sct)
{
switch (SCT_get_validation_status(sct)) {
case SCT_VALIDATION_STATUS_NOT_SET:
return "not set";
case SCT_VALIDATION_STATUS_UNKNOWN_VERSION:
return "unknown version";
case SCT_VALIDATION_STATUS_UNKNOWN_LOG:
return "unknown log";
case SCT_VALIDATION_STATUS_UNVERIFIED:
return "unverified";
case SCT_VALIDATION_STATUS_INVALID:
return "invalid";
case SCT_VALIDATION_STATUS_VALID:
return "valid";
}
return "unknown status";
}
LCRYPTO_ALIAS(SCT_validation_status_string);
void
SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *log_store)
{
const CTLOG *log = NULL;
if (log_store != NULL) {
log = CTLOG_STORE_get0_log_by_id(log_store, sct->log_id,
sct->log_id_len);
}
BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, "");
BIO_printf(out, "\n%*sVersion : ", indent + 4, "");
if (sct->version != SCT_VERSION_V1) {
BIO_printf(out, "unknown\n%*s", indent + 16, "");
BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len);
return;
}
BIO_printf(out, "v1 (0x0)");
if (log != NULL) {
BIO_printf(out, "\n%*sLog : %s", indent + 4, "",
CTLOG_get0_name(log));
}
BIO_printf(out, "\n%*sLog ID : ", indent + 4, "");
BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len);
BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
timestamp_print(sct->timestamp, out);
BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
if (sct->ext_len == 0)
BIO_printf(out, "none");
else
BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len);
BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
SCT_signature_algorithms_print(sct, out);
BIO_printf(out, "\n%*s ", indent + 4, "");
BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len);
}
LCRYPTO_ALIAS(SCT_print);
void
SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent,
const char *separator, const CTLOG_STORE *log_store)
{
int sct_count = sk_SCT_num(sct_list);
int i;
for (i = 0; i < sct_count; ++i) {
SCT *sct = sk_SCT_value(sct_list, i);
SCT_print(sct, out, indent, log_store);
if (i < sk_SCT_num(sct_list) - 1)
BIO_printf(out, "%s", separator);
}
}
LCRYPTO_ALIAS(SCT_LIST_print);

507
crypto/ct/ct_sct.c Normal file
View File

@@ -0,0 +1,507 @@
/* $OpenBSD: ct_sct.c,v 1.10 2023/07/22 17:02:49 tb Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com), Stephen Henson (steve@openssl.org)
* and Adam Eijdenberg (adam.eijdenberg@gmail.com) for the OpenSSL project 2016.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifdef OPENSSL_NO_CT
# error "CT disabled"
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include "ct_local.h"
SCT *
SCT_new(void)
{
SCT *sct = calloc(1, sizeof(*sct));
if (sct == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET;
sct->version = SCT_VERSION_NOT_SET;
return sct;
}
LCRYPTO_ALIAS(SCT_new);
void
SCT_free(SCT *sct)
{
if (sct == NULL)
return;
free(sct->log_id);
free(sct->ext);
free(sct->sig);
free(sct->sct);
free(sct);
}
LCRYPTO_ALIAS(SCT_free);
void
SCT_LIST_free(STACK_OF(SCT) *scts)
{
sk_SCT_pop_free(scts, SCT_free);
}
LCRYPTO_ALIAS(SCT_LIST_free);
int
SCT_set_version(SCT *sct, sct_version_t version)
{
if (version != SCT_VERSION_V1) {
CTerror(CT_R_UNSUPPORTED_VERSION);
return 0;
}
sct->version = version;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
return 1;
}
LCRYPTO_ALIAS(SCT_set_version);
int
SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type)
{
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
switch (entry_type) {
case CT_LOG_ENTRY_TYPE_X509:
case CT_LOG_ENTRY_TYPE_PRECERT:
sct->entry_type = entry_type;
return 1;
case CT_LOG_ENTRY_TYPE_NOT_SET:
break;
}
CTerror(CT_R_UNSUPPORTED_ENTRY_TYPE);
return 0;
}
LCRYPTO_ALIAS(SCT_set_log_entry_type);
int
SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len)
{
if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) {
CTerror(CT_R_INVALID_LOG_ID_LENGTH);
return 0;
}
free(sct->log_id);
sct->log_id = log_id;
sct->log_id_len = log_id_len;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
return 1;
}
LCRYPTO_ALIAS(SCT_set0_log_id);
int
SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len)
{
if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) {
CTerror(CT_R_INVALID_LOG_ID_LENGTH);
return 0;
}
free(sct->log_id);
sct->log_id = NULL;
sct->log_id_len = 0;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
if (log_id != NULL && log_id_len > 0) {
sct->log_id = malloc(log_id_len);
if (sct->log_id == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sct->log_id, log_id, log_id_len);
sct->log_id_len = log_id_len;
}
return 1;
}
LCRYPTO_ALIAS(SCT_set1_log_id);
void
SCT_set_timestamp(SCT *sct, uint64_t timestamp)
{
sct->timestamp = timestamp;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
}
LCRYPTO_ALIAS(SCT_set_timestamp);
int
SCT_set_signature_nid(SCT *sct, int nid)
{
switch (nid) {
case NID_sha256WithRSAEncryption:
sct->hash_alg = 4; /* XXX */
sct->sig_alg = 1; /* XXX */
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
return 1;
case NID_ecdsa_with_SHA256:
sct->hash_alg = 4; /* XXX */
sct->sig_alg = 3; /* XXX */
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
return 1;
default:
CTerror(CT_R_UNRECOGNIZED_SIGNATURE_NID);
return 0;
}
}
LCRYPTO_ALIAS(SCT_set_signature_nid);
void
SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len)
{
free(sct->ext);
sct->ext = ext;
sct->ext_len = ext_len;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
}
LCRYPTO_ALIAS(SCT_set0_extensions);
int
SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len)
{
free(sct->ext);
sct->ext = NULL;
sct->ext_len = 0;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
if (ext != NULL && ext_len > 0) {
sct->ext = malloc(ext_len);
if (sct->ext == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sct->ext, ext, ext_len);
sct->ext_len = ext_len;
}
return 1;
}
LCRYPTO_ALIAS(SCT_set1_extensions);
void
SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len)
{
free(sct->sig);
sct->sig = sig;
sct->sig_len = sig_len;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
}
LCRYPTO_ALIAS(SCT_set0_signature);
int
SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len)
{
free(sct->sig);
sct->sig = NULL;
sct->sig_len = 0;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
if (sig != NULL && sig_len > 0) {
sct->sig = malloc(sig_len);
if (sct->sig == NULL) {
CTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(sct->sig, sig, sig_len);
sct->sig_len = sig_len;
}
return 1;
}
LCRYPTO_ALIAS(SCT_set1_signature);
sct_version_t
SCT_get_version(const SCT *sct)
{
return sct->version;
}
LCRYPTO_ALIAS(SCT_get_version);
ct_log_entry_type_t
SCT_get_log_entry_type(const SCT *sct)
{
return sct->entry_type;
}
LCRYPTO_ALIAS(SCT_get_log_entry_type);
size_t
SCT_get0_log_id(const SCT *sct, unsigned char **log_id)
{
*log_id = sct->log_id;
return sct->log_id_len;
}
LCRYPTO_ALIAS(SCT_get0_log_id);
uint64_t
SCT_get_timestamp(const SCT *sct)
{
return sct->timestamp;
}
LCRYPTO_ALIAS(SCT_get_timestamp);
int
SCT_get_signature_nid(const SCT *sct)
{
if (sct->version == SCT_VERSION_V1) {
/* XXX sigalg numbers */
if (sct->hash_alg == 4) {
switch (sct->sig_alg) {
case 3:
return NID_ecdsa_with_SHA256;
case 1:
return NID_sha256WithRSAEncryption;
default:
return NID_undef;
}
}
}
return NID_undef;
}
LCRYPTO_ALIAS(SCT_get_signature_nid);
size_t
SCT_get0_extensions(const SCT *sct, unsigned char **ext)
{
*ext = sct->ext;
return sct->ext_len;
}
LCRYPTO_ALIAS(SCT_get0_extensions);
size_t
SCT_get0_signature(const SCT *sct, unsigned char **sig)
{
*sig = sct->sig;
return sct->sig_len;
}
LCRYPTO_ALIAS(SCT_get0_signature);
int
SCT_is_complete(const SCT *sct)
{
switch (sct->version) {
case SCT_VERSION_NOT_SET:
return 0;
case SCT_VERSION_V1:
return sct->log_id != NULL && SCT_signature_is_complete(sct);
default:
return sct->sct != NULL; /* Just need cached encoding */
}
}
int
SCT_signature_is_complete(const SCT *sct)
{
return SCT_get_signature_nid(sct) != NID_undef &&
sct->sig != NULL && sct->sig_len > 0;
}
sct_source_t
SCT_get_source(const SCT *sct)
{
return sct->source;
}
LCRYPTO_ALIAS(SCT_get_source);
int
SCT_set_source(SCT *sct, sct_source_t source)
{
sct->source = source;
sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
switch (source) {
case SCT_SOURCE_TLS_EXTENSION:
case SCT_SOURCE_OCSP_STAPLED_RESPONSE:
return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509);
case SCT_SOURCE_X509V3_EXTENSION:
return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT);
case SCT_SOURCE_UNKNOWN:
break;
}
/* if we aren't sure, leave the log entry type alone */
return 1;
}
LCRYPTO_ALIAS(SCT_set_source);
sct_validation_status_t
SCT_get_validation_status(const SCT *sct)
{
return sct->validation_status;
}
LCRYPTO_ALIAS(SCT_get_validation_status);
int
SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
{
int is_sct_valid = -1;
SCT_CTX *sctx = NULL;
X509_PUBKEY *pub = NULL, *log_pkey = NULL;
const CTLOG *log;
/*
* With an unrecognized SCT version we don't know what such an SCT means,
* let alone validate one. So we return validation failure (0).
*/
if (sct->version != SCT_VERSION_V1) {
sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION;
return 0;
}
log = CTLOG_STORE_get0_log_by_id(ctx->log_store, sct->log_id,
sct->log_id_len);
/* Similarly, an SCT from an unknown log also cannot be validated. */
if (log == NULL) {
sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG;
return 0;
}
sctx = SCT_CTX_new();
if (sctx == NULL)
goto err;
if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1)
goto err;
if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1)
goto err;
if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) {
EVP_PKEY *issuer_pkey;
if (ctx->issuer == NULL) {
sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
goto end;
}
if ((issuer_pkey = X509_get0_pubkey(ctx->issuer)) == NULL)
goto err;
if (X509_PUBKEY_set(&pub, issuer_pkey) != 1)
goto err;
if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1)
goto err;
}
SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms);
/*
* XXX: Potential for optimization. This repeats some idempotent heavy
* lifting on the certificate for each candidate SCT, and appears to not
* use any information in the SCT itself, only the certificate is
* processed. So it may make more sense to to do this just once, perhaps
* associated with the shared (by all SCTs) policy eval ctx.
*
* XXX: Failure here is global (SCT independent) and represents either an
* issue with the certificate (e.g. duplicate extensions) or an out of
* memory condition. When the certificate is incompatible with CT, we just
* mark the SCTs invalid, rather than report a failure to determine the
* validation status. That way, callbacks that want to do "soft" SCT
* processing will not abort handshakes with false positive internal
* errors. Since the function does not distinguish between certificate
* issues (peer's fault) and internal problems (out fault) the safe thing
* to do is to report a validation failure and let the callback or
* application decide what to do.
*/
if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1)
sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
else
sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ?
SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID;
end:
is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID;
err:
X509_PUBKEY_free(pub);
X509_PUBKEY_free(log_pkey);
SCT_CTX_free(sctx);
return is_sct_valid;
}
LCRYPTO_ALIAS(SCT_validate);
int
SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx)
{
int are_scts_valid = 1;
int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
int i;
for (i = 0; i < sct_count; ++i) {
int is_sct_valid = -1;
SCT *sct = sk_SCT_value(scts, i);
if (sct == NULL)
continue;
is_sct_valid = SCT_validate(sct, ctx);
if (is_sct_valid < 0)
return is_sct_valid;
are_scts_valid &= is_sct_valid;
}
return are_scts_valid;
}
LCRYPTO_ALIAS(SCT_LIST_validate);

323
crypto/ct/ct_sct_ctx.c Normal file
View File

@@ -0,0 +1,323 @@
/* $OpenBSD: ct_sct_ctx.c,v 1.6 2022/06/30 11:14:47 tb Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifdef OPENSSL_NO_CT
# error "CT is disabled"
#endif
#include <stddef.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include "ct_local.h"
SCT_CTX *
SCT_CTX_new(void)
{
SCT_CTX *sctx = calloc(1, sizeof(*sctx));
if (sctx == NULL)
CTerror(ERR_R_MALLOC_FAILURE);
return sctx;
}
void
SCT_CTX_free(SCT_CTX *sctx)
{
if (sctx == NULL)
return;
EVP_PKEY_free(sctx->pkey);
free(sctx->pkeyhash);
free(sctx->ihash);
free(sctx->certder);
free(sctx->preder);
free(sctx);
}
/*
* Finds the index of the first extension with the given NID in cert.
* If there is more than one extension with that NID, *is_duplicated is set to
* 1, otherwise 0 (unless it is NULL).
*/
static int
ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated)
{
int ret = X509_get_ext_by_NID(cert, nid, -1);
if (is_duplicated != NULL)
*is_duplicated = ret >= 0 &&
X509_get_ext_by_NID(cert, nid, ret) >= 0;
return ret;
}
/*
* Modifies a certificate by deleting extensions and copying the issuer and
* AKID from the presigner certificate, if necessary.
* Returns 1 on success, 0 otherwise.
*/
static int
ct_x509_cert_fixup(X509 *cert, X509 *presigner)
{
int preidx, certidx;
int pre_akid_ext_is_dup, cert_akid_ext_is_dup;
if (presigner == NULL)
return 1;
preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier,
&pre_akid_ext_is_dup);
certidx = ct_x509_get_ext(cert, NID_authority_key_identifier,
&cert_akid_ext_is_dup);
/* An error occurred whilst searching for the extension */
if (preidx < -1 || certidx < -1)
return 0;
/* Invalid certificate if they contain duplicate extensions */
if (pre_akid_ext_is_dup || cert_akid_ext_is_dup)
return 0;
/* AKID must be present in both certificate or absent in both */
if (preidx >= 0 && certidx == -1)
return 0;
if (preidx == -1 && certidx >= 0)
return 0;
/* Copy issuer name */
if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner)))
return 0;
if (preidx != -1) {
/* Retrieve and copy AKID encoding */
X509_EXTENSION *preext = X509_get_ext(presigner, preidx);
X509_EXTENSION *certext = X509_get_ext(cert, certidx);
ASN1_OCTET_STRING *preextdata;
/* Should never happen */
if (preext == NULL || certext == NULL)
return 0;
preextdata = X509_EXTENSION_get_data(preext);
if (preextdata == NULL ||
!X509_EXTENSION_set_data(certext, preextdata))
return 0;
}
return 1;
}
int
SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
{
unsigned char *certder = NULL, *preder = NULL;
X509 *pretmp = NULL;
int certderlen = 0, prederlen = 0;
int idx = -1;
int poison_ext_is_dup, sct_ext_is_dup;
int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup);
/* Duplicate poison extensions are present - error */
if (poison_ext_is_dup)
goto err;
/* If *cert doesn't have a poison extension, it isn't a precert */
if (poison_idx == -1) {
/* cert isn't a precert, so we shouldn't have a presigner */
if (presigner != NULL)
goto err;
certderlen = i2d_X509(cert, &certder);
if (certderlen < 0)
goto err;
}
/* See if cert has a precert SCTs extension */
idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup);
/* Duplicate SCT extensions are present - error */
if (sct_ext_is_dup)
goto err;
if (idx >= 0 && poison_idx >= 0) {
/*
* cert can't both contain SCTs (i.e. have an SCT extension) and be a
* precert (i.e. have a poison extension).
*/
goto err;
}
if (idx == -1) {
idx = poison_idx;
}
/*
* If either a poison or SCT extension is present, remove it before encoding
* cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see
* RFC5280) from cert, which is what the CT log signed when it produced the
* SCT.
*/
if (idx >= 0) {
X509_EXTENSION *ext;
/* Take a copy of certificate so we don't modify passed version */
pretmp = X509_dup(cert);
if (pretmp == NULL)
goto err;
ext = X509_delete_ext(pretmp, idx);
X509_EXTENSION_free(ext);
if (!ct_x509_cert_fixup(pretmp, presigner))
goto err;
prederlen = i2d_re_X509_tbs(pretmp, &preder);
if (prederlen <= 0)
goto err;
}
X509_free(pretmp);
free(sctx->certder);
sctx->certder = certder;
sctx->certderlen = certderlen;
free(sctx->preder);
sctx->preder = preder;
sctx->prederlen = prederlen;
return 1;
err:
free(certder);
free(preder);
X509_free(pretmp);
return 0;
}
static int
ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, size_t *hash_len)
{
int ret = 0;
unsigned char *md = NULL, *der = NULL;
int der_len;
unsigned int md_len;
/* Reuse buffer if possible */
if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
md = *hash;
} else {
md = malloc(SHA256_DIGEST_LENGTH);
if (md == NULL)
goto err;
}
/* Calculate key hash */
der_len = i2d_X509_PUBKEY(pkey, &der);
if (der_len <= 0)
goto err;
if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
goto err;
if (md != *hash) {
free(*hash);
*hash = md;
*hash_len = SHA256_DIGEST_LENGTH;
}
md = NULL;
ret = 1;
err:
free(md);
free(der);
return ret;
}
int
SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
{
return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer));
}
int
SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
{
return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
}
int
SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
{
EVP_PKEY *pkey = X509_PUBKEY_get(pubkey);
if (pkey == NULL)
return 0;
if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
EVP_PKEY_free(pkey);
return 0;
}
EVP_PKEY_free(sctx->pkey);
sctx->pkey = pkey;
return 1;
}
void
SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms)
{
sctx->epoch_time_in_ms = time_in_ms;
}

195
crypto/ct/ct_vfy.c Normal file
View File

@@ -0,0 +1,195 @@
/* $OpenBSD: ct_vfy.c,v 1.6 2022/01/06 14:34:40 jsing Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <string.h>
#include <openssl/ct.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "ct_local.h"
typedef enum sct_signature_type_t {
SIGNATURE_TYPE_NOT_SET = -1,
SIGNATURE_TYPE_CERT_TIMESTAMP,
SIGNATURE_TYPE_TREE_HASH
} SCT_SIGNATURE_TYPE;
/*
* Update encoding for SCT signature verification/generation to supplied
* EVP_MD_CTX.
*/
static int
sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct)
{
CBB cbb, entry, extensions;
uint8_t *data = NULL;
size_t data_len;
int ret = 0;
memset(&cbb, 0, sizeof(cbb));
if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET)
goto err;
if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)
goto err;
if (!CBB_init(&cbb, 0))
goto err;
/*
* Build the digitally-signed struct per RFC 6962 section 3.2.
*/
if (!CBB_add_u8(&cbb, sct->version))
goto err;
if (!CBB_add_u8(&cbb, SIGNATURE_TYPE_CERT_TIMESTAMP))
goto err;
if (!CBB_add_u64(&cbb, sct->timestamp))
goto err;
if (!CBB_add_u16(&cbb, sct->entry_type))
goto err;
if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) {
if (!CBB_add_bytes(&cbb, sctx->ihash, sctx->ihashlen))
goto err;
}
if (!CBB_add_u24_length_prefixed(&cbb, &entry))
goto err;
if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) {
if (sctx->preder == NULL)
goto err;
if (!CBB_add_bytes(&entry, sctx->preder, sctx->prederlen))
goto err;
} else {
if (sctx->certder == NULL)
goto err;
if (!CBB_add_bytes(&entry, sctx->certder, sctx->certderlen))
goto err;
}
if (!CBB_add_u16_length_prefixed(&cbb, &extensions))
goto err;
if (sct->ext_len > 0) {
if (!CBB_add_bytes(&extensions, sct->ext, sct->ext_len))
goto err;
}
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (!EVP_DigestUpdate(ctx, data, data_len))
goto err;
ret = 1;
err:
CBB_cleanup(&cbb);
free(data);
return ret;
}
int
SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
{
EVP_MD_CTX *ctx = NULL;
int ret = 0;
if (!SCT_is_complete(sct) || sctx->pkey == NULL ||
sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET ||
(sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT &&
sctx->ihash == NULL)) {
CTerror(CT_R_SCT_NOT_SET);
return 0;
}
if (sct->version != SCT_VERSION_V1) {
CTerror(CT_R_SCT_UNSUPPORTED_VERSION);
return 0;
}
if (sct->log_id_len != sctx->pkeyhashlen ||
memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) {
CTerror(CT_R_SCT_LOG_ID_MISMATCH);
return 0;
}
if (sct->timestamp > sctx->epoch_time_in_ms) {
CTerror(CT_R_SCT_FUTURE_TIMESTAMP);
return 0;
}
if ((ctx = EVP_MD_CTX_new()) == NULL)
goto end;
if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey))
goto end;
if (!sct_ctx_update(ctx, sctx, sct))
goto end;
/* Verify signature */
/* If ret < 0 some other error: fall through without setting error */
if ((ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len)) == 0)
CTerror(CT_R_SCT_INVALID_SIGNATURE);
end:
EVP_MD_CTX_free(ctx);
return ret;
}

186
crypto/ct/ct_x509v3.c Normal file
View File

@@ -0,0 +1,186 @@
/* $OpenBSD: ct_x509v3.c,v 1.6 2021/12/25 15:42:32 tb Exp $ */
/*
* Written by Rob Stradling (rob@comodo.com) and Stephen Henson
* (steve@openssl.org) for the OpenSSL project 2014.
*/
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifdef OPENSSL_NO_CT
# error "CT is disabled"
#endif
#include <string.h>
#include "ct_local.h"
static char *
i2s_poison(const X509V3_EXT_METHOD *method, void *val)
{
return strdup("NULL");
}
static void *
s2i_poison(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str)
{
return ASN1_NULL_new();
}
static int
i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list, BIO *out,
int indent)
{
SCT_LIST_print(sct_list, out, indent, "\n", NULL);
return 1;
}
static int
set_sct_list_source(STACK_OF(SCT) *s, sct_source_t source)
{
if (s != NULL) {
int i;
for (i = 0; i < sk_SCT_num(s); i++) {
int res = SCT_set_source(sk_SCT_value(s, i), source);
if (res != 1) {
return 0;
}
}
}
return 1;
}
static STACK_OF(SCT) *
x509_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
{
STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len);
if (set_sct_list_source(s, SCT_SOURCE_X509V3_EXTENSION) != 1) {
SCT_LIST_free(s);
*a = NULL;
return NULL;
}
return s;
}
static STACK_OF(SCT) *
ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
{
STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len);
if (set_sct_list_source(s, SCT_SOURCE_OCSP_STAPLED_RESPONSE) != 1) {
SCT_LIST_free(s);
*a = NULL;
return NULL;
}
return s;
}
/* Handlers for X509v3/OCSP Certificate Transparency extensions */
const X509V3_EXT_METHOD v3_ct_scts[3] = {
/* X509v3 extension in certificates that contains SCTs */
[0] = {
.ext_nid = NID_ct_precert_scts,
.ext_flags = 0,
.it = NULL,
.ext_new = NULL,
.ext_free = (X509V3_EXT_FREE)SCT_LIST_free,
.d2i = (X509V3_EXT_D2I)x509_ext_d2i_SCT_LIST,
.i2d = (X509V3_EXT_I2D)i2d_SCT_LIST,
.i2s = NULL,
.s2i = NULL,
.i2v = NULL,
.v2i = NULL,
.i2r = (X509V3_EXT_I2R)i2r_SCT_LIST,
.r2i = NULL,
.usr_data = NULL,
},
/* X509v3 extension to mark a certificate as a pre-certificate */
[1] = {
.ext_nid = NID_ct_precert_poison,
.ext_flags = 0,
.it = &ASN1_NULL_it,
.ext_new = NULL,
.ext_free = NULL,
.d2i = NULL,
.i2d = NULL,
.i2s = i2s_poison,
.s2i = s2i_poison,
.i2v = NULL,
.v2i = NULL,
.i2r = NULL,
.r2i = NULL,
.usr_data = NULL,
},
/* OCSP extension that contains SCTs */
[2] = {
.ext_nid = NID_ct_cert_scts,
.ext_flags = 0,
.it = NULL,
.ext_new = NULL,
.ext_free = (X509V3_EXT_FREE)SCT_LIST_free,
.d2i = (X509V3_EXT_D2I)ocsp_ext_d2i_SCT_LIST,
.i2d = (X509V3_EXT_I2D)i2d_SCT_LIST,
.i2s = NULL,
.s2i = NULL,
.i2v = NULL,
.v2i = NULL,
.i2r = (X509V3_EXT_I2R)i2r_SCT_LIST,
.r2i = NULL,
.usr_data = NULL,
},
};