CT policy validation
Specifies a callback that will, in the future, be used by the SSL code to decide whether to abort a connection on Certificate Transparency grounds. Reviewed-by: Ben Laurie <ben@openssl.org> Reviewed-by: Rich Salz <rsalz@openssl.org>master
parent
7852414967
commit
7d054e5ab2
|
@ -15,10 +15,10 @@ CFLAGS= $(INCLUDES) $(CFLAG) $(SHARED_CFLAG)
|
|||
GENERAL=Makefile
|
||||
|
||||
LIB=$(TOP)/libcrypto.a
|
||||
LIBSRC= ct_b64.c ct_err.c ct_log.c ct_oct.c ct_prn.c ct_sct.c ct_sct_ctx.c \
|
||||
ct_vfy.c ct_x509v3.c
|
||||
LIBOBJ= ct_b64.o ct_err.o ct_log.o ct_oct.o ct_prn.o ct_sct.o ct_sct_ctx.o \
|
||||
ct_vfy.o ct_x509v3.o
|
||||
LIBSRC= ct_b64.c ct_err.c ct_log.c ct_oct.c ct_policy.c ct_prn.c ct_sct.c \
|
||||
ct_sct_ctx.c ct_vfy.c ct_x509v3.c
|
||||
LIBOBJ= ct_b64.o ct_err.o ct_log.o ct_oct.o ct_policy.o ct_prn.o ct_sct.o \
|
||||
ct_sct_ctx.o ct_vfy.o ct_x509v3.o
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]= ct_b64.c ct_err.c ct_log.c ct_oct.c ct_prn.c ct_sct.c \
|
||||
ct_sct_ctx.c ct_vfy.c ct_x509v3.c
|
||||
SOURCE[../../libcrypto]= ct_b64.c ct_err.c ct_log.c ct_oct.c ct_policy.c \
|
||||
ct_prn.c ct_sct.c ct_sct_ctx.c ct_vfy.c ct_x509v3.c
|
||||
|
|
|
@ -77,7 +77,23 @@ static ERR_STRING_DATA CT_str_functs[] = {
|
|||
{ERR_FUNC(CT_F_CTLOG_STORE_LOAD_CTX_NEW), "CTLOG_STORE_LOAD_CTX_new"},
|
||||
{ERR_FUNC(CT_F_CTLOG_STORE_LOAD_FILE), "CTLOG_STORE_load_file"},
|
||||
{ERR_FUNC(CT_F_CT_BASE64_DECODE), "CT_base64_decode"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_GET0_CERT),
|
||||
"CT_POLICY_EVAL_CTX_get0_cert"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_GET0_ISSUER),
|
||||
"CT_POLICY_EVAL_CTX_get0_issuer"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_GET0_LOG_STORE),
|
||||
"CT_POLICY_EVAL_CTX_get0_log_store"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_NEW), "CT_POLICY_EVAL_CTX_new"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_SET0_CERT),
|
||||
"CT_POLICY_EVAL_CTX_set0_cert"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_SET0_ISSUER),
|
||||
"CT_POLICY_EVAL_CTX_set0_issuer"},
|
||||
{ERR_FUNC(CT_F_CT_POLICY_EVAL_CTX_SET0_LOG_STORE),
|
||||
"CT_POLICY_EVAL_CTX_set0_log_store"},
|
||||
{ERR_FUNC(CT_F_CT_V1_LOG_ID_FROM_PKEY), "CT_v1_log_id_from_pkey"},
|
||||
{ERR_FUNC(CT_F_CT_VERIFY_AT_LEAST_ONE_GOOD_SCT),
|
||||
"CT_verify_at_least_one_good_sct"},
|
||||
{ERR_FUNC(CT_F_CT_VERIFY_NO_BAD_SCTS), "CT_verify_no_bad_scts"},
|
||||
{ERR_FUNC(CT_F_D2I_SCT_LIST), "d2i_SCT_LIST"},
|
||||
{ERR_FUNC(CT_F_I2D_SCT_LIST), "i2d_SCT_LIST"},
|
||||
{ERR_FUNC(CT_F_I2O_SCT), "i2o_SCT"},
|
||||
|
@ -87,6 +103,7 @@ static ERR_STRING_DATA CT_str_functs[] = {
|
|||
{ERR_FUNC(CT_F_O2I_SCT_LIST), "o2i_SCT_LIST"},
|
||||
{ERR_FUNC(CT_F_O2I_SCT_SIGNATURE), "o2i_SCT_signature"},
|
||||
{ERR_FUNC(CT_F_SCT_CTX_NEW), "SCT_CTX_new"},
|
||||
{ERR_FUNC(CT_F_SCT_LIST_VALIDATE), "SCT_LIST_validate"},
|
||||
{ERR_FUNC(CT_F_SCT_NEW), "SCT_new"},
|
||||
{ERR_FUNC(CT_F_SCT_NEW_FROM_BASE64), "SCT_new_from_base64"},
|
||||
{ERR_FUNC(CT_F_SCT_SET0_LOG_ID), "SCT_set0_log_id"},
|
||||
|
@ -97,6 +114,7 @@ static ERR_STRING_DATA CT_str_functs[] = {
|
|||
{ERR_FUNC(CT_F_SCT_SET_SIGNATURE_NID), "SCT_set_signature_nid"},
|
||||
{ERR_FUNC(CT_F_SCT_SET_VERSION), "SCT_set_version"},
|
||||
{ERR_FUNC(CT_F_SCT_SIGNATURE_IS_VALID), "SCT_signature_is_valid"},
|
||||
{ERR_FUNC(CT_F_SCT_VALIDATE), "SCT_validate"},
|
||||
{ERR_FUNC(CT_F_SCT_VERIFY), "SCT_verify"},
|
||||
{ERR_FUNC(CT_F_SCT_VERIFY_V1), "SCT_verify_v1"},
|
||||
{0, NULL}
|
||||
|
@ -111,12 +129,15 @@ static ERR_STRING_DATA CT_str_reasons[] = {
|
|||
"log conf missing description"},
|
||||
{ERR_REASON(CT_R_LOG_CONF_MISSING_KEY), "log conf missing key"},
|
||||
{ERR_REASON(CT_R_LOG_KEY_INVALID), "log key invalid"},
|
||||
{ERR_REASON(CT_R_NOT_ENOUGH_SCTS), "not enough scts"},
|
||||
{ERR_REASON(CT_R_SCT_INVALID), "sct invalid"},
|
||||
{ERR_REASON(CT_R_SCT_INVALID_SIGNATURE), "sct invalid signature"},
|
||||
{ERR_REASON(CT_R_SCT_LIST_INVALID), "sct list invalid"},
|
||||
{ERR_REASON(CT_R_SCT_LOG_ID_MISMATCH), "sct log id mismatch"},
|
||||
{ERR_REASON(CT_R_SCT_NOT_SET), "sct not set"},
|
||||
{ERR_REASON(CT_R_SCT_UNSUPPORTED_VERSION), "sct unsupported version"},
|
||||
{ERR_REASON(CT_R_SCT_VALIDATION_STATUS_NOT_SET),
|
||||
"sct validation status not set"},
|
||||
{ERR_REASON(CT_R_UNRECOGNIZED_SIGNATURE_NID),
|
||||
"unrecognized signature nid"},
|
||||
{ERR_REASON(CT_R_UNSUPPORTED_ENTRY_TYPE), "unsupported entry type"},
|
||||
|
|
|
@ -127,6 +127,8 @@ struct sct_st {
|
|||
sct_source_t source;
|
||||
/* The CT log that produced this SCT. */
|
||||
CTLOG *log;
|
||||
/* 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 */
|
||||
|
@ -147,6 +149,15 @@ struct sct_ctx_st {
|
|||
size_t prederlen;
|
||||
};
|
||||
|
||||
/* Context when evaluating whether a Certificate Transparency policy is met */
|
||||
struct ct_policy_eval_ctx_st {
|
||||
X509 *cert;
|
||||
X509 *issuer;
|
||||
CTLOG_STORE *log_store;
|
||||
STACK_OF(SCT) *good_scts;
|
||||
STACK_OF(SCT) *bad_scts;
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a new context for verifying an SCT.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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 "ct_locl.h"
|
||||
|
||||
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
|
||||
{
|
||||
CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX));
|
||||
|
||||
if (ctx == NULL) {
|
||||
CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx)
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
void CT_POLICY_EVAL_CTX_set0_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert)
|
||||
{
|
||||
ctx->cert = cert;
|
||||
}
|
||||
|
||||
void CT_POLICY_EVAL_CTX_set0_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer)
|
||||
{
|
||||
ctx->issuer = issuer;
|
||||
}
|
||||
|
||||
void CT_POLICY_EVAL_CTX_set0_log_store(CT_POLICY_EVAL_CTX *ctx,
|
||||
CTLOG_STORE *log_store)
|
||||
{
|
||||
ctx->log_store = log_store;
|
||||
}
|
||||
|
||||
X509* CT_POLICY_EVAL_CTX_get0_cert(CT_POLICY_EVAL_CTX *ctx)
|
||||
{
|
||||
return ctx->cert;
|
||||
}
|
||||
|
||||
X509* CT_POLICY_EVAL_CTX_get0_issuer(CT_POLICY_EVAL_CTX *ctx)
|
||||
{
|
||||
return ctx->issuer;
|
||||
}
|
||||
|
||||
CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(CT_POLICY_EVAL_CTX *ctx)
|
||||
{
|
||||
return ctx->log_store;
|
||||
}
|
||||
|
|
@ -356,3 +356,94 @@ int SCT_LIST_set0_logs(STACK_OF(SCT) *sct_list, const CTLOG_STORE *ct_logs)
|
|||
|
||||
return sct_logs_found;
|
||||
}
|
||||
|
||||
sct_validation_status_t SCT_get_validation_status(const SCT *sct)
|
||||
{
|
||||
return sct->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;
|
||||
|
||||
switch (sct->version) {
|
||||
case SCT_VERSION_V1:
|
||||
if (sct->log == NULL)
|
||||
sct->log = CTLOG_STORE_get0_log_by_id(ctx->log_store,
|
||||
sct->log_id,
|
||||
CT_V1_HASHLEN);
|
||||
break;
|
||||
default:
|
||||
sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sct->log == NULL) {
|
||||
sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG;
|
||||
goto end;
|
||||
}
|
||||
|
||||
sctx = SCT_CTX_new();
|
||||
if (sctx == NULL)
|
||||
goto err;
|
||||
|
||||
if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(sct->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;
|
||||
}
|
||||
|
||||
issuer_pkey = X509_get_pubkey(ctx->issuer);
|
||||
|
||||
if (X509_PUBKEY_set(&pub, issuer_pkey) != 1)
|
||||
goto err;
|
||||
if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1)
|
||||
goto err;
|
||||
|
||||
sct->validation_status = SCT_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,65 @@ typedef enum sct_signature_type_t {
|
|||
SIGNATURE_TYPE_TREE_HASH
|
||||
} SCT_SIGNATURE_TYPE;
|
||||
|
||||
int CT_verify_no_bad_scts(const CT_POLICY_EVAL_CTX *ctx,
|
||||
const STACK_OF(SCT) *scts, void *arg)
|
||||
{
|
||||
int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sct_count; ++i) {
|
||||
SCT *sct = sk_SCT_value(scts, i);
|
||||
|
||||
switch (SCT_get_validation_status(sct)) {
|
||||
case SCT_VALIDATION_STATUS_INVALID:
|
||||
return 0;
|
||||
case SCT_VALIDATION_STATUS_NOT_SET:
|
||||
CTerr(CT_F_CT_VERIFY_NO_BAD_SCTS,
|
||||
CT_R_SCT_VALIDATION_STATUS_NOT_SET);
|
||||
return -1;
|
||||
default:
|
||||
/* Ignore other validation statuses. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CT_verify_at_least_one_good_sct(const CT_POLICY_EVAL_CTX *ctx,
|
||||
const STACK_OF(SCT) *scts, void *arg)
|
||||
{
|
||||
int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
|
||||
int valid_scts = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sct_count; ++i) {
|
||||
SCT *sct = sk_SCT_value(scts, i);
|
||||
|
||||
switch (SCT_get_validation_status(sct)) {
|
||||
case SCT_VALIDATION_STATUS_VALID:
|
||||
++valid_scts;
|
||||
break;
|
||||
case SCT_VALIDATION_STATUS_INVALID:
|
||||
return 0;
|
||||
case SCT_VALIDATION_STATUS_NOT_SET:
|
||||
CTerr(CT_F_CT_VERIFY_AT_LEAST_ONE_GOOD_SCT,
|
||||
CT_R_SCT_VALIDATION_STATUS_NOT_SET);
|
||||
return -1;
|
||||
default:
|
||||
/* Ignore other validation statuses. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_scts == 0) {
|
||||
CTerr(CT_F_CT_VERIFY_AT_LEAST_ONE_GOOD_SCT, CT_R_NOT_ENOUGH_SCTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update encoding for SCT signature verification/generation to supplied
|
||||
* EVP_MD_CTX.
|
||||
|
|
|
@ -90,9 +90,62 @@ typedef enum {
|
|||
SCT_SOURCE_OCSP_STAPLED_RESPONSE
|
||||
} sct_source_t;
|
||||
|
||||
typedef enum {
|
||||
SCT_VALIDATION_STATUS_NOT_SET,
|
||||
SCT_VALIDATION_STATUS_UNKNOWN_LOG,
|
||||
SCT_VALIDATION_STATUS_VALID,
|
||||
SCT_VALIDATION_STATUS_INVALID,
|
||||
SCT_VALIDATION_STATUS_UNVERIFIED,
|
||||
SCT_VALIDATION_STATUS_UNKNOWN_VERSION
|
||||
} sct_validation_status_t;
|
||||
|
||||
DEFINE_STACK_OF(SCT)
|
||||
DEFINE_STACK_OF(CTLOG)
|
||||
|
||||
/******************************************
|
||||
* CT policy evaluation context functions *
|
||||
******************************************/
|
||||
|
||||
/* Creates a new, empty policy evaluation context */
|
||||
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void);
|
||||
|
||||
/* Deletes a policy evaluation context */
|
||||
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
/* Gets the peer certificate that the SCTs are for */
|
||||
X509* CT_POLICY_EVAL_CTX_get0_cert(CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
/* Sets the certificate associated with the received SCTs */
|
||||
void CT_POLICY_EVAL_CTX_set0_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert);
|
||||
|
||||
/* Gets the issuer of the aforementioned certificate */
|
||||
X509* CT_POLICY_EVAL_CTX_get0_issuer(CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
/* Sets the issuer of the certificate associated with the received SCTs */
|
||||
void CT_POLICY_EVAL_CTX_set0_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer);
|
||||
|
||||
/* Gets the CT logs that are trusted sources of SCTs */
|
||||
CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
/* Sets the log store that is in use */
|
||||
void CT_POLICY_EVAL_CTX_set0_log_store(CT_POLICY_EVAL_CTX *ctx,
|
||||
CTLOG_STORE *log_store);
|
||||
|
||||
/*
|
||||
* A callback for verifying that the received SCTs are sufficient.
|
||||
* Expected to return 1 if they are sufficient, otherwise 0.
|
||||
* May return a negative integer if an error occurs.
|
||||
* A connection should be aborted if the SCTs are deemed insufficient.
|
||||
*/
|
||||
typedef int(*ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
|
||||
const STACK_OF(SCT) *scts, void *arg);
|
||||
/* Returns 0 if there are invalid SCTs */
|
||||
int CT_verify_no_bad_scts(const CT_POLICY_EVAL_CTX *ctx,
|
||||
const STACK_OF(SCT) *scts, void *arg);
|
||||
/* Returns 0 if there are invalid SCTS or fewer than one valid SCT */
|
||||
int CT_verify_at_least_one_good_sct(const CT_POLICY_EVAL_CTX *ctx,
|
||||
const STACK_OF(SCT) *scts, void *arg);
|
||||
|
||||
/*****************
|
||||
* SCT functions *
|
||||
*****************/
|
||||
|
@ -304,6 +357,31 @@ int SCT_verify(const SCT_CTX *sctx, const SCT *sct);
|
|||
int SCT_verify_v1(SCT *sct, X509 *cert, X509 *preissuer,
|
||||
X509_PUBKEY *log_pubkey, X509 *issuer_cert);
|
||||
|
||||
/*
|
||||
* Gets the last result of validating this SCT.
|
||||
* If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET.
|
||||
*/
|
||||
sct_validation_status_t SCT_get_validation_status(const SCT *sct);
|
||||
|
||||
/*
|
||||
* Validates the given SCT with the provided context.
|
||||
* Sets the "validation_status" field of the SCT.
|
||||
* Returns 1 if the SCT is valid and the signature verifies.
|
||||
* Returns 0 if the SCT is invalid or could not be verified.
|
||||
* Returns -1 if an error occurs.
|
||||
*/
|
||||
int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
/*
|
||||
* Validates the given list of SCTs with the provided context.
|
||||
* Populates the "good_scts" and "bad_scts" of the evaluation context.
|
||||
* Returns 1 if there are no invalid SCTs and all signatures verify.
|
||||
* Returns 0 if at least one SCT is invalid or could not be verified.
|
||||
* Returns a negative integer if an error occurs.
|
||||
*/
|
||||
int SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx);
|
||||
|
||||
|
||||
/*********************************
|
||||
* SCT parsing and serialisation *
|
||||
*********************************/
|
||||
|
@ -494,7 +572,16 @@ void ERR_load_CT_strings(void);
|
|||
# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122
|
||||
# define CT_F_CTLOG_STORE_LOAD_FILE 123
|
||||
# define CT_F_CT_BASE64_DECODE 124
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_GET0_CERT 130
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_GET0_ISSUER 131
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_GET0_LOG_STORE 132
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_NEW 133
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_SET0_CERT 134
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_SET0_ISSUER 135
|
||||
# define CT_F_CT_POLICY_EVAL_CTX_SET0_LOG_STORE 136
|
||||
# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125
|
||||
# define CT_F_CT_VERIFY_AT_LEAST_ONE_GOOD_SCT 137
|
||||
# define CT_F_CT_VERIFY_NO_BAD_SCTS 138
|
||||
# define CT_F_D2I_SCT_LIST 105
|
||||
# define CT_F_I2D_SCT_LIST 106
|
||||
# define CT_F_I2O_SCT 107
|
||||
|
@ -504,6 +591,7 @@ void ERR_load_CT_strings(void);
|
|||
# define CT_F_O2I_SCT_LIST 111
|
||||
# define CT_F_O2I_SCT_SIGNATURE 112
|
||||
# define CT_F_SCT_CTX_NEW 126
|
||||
# define CT_F_SCT_LIST_VALIDATE 139
|
||||
# define CT_F_SCT_NEW 100
|
||||
# define CT_F_SCT_NEW_FROM_BASE64 127
|
||||
# define CT_F_SCT_SET0_LOG_ID 101
|
||||
|
@ -514,6 +602,7 @@ void ERR_load_CT_strings(void);
|
|||
# define CT_F_SCT_SET_SIGNATURE_NID 103
|
||||
# define CT_F_SCT_SET_VERSION 104
|
||||
# define CT_F_SCT_SIGNATURE_IS_VALID 113
|
||||
# define CT_F_SCT_VALIDATE 140
|
||||
# define CT_F_SCT_VERIFY 128
|
||||
# define CT_F_SCT_VERIFY_V1 129
|
||||
|
||||
|
@ -525,12 +614,14 @@ void ERR_load_CT_strings(void);
|
|||
# define CT_R_LOG_CONF_MISSING_DESCRIPTION 111
|
||||
# define CT_R_LOG_CONF_MISSING_KEY 112
|
||||
# define CT_R_LOG_KEY_INVALID 113
|
||||
# define CT_R_NOT_ENOUGH_SCTS 116
|
||||
# define CT_R_SCT_INVALID 104
|
||||
# define CT_R_SCT_INVALID_SIGNATURE 107
|
||||
# define CT_R_SCT_LIST_INVALID 105
|
||||
# define CT_R_SCT_LOG_ID_MISMATCH 114
|
||||
# define CT_R_SCT_NOT_SET 106
|
||||
# define CT_R_SCT_UNSUPPORTED_VERSION 115
|
||||
# define CT_R_SCT_VALIDATION_STATUS_NOT_SET 117
|
||||
# define CT_R_UNRECOGNIZED_SIGNATURE_NID 101
|
||||
# define CT_R_UNSUPPORTED_ENTRY_TYPE 102
|
||||
# define CT_R_UNSUPPORTED_VERSION 103
|
||||
|
|
|
@ -204,6 +204,7 @@ typedef struct sct_st SCT;
|
|||
typedef struct sct_ctx_st SCT_CTX;
|
||||
typedef struct ctlog_st CTLOG;
|
||||
typedef struct ctlog_store_st CTLOG_STORE;
|
||||
typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX;
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
|
||||
defined(INTMAX_MAX) && defined(UINTMAX_MAX)
|
||||
|
|
|
@ -373,7 +373,7 @@ $(ASYNCTEST)$(EXE_EXT): $(ASYNCTEST).o
|
|||
$(DTLSV1LISTENTEST)$(EXE_EXT): $(DTLSV1LISTENTEST).o
|
||||
@target=$(DTLSV1LISTENTEST) $(BUILD_CMD)
|
||||
|
||||
$(CTTEST)$(EXE_EXT): $(CTTEST).o testutil.o
|
||||
$(CTTEST)$(EXE_EXT): $(CTTEST).o $(DLIBCRYPTO) testutil.o
|
||||
@target=$(CTTEST) testutil=testutil.o; $(BUILD_CMD)
|
||||
|
||||
$(THREADSTEST)$(EXE_EXT): $(THREADSTEST).o $(DLIBCRYPTO)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
|
||||
MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
|
||||
YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
|
||||
MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
|
||||
c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
|
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
|
||||
jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
|
||||
KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
|
||||
svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
|
||||
tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
|
||||
A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
|
||||
MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
|
||||
OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
|
||||
f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
|
||||
OwqULg==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,35 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB
|
||||
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
||||
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy
|
||||
MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
||||
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
||||
Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg
|
||||
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf
|
||||
CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj
|
||||
vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA
|
||||
xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6
|
||||
WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg
|
||||
iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j
|
||||
BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI
|
||||
ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G
|
||||
A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j
|
||||
b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k
|
||||
b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr
|
||||
BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t
|
||||
L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
|
||||
cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R
|
||||
AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk
|
||||
jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk
|
||||
1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i
|
||||
teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o
|
||||
fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA
|
||||
KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e
|
||||
ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9
|
||||
XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA
|
||||
tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2
|
||||
jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn
|
||||
pLwltum95OmYdBbxN4SBB7SC
|
||||
-----END CERTIFICATE-----
|
169
test/ct_test.c
169
test/ct_test.c
|
@ -1,8 +1,7 @@
|
|||
/*
|
||||
* Tests the Certificate Transparency public and internal APIs.
|
||||
*
|
||||
* Author: Rob Percival (robpercival@google.com)
|
||||
* Date: 2016-01-26
|
||||
* Author: Rob Percival (robpercival@google.com)
|
||||
*
|
||||
* ====================================================================
|
||||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved.
|
||||
|
@ -72,9 +71,12 @@
|
|||
|
||||
typedef struct ct_test_fixture {
|
||||
const char *test_case_name;
|
||||
/* The CT log store to use during tests */
|
||||
CTLOG_STORE* ctlog_store;
|
||||
/* Set the following to test handling of SCTs in X509 certificates */
|
||||
const char *certificate_file_path;
|
||||
size_t expected_sct_count;
|
||||
const char *issuer_file_path;
|
||||
int expected_sct_count;
|
||||
/* Set the following to test handling of SCTs in TLS format */
|
||||
const uint8_t *tls_sct;
|
||||
size_t tls_sct_len;
|
||||
|
@ -85,6 +87,8 @@ typedef struct ct_test_fixture {
|
|||
* A maximum of |CT_TEST_MAX_FILE_SIZE| bytes will be read of this file.
|
||||
*/
|
||||
const char *sct_text_file_path;
|
||||
/* Whether to test the validity of the SCT(s) */
|
||||
int test_validity;
|
||||
|
||||
} CT_TEST_FIXTURE;
|
||||
|
||||
|
@ -92,10 +96,25 @@ static CT_TEST_FIXTURE set_up(const char *const test_case_name)
|
|||
{
|
||||
CT_TEST_FIXTURE fixture;
|
||||
int setup_ok = 1;
|
||||
CTLOG_STORE *ctlog_store = CTLOG_STORE_new();
|
||||
|
||||
if (ctlog_store == NULL) {
|
||||
setup_ok = 0;
|
||||
fprintf(stderr, "Failed to create a new CT log store\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (CTLOG_STORE_load_default_file(ctlog_store) != 1) {
|
||||
setup_ok = 0;
|
||||
fprintf(stderr, "Failed to load CT log list\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
memset(&fixture, 0, sizeof(fixture));
|
||||
fixture.test_case_name = test_case_name;
|
||||
fixture.ctlog_store = ctlog_store;
|
||||
|
||||
end:
|
||||
if (!setup_ok) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -104,6 +123,7 @@ static CT_TEST_FIXTURE set_up(const char *const test_case_name)
|
|||
|
||||
static void tear_down(CT_TEST_FIXTURE fixture)
|
||||
{
|
||||
CTLOG_STORE_free(fixture.ctlog_store);
|
||||
ERR_print_errors_fp(stderr);
|
||||
}
|
||||
|
||||
|
@ -211,11 +231,13 @@ end:
|
|||
|
||||
static int execute_cert_test(CT_TEST_FIXTURE fixture)
|
||||
{
|
||||
int result = 0;
|
||||
X509 *cert = NULL;
|
||||
int test_failed = 0;
|
||||
X509 *cert = NULL, *issuer = NULL;
|
||||
STACK_OF(SCT) *scts = NULL;
|
||||
SCT *sct = NULL;
|
||||
char expected_sct_text[CT_TEST_MAX_FILE_SIZE];
|
||||
int sct_text_len = 0;
|
||||
CT_POLICY_EVAL_CTX *ct_policy_ctx = CT_POLICY_EVAL_CTX_new();
|
||||
|
||||
if (fixture.sct_text_file_path != NULL) {
|
||||
sct_text_len = read_text_file(
|
||||
|
@ -224,7 +246,7 @@ static int execute_cert_test(CT_TEST_FIXTURE fixture)
|
|||
CT_TEST_MAX_FILE_SIZE - 1);
|
||||
|
||||
if (sct_text_len < 0) {
|
||||
result = 1;
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Test data file not found: %s\n",
|
||||
fixture.sct_text_file_path);
|
||||
goto end;
|
||||
|
@ -233,38 +255,106 @@ static int execute_cert_test(CT_TEST_FIXTURE fixture)
|
|||
expected_sct_text[sct_text_len] = '\0';
|
||||
}
|
||||
|
||||
CT_POLICY_EVAL_CTX_set0_log_store(ct_policy_ctx, fixture.ctlog_store);
|
||||
|
||||
if (fixture.certificate_file_path != NULL) {
|
||||
int sct_extension_index;
|
||||
X509_EXTENSION *sct_extension = NULL;
|
||||
cert = load_pem_cert(fixture.certificate_file_path);
|
||||
|
||||
if (cert == NULL) {
|
||||
result = 1;
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Unable to load certificate: %s\n",
|
||||
fixture.certificate_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
sct_extension_index = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1);
|
||||
CT_POLICY_EVAL_CTX_set0_cert(ct_policy_ctx, cert);
|
||||
|
||||
if (fixture.issuer_file_path != NULL) {
|
||||
issuer = load_pem_cert(fixture.issuer_file_path);
|
||||
|
||||
if (issuer == NULL) {
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Unable to load issuer certificate: %s\n",
|
||||
fixture.issuer_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
CT_POLICY_EVAL_CTX_set0_issuer(ct_policy_ctx, issuer);
|
||||
}
|
||||
|
||||
sct_extension_index =
|
||||
X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1);
|
||||
sct_extension = X509_get_ext(cert, sct_extension_index);
|
||||
if (fixture.expected_sct_count > 0) {
|
||||
if (sct_extension == NULL) {
|
||||
result = 1;
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "SCT extension not found in: %s\n",
|
||||
fixture.certificate_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fixture.sct_text_file_path) {
|
||||
result = compare_extension_printout(sct_extension,
|
||||
test_failed = compare_extension_printout(sct_extension,
|
||||
expected_sct_text);
|
||||
if (result != 0)
|
||||
if (test_failed != 0)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fixture.test_validity) {
|
||||
int are_scts_validated = 0;
|
||||
scts = X509V3_EXT_d2i(sct_extension);
|
||||
SCT_LIST_set_source(scts, SCT_SOURCE_X509V3_EXTENSION);
|
||||
|
||||
are_scts_validated = SCT_LIST_validate(scts, ct_policy_ctx);
|
||||
if (are_scts_validated < 0) {
|
||||
fprintf(stderr, "Error verifying SCTs\n");
|
||||
test_failed = 1;
|
||||
} else if (!are_scts_validated) {
|
||||
int invalid_sct_count = 0;
|
||||
int valid_sct_count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sk_SCT_num(scts); ++i) {
|
||||
SCT *sct_i = sk_SCT_value(scts, i);
|
||||
switch (SCT_get_validation_status(sct_i)) {
|
||||
case SCT_VALIDATION_STATUS_VALID:
|
||||
++valid_sct_count;
|
||||
break;
|
||||
case SCT_VALIDATION_STATUS_INVALID:
|
||||
++invalid_sct_count;
|
||||
break;
|
||||
default:
|
||||
/* Ignore other validation statuses. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_sct_count != fixture.expected_sct_count) {
|
||||
int unverified_sct_count = sk_SCT_num(scts) -
|
||||
invalid_sct_count - valid_sct_count;
|
||||
|
||||
fprintf(stderr,
|
||||
"%d SCTs failed verification\n"
|
||||
"%d SCTs passed verification (%d expected)\n"
|
||||
"%d SCTs were unverified\n",
|
||||
invalid_sct_count,
|
||||
valid_sct_count,
|
||||
fixture.expected_sct_count,
|
||||
unverified_sct_count);
|
||||
}
|
||||
test_failed = 1;
|
||||
}
|
||||
|
||||
if (test_failed != 0)
|
||||
goto end;
|
||||
}
|
||||
} else if (sct_extension != NULL) {
|
||||
result = 1;
|
||||
fprintf(stderr, "Expected no SCTs, but found SCT extension in: %s\n",
|
||||
fixture.certificate_file_path);
|
||||
test_failed = 1;
|
||||
fprintf(stderr,
|
||||
"Expected no SCTs, but found SCT extension in: %s\n",
|
||||
fixture.certificate_file_path);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
@ -274,30 +364,46 @@ static int execute_cert_test(CT_TEST_FIXTURE fixture)
|
|||
unsigned char *tls_sct;
|
||||
size_t tls_sct_len;
|
||||
if (o2i_SCT(&sct, &p, fixture.tls_sct_len) == NULL) {
|
||||
result = 1;
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Failed to decode SCT from TLS format\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fixture.sct_text_file_path) {
|
||||
result = compare_sct_printout(sct, expected_sct_text);
|
||||
if (result != 0)
|
||||
test_failed = compare_sct_printout(sct, expected_sct_text);
|
||||
if (test_failed != 0)
|
||||
goto end;
|
||||
}
|
||||
|
||||
tls_sct_len = i2o_SCT(sct, &tls_sct);
|
||||
if (tls_sct_len != fixture.tls_sct_len ||
|
||||
memcmp(fixture.tls_sct, tls_sct, tls_sct_len) != 0) {
|
||||
result = 1;
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Failed to encode SCT into TLS format correctly\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fixture.test_validity && cert != NULL) {
|
||||
int is_sct_validated = SCT_validate(sct, ct_policy_ctx);
|
||||
if (is_sct_validated < 0) {
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "Error validating SCT\n");
|
||||
goto end;
|
||||
} else if (!is_sct_validated) {
|
||||
test_failed = 1;
|
||||
fprintf(stderr, "SCT failed verification\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
X509_free(cert);
|
||||
X509_free(issuer);
|
||||
SCT_LIST_free(scts);
|
||||
SCT_free(sct);
|
||||
return result;
|
||||
CT_POLICY_EVAL_CTX_free(ct_policy_ctx);
|
||||
return test_failed;
|
||||
}
|
||||
|
||||
#define SETUP_CT_TEST_FIXTURE() SETUP_TEST_FIXTURE(CT_TEST_FIXTURE, set_up)
|
||||
|
@ -307,6 +413,7 @@ static int test_no_scts_in_certificate()
|
|||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
fixture.certificate_file_path = "certs/leaf.pem";
|
||||
fixture.issuer_file_path = "certs/subinterCA.pem";
|
||||
fixture.expected_sct_count = 0;
|
||||
EXECUTE_CT_TEST();
|
||||
}
|
||||
|
@ -315,6 +422,7 @@ static int test_one_sct_in_certificate()
|
|||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
fixture.certificate_file_path = "certs/embeddedSCTs1.pem";
|
||||
fixture.issuer_file_path = "certs/embeddedSCTs1_issuer.pem";
|
||||
fixture.expected_sct_count = 1;
|
||||
fixture.sct_text_file_path = "certs/embeddedSCTs1.sct";
|
||||
EXECUTE_CT_TEST();
|
||||
|
@ -324,11 +432,32 @@ static int test_multiple_scts_in_certificate()
|
|||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
fixture.certificate_file_path = "certs/embeddedSCTs3.pem";
|
||||
fixture.issuer_file_path = "certs/embeddedSCTs3_issuer.pem";
|
||||
fixture.expected_sct_count = 3;
|
||||
fixture.sct_text_file_path = "certs/embeddedSCTs3.sct";
|
||||
EXECUTE_CT_TEST();
|
||||
}
|
||||
|
||||
static int test_verify_one_sct()
|
||||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
fixture.certificate_file_path = "certs/embeddedSCTs1.pem";
|
||||
fixture.issuer_file_path = "certs/embeddedSCTs1_issuer.pem";
|
||||
fixture.expected_sct_count = 1;
|
||||
fixture.test_validity = 1;
|
||||
EXECUTE_CT_TEST();
|
||||
}
|
||||
|
||||
static int test_verify_multiple_scts()
|
||||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
fixture.certificate_file_path = "certs/embeddedSCTs3.pem";
|
||||
fixture.issuer_file_path = "certs/embeddedSCTs3_issuer.pem";
|
||||
fixture.expected_sct_count = 3;
|
||||
fixture.test_validity = 1;
|
||||
EXECUTE_CT_TEST();
|
||||
}
|
||||
|
||||
static int test_decode_tls_sct()
|
||||
{
|
||||
SETUP_CT_TEST_FIXTURE();
|
||||
|
@ -384,6 +513,8 @@ int main(int argc, char *argv[])
|
|||
ADD_TEST(test_no_scts_in_certificate);
|
||||
ADD_TEST(test_one_sct_in_certificate);
|
||||
ADD_TEST(test_multiple_scts_in_certificate);
|
||||
ADD_TEST(test_verify_one_sct);
|
||||
ADD_TEST(test_verify_multiple_scts);
|
||||
ADD_TEST(test_decode_tls_sct);
|
||||
ADD_TEST(test_encode_tls_sct);
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||
use OpenSSL::Test::Simple;
|
||||
|
||||
simple_test("test_ct", "ct_test");
|
||||
setup("test_ct");
|
||||
$ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
|
||||
simple_test("test_ct", "ct_test", "ct");
|
||||
|
||||
|
|
|
@ -4788,3 +4788,16 @@ SCT_LIST_set0_logs 5291 1_1_0 EXIST::FUNCTION:
|
|||
CTLOG_STORE_get0_log_by_id 5292 1_1_0 EXIST::FUNCTION:
|
||||
CTLOG_STORE_load_default_file 5293 1_1_0 EXIST::FUNCTION:
|
||||
CTLOG_new 5294 1_1_0 EXIST::FUNCTION:
|
||||
SCT_LIST_validate 5295 1_1_0 EXIST::FUNCTION:
|
||||
CT_verify_at_least_one_good_sct 5296 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_set0_issuer 5297 1_1_0 EXIST::FUNCTION:
|
||||
SCT_get_validation_status 5298 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_set0_log_store 5299 1_1_0 EXIST::FUNCTION:
|
||||
SCT_validate 5300 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_new 5301 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_get0_cert 5302 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_get0_issuer 5303 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_set0_cert 5304 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_get0_log_store 5305 1_1_0 EXIST::FUNCTION:
|
||||
CT_POLICY_EVAL_CTX_free 5306 1_1_0 EXIST::FUNCTION:
|
||||
CT_verify_no_bad_scts 5307 1_1_0 EXIST::FUNCTION:
|
||||
|
|
Loading…
Reference in New Issue