check in v3.8.2 source
This commit is contained in:
226
crypto/ct/ct_b64.c
Normal file
226
crypto/ct/ct_b64.c
Normal 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
147
crypto/ct/ct_err.c
Normal 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
260
crypto/ct/ct_local.h
Normal 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
375
crypto/ct/ct_log.c
Normal 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
464
crypto/ct/ct_oct.c
Normal 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, ×tamp))
|
||||
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
163
crypto/ct/ct_policy.c
Normal 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
211
crypto/ct/ct_prn.c
Normal 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
507
crypto/ct/ct_sct.c
Normal 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
323
crypto/ct/ct_sct_ctx.c
Normal 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
195
crypto/ct/ct_vfy.c
Normal 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
186
crypto/ct/ct_x509v3.c
Normal 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,
|
||||
},
|
||||
};
|
Reference in New Issue
Block a user