CT_POLICY_EVAL_CTX_NEW(3SSL)

πŸ’– CT_POLICY_EVAL_CTX_new, CT_POLICY_EVAL_CTX_new_ex, CT_POLICY_EVAL_CTX_free β€” and the whole lil CT policy fam πŸ’–

okay bestie, welcome to the 3SSL manual page for the OpenSSL CT_POLICY_EVAL_CTX crew ✨ this is the little context object that holds literally everything you need to figure out whether some SCTs actually satisfy a Certificate Transparency policy. yes we're being ✨cryptographically responsible✨ today, no cap.


🌸 NAME 🌸

CT_POLICY_EVAL_CTX_new_ex, CT_POLICY_EVAL_CTX_new, CT_POLICY_EVAL_CTX_free, CT_POLICY_EVAL_CTX_get0_cert, CT_POLICY_EVAL_CTX_set1_cert, CT_POLICY_EVAL_CTX_get0_issuer, CT_POLICY_EVAL_CTX_set1_issuer, CT_POLICY_EVAL_CTX_get0_log_store, CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE, CT_POLICY_EVAL_CTX_get_time, CT_POLICY_EVAL_CTX_set_time β€” encapsulates the data required to evaluate whether SCTs meet a Certificate Transparency policy πŸ¦‹


✨ SYNOPSIS ✨

#include <openssl/ct.h>

CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_ex(OSSL_LIB_CTX *libctx,
                                              const char *propq);
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void);
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx);
X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx);
int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert);
X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx);
int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer);
const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx);
void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
                                               CTLOG_STORE *log_store);
uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx);
void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms);

πŸ‘‘ DESCRIPTION πŸ‘‘

so a CT_POLICY_EVAL_CTX is what all the functions that check whether Signed Certificate Timestamps (aka SCTs) fulfil a Certificate Transparency (aka CT) policy pass around. and what's a policy, you ask? it's giving "at least one valid SCT is available", for example. to actually decide that, you gotta verify an SCT's timestamp and its signature. which means you need:

  • the public key of the log that issued the SCT πŸ”‘
  • the certificate that the SCT was issued for πŸ“œ
  • the issuer certificate (if the SCT was issued for a pre-certificate) 🧚
  • the current time ⏰

and you feed all of that in with the setters down below. the way this works is genuinely so clean, i'm obsessed.

CT_POLICY_EVAL_CTX_new_ex() makes you an empty policy evaluation context and pairs it up with the library context libctx and the property query string propq you hand it.

CT_POLICY_EVAL_CTX_new() is literally the same thing as CT_POLICY_EVAL_CTX_new_ex() except it rolls with the default library context and default property query string. iconic, low-effort, we love her πŸ’…

then you populate your CT_POLICY_EVAL_CTX using these:

  • CT_POLICY_EVAL_CTX_set1_cert() β€” to provide the certificate the SCTs were issued for.

increments the reference count of the certificate. πŸ”Ό

  • CT_POLICY_EVAL_CTX_set1_issuer() β€” to provide the issuer certificate.

increments the reference count of the certificate. πŸ”Ό

  • CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE() β€” to provide a list of logs that are trusted as sources of SCTs.

holds a pointer to the CTLOG_STORE, so the CTLOG_STORE must outlive the CT_POLICY_EVAL_CTX. no cap, don't let that thing get freed underneath you 😭

  • CT_POLICY_EVAL_CTX_set_time() β€” to set the time SCTs should be compared with to determine if they are valid.

the SCT timestamp gets compared to this time to check whether the SCT was issued in the future. RFC6962 states that "TLS clients MUST reject SCTs whose timestamp is in the future". by default this will be set to 5 minutes in the future (e.g. (time() + 300) * 1000), to allow for clock drift. ⏱️

the time should be in milliseconds since the Unix Epoch.

every setter has a matching getter for peeking at the current value πŸ‘€ β€” CT_POLICY_EVAL_CTX_get0_cert, CT_POLICY_EVAL_CTX_get0_issuer, CT_POLICY_EVAL_CTX_get0_log_store and CT_POLICY_EVAL_CTX_get_time. getter/setter pairs, the main character energy we deserve 🌈

when you're done with it, hand your CT_POLICY_EVAL_CTX over to CT_POLICY_EVAL_CTX_free() to delete it. and if the argument to CT_POLICY_EVAL_CTX_free() is NULL, nothing happens β€” no crash, no drama, she just vibes. 🫢


🌟 NOTES 🌟

the issuer certificate only needs to be provided if at least one of the SCTs was issued for a pre-certificate. that's always the case for SCTs embedded in a certificate (i.e. those in an X.509 extension), but it might not be the case for SCTs found in the TLS SCT extension or in an OCSP response. iykyk πŸ’…


πŸŽ€ RETURN VALUES πŸŽ€

CT_POLICY_EVAL_CTX_new_ex() and CT_POLICY_EVAL_CTX_new() will return NULL if malloc fails. πŸ’€ (that's the whole return values section, she's short and honest, periodt.)


πŸ”₯ SEE ALSO πŸ”₯

ct(7)


🌈 HISTORY 🌈

CT_POLICY_EVAL_CTX_new_ex was added in OpenSSL 3.0. all the other functions were added in OpenSSL 1.1.0. so this whole squad has been around a minute ⭐


Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (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>.


and that's the whole page bestie πŸ’– this was OpenSSL version 4.0.3, dated 2026-09-29, filed under CT_POLICY_EVAL_CTX_NEW(3SSL). go forth and validate those SCTs responsibly, mwah πŸŽ€βœ¨

πŸ“¦ where this page comes from