summaryrefslogtreecommitdiffstats
path: root/crypto/ct
diff options
context:
space:
mode:
authorRob Percival <robpercival@google.com>2016-09-08 16:02:46 +0100
committerRich Salz <rsalz@openssl.org>2016-11-15 16:28:14 -0500
commita99be00636e73206f7a40b626595466003fa250e (patch)
tree9ef294d454248f15e4d7f206f9c6338056b08e95 /crypto/ct
parent5be6f71858a66060c7dcb46d0c015a55fc0b569d (diff)
Check that SCT timestamps are not in the future
Reviewed-by: Viktor Dukhovni <viktor@openssl.org> Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/1554) (cherry picked from commit 1fa9ffd934429f140edcfbaf76d2f32cc21e449b)
Diffstat (limited to 'crypto/ct')
-rw-r--r--crypto/ct/ct_err.c3
-rw-r--r--crypto/ct/ct_locl.h12
-rw-r--r--crypto/ct/ct_policy.c9
-rw-r--r--crypto/ct/ct_sct.c2
-rw-r--r--crypto/ct/ct_sct_ctx.c5
-rw-r--r--crypto/ct/ct_vfy.c4
6 files changed, 34 insertions, 1 deletions
diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c
index df232dc488..fe0778b278 100644
--- a/crypto/ct/ct_err.c
+++ b/crypto/ct/ct_err.c
@@ -36,6 +36,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_CTX_VERIFY), "SCT_CTX_verify"},
{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"},
@@ -45,7 +46,6 @@ static ERR_STRING_DATA CT_str_functs[] = {
{ERR_FUNC(CT_F_SCT_SET_LOG_ENTRY_TYPE), "SCT_set_log_entry_type"},
{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_CTX_VERIFY), "SCT_CTX_verify"},
{0, NULL}
};
@@ -58,6 +58,7 @@ 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_SCT_FUTURE_TIMESTAMP), "sct future timestamp"},
{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"},
diff --git a/crypto/ct/ct_locl.h b/crypto/ct/ct_locl.h
index 7adc4961b3..4b5e344191 100644
--- a/crypto/ct/ct_locl.h
+++ b/crypto/ct/ct_locl.h
@@ -98,6 +98,8 @@ struct sct_ctx_st {
/* 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 */
@@ -105,6 +107,8 @@ struct ct_policy_eval_ctx_st {
X509 *cert;
X509 *issuer;
CTLOG_STORE *log_store;
+ /* milliseconds since epoch (to check that SCTs aren't from the future) */
+ uint64_t epoch_time_in_ms;
};
/*
@@ -151,6 +155,14 @@ __owur int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
__owur int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
/*
+ * Sets the current time, in milliseconds since the Unix epoch.
+ * The timestamp of the SCT will be compared to this, to check that it was not
+ * issued in the future. RFC6962 states that "TLS clients MUST reject SCTs whose
+ * timestamp is in the future", so SCT verification will fail 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.
diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c
index 33738de103..074589db93 100644
--- a/crypto/ct/ct_policy.c
+++ b/crypto/ct/ct_policy.c
@@ -59,6 +59,11 @@ void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
ctx->log_store = log_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;
+}
+
X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx)
{
return ctx->cert;
@@ -74,3 +79,7 @@ const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *c
return ctx->log_store;
}
+uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx)
+{
+ return ctx->epoch_time_in_ms;
+}
diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c
index 67adcfaa52..92cee8d587 100644
--- a/crypto/ct/ct_sct.c
+++ b/crypto/ct/ct_sct.c
@@ -329,6 +329,8 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
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
diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c
index 28fd04485f..75a5027df0 100644
--- a/crypto/ct/ct_sct_ctx.c
+++ b/crypto/ct/ct_sct_ctx.c
@@ -256,3 +256,8 @@ int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
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;
+}
diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c
index 724f65579b..cabcf5782a 100644
--- a/crypto/ct/ct_vfy.c
+++ b/crypto/ct/ct_vfy.c
@@ -113,6 +113,10 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH);
return 0;
}
+ if (sct->timestamp > sctx->epoch_time_in_ms) {
+ CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP);
+ return 0;
+ }
ctx = EVP_MD_CTX_new();
if (ctx == NULL)