mirror of
https://github.com/openssl/openssl.git
synced 2026-05-07 20:12:39 +00:00
Add CTLOG_STORE_add0_log() to add CTLOGs to a store programmatically
Reviewed-by: Tomas Mraz <tomas@openssl.foundation> Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org> MergeDate: Thu Mar 19 20:45:34 2026 (Merged from https://github.com/openssl/openssl/pull/30427)
This commit is contained in:
committed by
Eugene Syromiatnikov
parent
10b0340fec
commit
fe26a8fc90
@@ -41,6 +41,10 @@ OpenSSL Releases
|
||||
|
||||
*Paul Louvel*
|
||||
|
||||
* Added `CTLOG_STORE_add0_log()` to add individual CT logs to a `CTLOG_STORE`.
|
||||
|
||||
*Tim Perry*
|
||||
|
||||
* Dropped `no-ecdsa` and `no-ecdh` options from `Configure` as these options
|
||||
did not really disable the implementations. Use `no-ec` to disable the
|
||||
elliptic curve support.
|
||||
|
||||
@@ -315,6 +315,20 @@ EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log)
|
||||
return log->public_key;
|
||||
}
|
||||
|
||||
int CTLOG_STORE_add0_log(CTLOG_STORE *store, CTLOG *log)
|
||||
{
|
||||
if (store == NULL || log == NULL) {
|
||||
ERR_raise(ERR_LIB_CT, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sk_CTLOG_push(store->logs, log)) {
|
||||
ERR_raise(ERR_LIB_CT, ERR_R_CRYPTO_LIB);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a log ID, finds the matching log.
|
||||
* Returns NULL if no match found.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
CTLOG_STORE_new_ex,
|
||||
CTLOG_STORE_new, CTLOG_STORE_free,
|
||||
CTLOG_STORE_add0_log,
|
||||
CTLOG_STORE_load_default_file, CTLOG_STORE_load_file -
|
||||
Create and populate a Certificate Transparency log list
|
||||
|
||||
@@ -15,14 +16,17 @@ Create and populate a Certificate Transparency log list
|
||||
CTLOG_STORE *CTLOG_STORE_new(void);
|
||||
void CTLOG_STORE_free(CTLOG_STORE *store);
|
||||
|
||||
int CTLOG_STORE_add0_log(CTLOG_STORE *store, CTLOG *log);
|
||||
|
||||
int CTLOG_STORE_load_default_file(CTLOG_STORE *store);
|
||||
int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A CTLOG_STORE is a container for a list of CTLOGs (Certificate Transparency
|
||||
logs). The list can be loaded from one or more files and then searched by LogID
|
||||
(see RFC 6962, Section 3.2, for the definition of a LogID).
|
||||
logs). The list can be loaded from one or more files, or populated
|
||||
programmatically, and then searched by LogID (see RFC 6962, Section 3.2, for
|
||||
the definition of a LogID).
|
||||
|
||||
CTLOG_STORE_new_ex() creates an empty list of CT logs associated with
|
||||
the library context I<libctx> and the property query string I<propq>.
|
||||
@@ -30,8 +34,10 @@ the library context I<libctx> and the property query string I<propq>.
|
||||
CTLOG_STORE_new() does the same thing as CTLOG_STORE_new_ex() but with
|
||||
the default library context and property query string.
|
||||
|
||||
The CTLOG_STORE is then populated by CTLOG_STORE_load_default_file() or
|
||||
CTLOG_STORE_load_file(). CTLOG_STORE_load_default_file() loads from the default
|
||||
The CTLOG_STORE is then populated by CTLOG_STORE_load_default_file(),
|
||||
CTLOG_STORE_load_file(), or CTLOG_STORE_add0_log().
|
||||
|
||||
CTLOG_STORE_load_default_file() loads from the default
|
||||
file, which is named F<ct_log_list.cnf> in OPENSSLDIR (see the output of
|
||||
L<openssl-version(1)>). This can be overridden using an environment variable
|
||||
named B<CTLOG_FILE>. CTLOG_STORE_load_file() loads from a caller-specified file
|
||||
@@ -50,6 +56,11 @@ The expected format of the file is:
|
||||
description = Log 2
|
||||
key = <base64-encoded DER SubjectPublicKeyInfo here>
|
||||
|
||||
CTLOG_STORE_add0_log() adds a single CTLOG (see L<CTLOG_new(3)>) to the store.
|
||||
On success, the store takes ownership of I<log> and the caller must not free
|
||||
it. On failure, the caller retains ownership and is responsible for freeing
|
||||
I<log>.
|
||||
|
||||
Once a CTLOG_STORE is no longer required, it should be passed to
|
||||
CTLOG_STORE_free(). This will delete all of the CTLOGs stored within, along
|
||||
with the CTLOG_STORE itself. If the argument is NULL, nothing is done.
|
||||
@@ -62,6 +73,8 @@ invalid if it is missing a "key" or "description" field.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
B<CTLOG_STORE_add0_log> returns 1 on success, 0 on failure.
|
||||
|
||||
Both B<CTLOG_STORE_load_default_file> and B<CTLOG_STORE_load_file> return 1 if
|
||||
all CT logs in the file are successfully parsed and loaded, 0 otherwise.
|
||||
|
||||
@@ -73,8 +86,8 @@ L<SSL_CTX_set_ctlog_list_file(3)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
CTLOG_STORE_new_ex was added in OpenSSL 3.0. All other functions were
|
||||
added in OpenSSL 1.1.0.
|
||||
CTLOG_STORE_add0_log was added in OpenSSL 4.1. CTLOG_STORE_new_ex was added in
|
||||
OpenSSL 3.0. All other functions were added in OpenSSL 1.1.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
|
||||
@@ -499,6 +499,14 @@ CTLOG_STORE *CTLOG_STORE_new(void);
|
||||
*/
|
||||
void CTLOG_STORE_free(CTLOG_STORE *store);
|
||||
|
||||
/*
|
||||
* Adds a CT log to a CTLOG_STORE.
|
||||
* Takes ownership of the CTLOG on success - the caller must not free it after
|
||||
* a successful call. On failure, the caller retains ownership.
|
||||
* Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
__owur int CTLOG_STORE_add0_log(CTLOG_STORE *store, CTLOG *log);
|
||||
|
||||
/*
|
||||
* Finds a CT log in the store based on its log ID.
|
||||
* Returns the CT log, or NULL if no match is found.
|
||||
|
||||
+128
@@ -508,6 +508,131 @@ static int test_ctlog_from_base64(void)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ctlog_store_add0_log(void)
|
||||
{
|
||||
CTLOG_STORE *store = NULL;
|
||||
CTLOG *log = NULL;
|
||||
const CTLOG *found = NULL;
|
||||
const uint8_t *log_id = NULL;
|
||||
size_t log_id_len = 0;
|
||||
int result = 0;
|
||||
const char pkey_base64[] = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmXg8sUUzwBYaWrRb+V0IopzQ6o3U"
|
||||
"yEJ04r5ZrRXGdpYM8K+hB0pXrGRLI0eeWz+3skXrS0IO83AhA3GpRL6s6w==";
|
||||
const char name[] = "test log";
|
||||
|
||||
if (!TEST_ptr(store = CTLOG_STORE_new()))
|
||||
goto end;
|
||||
if (!TEST_true(CTLOG_new_from_base64(&log, pkey_base64, name)))
|
||||
goto end;
|
||||
|
||||
CTLOG_get0_log_id(log, &log_id, &log_id_len);
|
||||
if (!TEST_size_t_eq(log_id_len, CT_V1_HASHLEN))
|
||||
goto end;
|
||||
if (!TEST_ptr_null(CTLOG_STORE_get0_log_by_id(store, log_id, log_id_len)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(CTLOG_STORE_add0_log(store, log)))
|
||||
goto end;
|
||||
log = NULL;
|
||||
|
||||
found = CTLOG_STORE_get0_log_by_id(store, log_id, log_id_len);
|
||||
if (!TEST_ptr(found))
|
||||
goto end;
|
||||
if (!TEST_str_eq(CTLOG_get0_name(found), name))
|
||||
goto end;
|
||||
|
||||
result = 1;
|
||||
|
||||
end:
|
||||
CTLOG_STORE_free(store);
|
||||
CTLOG_free(log);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int test_ctlog_store_add0_log_validates_sct(void)
|
||||
{
|
||||
CTLOG_STORE *store = NULL;
|
||||
CTLOG *log = NULL;
|
||||
CT_POLICY_EVAL_CTX *ct_policy_ctx = NULL;
|
||||
X509 *cert = NULL, *issuer = NULL;
|
||||
STACK_OF(SCT) *scts = NULL;
|
||||
const X509_EXTENSION *sct_extension = NULL;
|
||||
int result = 0;
|
||||
const char pkey_base64[] = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmXg8sUUzwBYaWrRb+V0IopzQ6o3U"
|
||||
"yEJ04r5ZrRXGdpYM8K+hB0pXrGRLI0eeWz+3skXrS0IO83AhA3GpRL6s6w==";
|
||||
|
||||
if (!TEST_ptr(store = CTLOG_STORE_new()))
|
||||
goto end;
|
||||
if (!TEST_true(CTLOG_new_from_base64(&log, pkey_base64, "test")))
|
||||
goto end;
|
||||
if (!TEST_true(CTLOG_STORE_add0_log(store, log)))
|
||||
goto end;
|
||||
log = NULL;
|
||||
|
||||
if (!TEST_ptr(ct_policy_ctx = CT_POLICY_EVAL_CTX_new()))
|
||||
goto end;
|
||||
CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ct_policy_ctx, store);
|
||||
CT_POLICY_EVAL_CTX_set_time(ct_policy_ctx, 1580335307000ULL);
|
||||
|
||||
if (!TEST_ptr(cert = load_pem_cert(certs_dir, "embeddedSCTs1.pem")))
|
||||
goto end;
|
||||
if (!TEST_ptr(issuer = load_pem_cert(certs_dir, "embeddedSCTs1_issuer.pem")))
|
||||
goto end;
|
||||
CT_POLICY_EVAL_CTX_set1_cert(ct_policy_ctx, cert);
|
||||
CT_POLICY_EVAL_CTX_set1_issuer(ct_policy_ctx, issuer);
|
||||
|
||||
sct_extension = X509_get_ext(cert,
|
||||
X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1));
|
||||
if (!TEST_ptr(sct_extension))
|
||||
goto end;
|
||||
if (!TEST_ptr(scts = X509V3_EXT_d2i(sct_extension)))
|
||||
goto end;
|
||||
if (!TEST_int_eq(sk_SCT_num(scts), 1))
|
||||
goto end;
|
||||
if (!TEST_int_ge(SCT_LIST_validate(scts, ct_policy_ctx), 0))
|
||||
goto end;
|
||||
if (!TEST_int_eq(SCT_get_validation_status(sk_SCT_value(scts, 0)),
|
||||
SCT_VALIDATION_STATUS_VALID))
|
||||
goto end;
|
||||
|
||||
result = 1;
|
||||
|
||||
end:
|
||||
CTLOG_STORE_free(store);
|
||||
CTLOG_free(log);
|
||||
CT_POLICY_EVAL_CTX_free(ct_policy_ctx);
|
||||
X509_free(cert);
|
||||
X509_free(issuer);
|
||||
SCT_LIST_free(scts);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int test_ctlog_store_add0_log_null(void)
|
||||
{
|
||||
CTLOG_STORE *store = NULL;
|
||||
CTLOG *log = NULL;
|
||||
int result = 0;
|
||||
const char pkey_base64[] = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmXg8sUUzwBYaWrRb+V0IopzQ6o3U"
|
||||
"yEJ04r5ZrRXGdpYM8K+hB0pXrGRLI0eeWz+3skXrS0IO83AhA3GpRL6s6w==";
|
||||
|
||||
if (!TEST_ptr(store = CTLOG_STORE_new()))
|
||||
goto end;
|
||||
if (!TEST_false(CTLOG_STORE_add0_log(store, NULL)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(CTLOG_new_from_base64(&log, pkey_base64, "test")))
|
||||
goto end;
|
||||
if (!TEST_false(CTLOG_STORE_add0_log(NULL, log)))
|
||||
goto end;
|
||||
|
||||
result = 1;
|
||||
|
||||
end:
|
||||
CTLOG_STORE_free(store);
|
||||
CTLOG_free(log);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
int setup_tests(void)
|
||||
@@ -528,6 +653,9 @@ int setup_tests(void)
|
||||
ADD_TEST(test_encode_tls_sct);
|
||||
ADD_TEST(test_default_ct_policy_eval_ctx_time_is_now);
|
||||
ADD_TEST(test_ctlog_from_base64);
|
||||
ADD_TEST(test_ctlog_store_add0_log);
|
||||
ADD_TEST(test_ctlog_store_add0_log_validates_sct);
|
||||
ADD_TEST(test_ctlog_store_add0_log_null);
|
||||
#else
|
||||
printf("No CT support\n");
|
||||
#endif
|
||||
|
||||
@@ -5715,3 +5715,4 @@ OPENSSL_sk_set_cmp_thunks ? 4_0_0 EXIST::FUNCTION:
|
||||
ASN1_BIT_STRING_set1 ? 4_0_0 EXIST::FUNCTION:
|
||||
OSSL_ESS_check_signing_certs_ex ? 4_0_0 EXIST::FUNCTION:
|
||||
X509v3_delete_extension ? 4_0_0 EXIST::FUNCTION:
|
||||
CTLOG_STORE_add0_log ? 4_0_0 EXIST::FUNCTION:CT
|
||||
|
||||
Reference in New Issue
Block a user