[openssl-commits] [openssl] master update

Rich Salz rsalz at openssl.org
Tue Nov 15 21:20:46 UTC 2016


The branch master has been updated
       via  ebcb536858a271e8812fb9bbafbc0b825e5ece24 (commit)
       via  08e588b7d5cefbfd107c88416900165a28a5b59e (commit)
       via  5e08606619c0b0e065f1ffa12ce6411f321ed174 (commit)
       via  c22aa33e29ce162c672c9b2f0df591db977d4e9b (commit)
       via  f0f535e92b096db4a308ecc49ba7f0fd3f0f7945 (commit)
       via  e25233d99c30885bdf97bfb6df657e13ca2bf1da (commit)
       via  1871a5aa8a538c2b8ac3d302c1e9e72867f5ee0f (commit)
       via  333c2e43729a92cf37d4bd12d6a3531b4bd7e1da (commit)
       via  1fa9ffd934429f140edcfbaf76d2f32cc21e449b (commit)
      from  7b176a549ea374fc9b64c3fa7f0812239528b696 (commit)


- Log -----------------------------------------------------------------
commit ebcb536858a271e8812fb9bbafbc0b825e5ece24
Author: Rob Percival <robpercival at google.com>
Date:   Tue Nov 15 10:42:57 2016 +0000

    Add test for CT_POLICY_EVAL_CTX default time
    
    Checks that the epoch_time_in_ms field of CT_POLICY_EVAL_CTX is initialized
    to approximately the current time (as returned by time()) by default. This
    prevents the addition of this field, and its verification during SCT
    validation, from breaking existing code that calls SCT_validate directly.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit 08e588b7d5cefbfd107c88416900165a28a5b59e
Author: Rob Percival <robpercival at google.com>
Date:   Wed Sep 14 20:26:23 2016 +0100

    Convert C++ comments to C-style comments
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit 5e08606619c0b0e065f1ffa12ce6411f321ed174
Author: Rob Percival <robpercival at google.com>
Date:   Wed Sep 14 20:25:01 2016 +0100

    Cast time_t to uint64_t before converting to milliseconds in ct_policy.c
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit c22aa33e29ce162c672c9b2f0df591db977d4e9b
Author: Rob Percival <robpercival at google.com>
Date:   Mon Sep 12 17:02:58 2016 +0100

    By default, allow SCT timestamps to be up to 5 minutes in the future
    
    As requested in
    https://github.com/openssl/openssl/pull/1554#issuecomment-246371575.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit f0f535e92b096db4a308ecc49ba7f0fd3f0f7945
Author: Rob Percival <robpercival at google.com>
Date:   Mon Sep 12 16:58:29 2016 +0100

    Don't check for time() failing in CT_POLICY_EVAL_CTX_new
    
    See https://github.com/openssl/openssl/pull/1554#issuecomment-246354677.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit e25233d99c30885bdf97bfb6df657e13ca2bf1da
Author: Rob Percival <robpercival at google.com>
Date:   Mon Sep 12 16:57:38 2016 +0100

    Default CT_POLICY_EVAL_CTX.epoch_time_in_ms to time()
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit 1871a5aa8a538c2b8ac3d302c1e9e72867f5ee0f
Author: Rob Percival <robpercival at google.com>
Date:   Mon Sep 12 10:28:21 2016 +0100

    Reword documentation for {SCT_CTX/CT_POLICY_EVAL_CTX}_set_time
    
    Do not call the time "current", as a different time can be provided.
    For example, a time slightly in the future, to provide tolerance for
    CT logs with a clock that is running fast.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit 333c2e43729a92cf37d4bd12d6a3531b4bd7e1da
Author: Rob Percival <robpercival at google.com>
Date:   Thu Sep 8 16:03:26 2016 +0100

    Remove obsolete error constant CT_F_CTLOG_NEW_NULL
    
    ctlog_new_null() no longer exists.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

commit 1fa9ffd934429f140edcfbaf76d2f32cc21e449b
Author: Rob Percival <robpercival at google.com>
Date:   Thu Sep 8 16:02:46 2016 +0100

    Check that SCT timestamps are not in the future
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/1554)

-----------------------------------------------------------------------

Summary of changes:
 crypto/ct/ct_err.c                              |  3 +-
 crypto/ct/ct_locl.h                             | 13 ++++++
 crypto/ct/ct_policy.c                           | 22 ++++++++++
 crypto/ct/ct_sct.c                              |  2 +
 crypto/ct/ct_sct_ctx.c                          |  5 +++
 crypto/ct/ct_vfy.c                              |  4 ++
 doc/man3/CT_POLICY_EVAL_CTX_new.pod             | 19 ++++++++-
 doc/man3/SCT_validate.pod                       |  8 ++--
 doc/man3/SSL_CTX_set_ct_validation_callback.pod |  6 ++-
 include/openssl/ct.h                            | 19 ++++++++-
 ssl/ssl_lib.c                                   |  1 +
 test/ct_test.c                                  | 57 ++++++++++++++++++++++---
 util/libcrypto.num                              |  2 +
 13 files changed, 147 insertions(+), 14 deletions(-)

diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c
index df232dc..fe0778b 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 7adc496..9f983c9 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,15 @@ __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 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.
diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c
index 33738de..0d7b346 100644
--- a/crypto/ct/ct_policy.c
+++ b/crypto/ct/ct_policy.c
@@ -13,9 +13,18 @@
 
 #include <openssl/ct.h>
 #include <openssl/err.h>
+#include <time.h>
 
 #include "ct_locl.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 = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX));
@@ -25,6 +34,10 @@ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
         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;
 }
 
@@ -59,6 +72,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 +92,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 2f0fef7..1b13d9e 100644
--- a/crypto/ct/ct_sct.c
+++ b/crypto/ct/ct_sct.c
@@ -332,6 +332,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 28fd044..75a5027 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 724f655..cabcf57 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)
diff --git a/doc/man3/CT_POLICY_EVAL_CTX_new.pod b/doc/man3/CT_POLICY_EVAL_CTX_new.pod
index 37f3ed5..fedc58d 100644
--- a/doc/man3/CT_POLICY_EVAL_CTX_new.pod
+++ b/doc/man3/CT_POLICY_EVAL_CTX_new.pod
@@ -5,7 +5,8 @@
 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_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
 
 =head1 SYNOPSIS
@@ -20,13 +21,16 @@ Encapsulates the data required to evaluate whether SCTs meet a Certificate Trans
  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);
 
 =head1 DESCRIPTION
 
 A B<CT_POLICY_EVAL_CTX> is used by functions that evaluate whether Signed
 Certificate Timestamps (SCTs) fulfil a Certificate Transparency (CT) policy.
 This policy may be, for example, that at least one valid SCT is available. To
-determine this, an SCT's signature must be verified. This requires:
+determine this, an SCT's timestamp and signature must be verified.
+This requires:
 
 =over
 
@@ -36,6 +40,8 @@ determine this, an SCT's signature must be verified. This requires:
 
 =item * the issuer certificate (if the SCT was issued for a pre-certificate)
 
+=item * the current time
+
 =back
 
 The above requirements are met using the setters described below.
@@ -58,6 +64,15 @@ Increments the reference count of the certificate.
 Holds a pointer to the CTLOG_STORE, so the CTLOG_STORE must outlive the
 CT_POLICY_EVAL_CTX.
 
+=item * CT_POLICY_EVAL_CTX_set_time() to set the time SCTs should be compared with to determine if they are valid
+
+The SCT timestamp will be 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.
+
 =back
 
 Each setter has a matching getter for accessing the current value.
diff --git a/doc/man3/SCT_validate.pod b/doc/man3/SCT_validate.pod
index 98ae618..9868a28 100644
--- a/doc/man3/SCT_validate.pod
+++ b/doc/man3/SCT_validate.pod
@@ -54,9 +54,11 @@ status will be SCT_VALIDATION_STATUS_UNKNOWN_LOG.
 If the SCT is of an unsupported version (only v1 is currently supported), the
 validation status will be SCT_VALIDATION_STATUS_UNKNOWN_VERSION.
 
-If the SCT's signature is incorrect, the validation status will be
-SCT_VALIDATION_STATUS_INVALID. Otherwise, if all checks have passed, the
-validation status will be SCT_VALIDATION_STATUS_VALID.
+If the SCT's signature is incorrect, its timestamp is in the future (relative to
+the time in CT_POLICY_EVAL_CTX), or if it is otherwise invalid, the validation
+status will be SCT_VALIDATION_STATUS_INVALID.
+
+If all checks pass, the validation status will be SCT_VALIDATION_STATUS_VALID.
 
 =head1 NOTES
 
diff --git a/doc/man3/SSL_CTX_set_ct_validation_callback.pod b/doc/man3/SSL_CTX_set_ct_validation_callback.pod
index a6cbe8f..d818e00 100644
--- a/doc/man3/SSL_CTX_set_ct_validation_callback.pod
+++ b/doc/man3/SSL_CTX_set_ct_validation_callback.pod
@@ -97,6 +97,9 @@ otherwise.
 When SCT processing is enabled, OCSP stapling will be enabled. This is because
 one possible source of SCTs is the OCSP response from a server.
 
+The time returned by SSL_SESSION_get_time() will be used to evaluate whether any
+presented SCTs have timestamps that are in the future (and therefore invalid).
+
 =head1 RESTRICTIONS
 
 Certificate Transparency validation cannot be enabled and so a callback cannot
@@ -124,7 +127,8 @@ L<ssl(7)>,
 L<SSL_session_reused(3)>,
 L<SSL_set_verify(3)>,
 L<SSL_CTX_set_verify(3)>,
-L<ssl_ct_validation_cb(3)>
+L<ssl_ct_validation_cb(3)>,
+L<SSL_SESSION_get_time(3)>
 
 =head1 COPYRIGHT
 
diff --git a/include/openssl/ct.h b/include/openssl/ct.h
index 6c63265..bf29fba 100644
--- a/include/openssl/ct.h
+++ b/include/openssl/ct.h
@@ -98,6 +98,21 @@ const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *c
 void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
                                                CTLOG_STORE *log_store);
 
+/*
+ * Gets the time, in milliseconds since the Unix epoch, that will be used as the
+ * current time when checking whether an SCT was issued in the future.
+ * Such SCTs will fail validation, as required by RFC6962.
+ */
+uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx);
+
+/*
+ * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch.
+ * If an 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 CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms);
+
 /*****************
  * SCT functions *
  *****************/
@@ -467,7 +482,6 @@ int ERR_load_CT_strings(void);
 # define CT_F_CTLOG_NEW                                   117
 # define CT_F_CTLOG_NEW_FROM_BASE64                       118
 # define CT_F_CTLOG_NEW_FROM_CONF                         119
-# define CT_F_CTLOG_NEW_NULL                              120
 # define CT_F_CTLOG_STORE_LOAD_CTX_NEW                    122
 # define CT_F_CTLOG_STORE_LOAD_FILE                       123
 # define CT_F_CTLOG_STORE_LOAD_LOG                        130
@@ -482,6 +496,7 @@ int 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_CTX_VERIFY                              128
 # define CT_F_SCT_NEW                                     100
 # define CT_F_SCT_NEW_FROM_BASE64                         127
 # define CT_F_SCT_SET0_LOG_ID                             101
@@ -491,7 +506,6 @@ int ERR_load_CT_strings(void);
 # define CT_F_SCT_SET_LOG_ENTRY_TYPE                      102
 # define CT_F_SCT_SET_SIGNATURE_NID                       103
 # define CT_F_SCT_SET_VERSION                             104
-# define CT_F_SCT_CTX_VERIFY                              128
 
 /* Reason codes. */
 # define CT_R_BASE64_DECODE_ERROR                         108
@@ -501,6 +515,7 @@ int 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_SCT_FUTURE_TIMESTAMP                        116
 # define CT_R_SCT_INVALID                                 104
 # define CT_R_SCT_INVALID_SIGNATURE                       107
 # define CT_R_SCT_LIST_INVALID                            105
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a6360ac..b6f7015 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -4279,6 +4279,7 @@ int ssl_validate_ct(SSL *s)
     CT_POLICY_EVAL_CTX_set1_cert(ctx, cert);
     CT_POLICY_EVAL_CTX_set1_issuer(ctx, issuer);
     CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ctx, s->ctx->ctlog_store);
+    CT_POLICY_EVAL_CTX_set_time(ctx, SSL_SESSION_get_time(SSL_get0_session(s)));
 
     scts = SSL_get0_peer_scts(s);
 
diff --git a/test/ct_test.c b/test/ct_test.c
index 1cfd0d1..eaf05dc 100644
--- a/test/ct_test.c
+++ b/test/ct_test.c
@@ -8,6 +8,7 @@
  */
 
 #include <ctype.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -29,13 +30,18 @@ static char *ct_dir = NULL;
 
 typedef struct ct_test_fixture {
     const char *test_case_name;
+    /* The current time in milliseconds */
+    uint64_t epoch_time_in_ms;
     /* 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 *certs_dir;
     char *certificate_file;
     char *issuer_file;
+    /* Expected number of SCTs */
     int expected_sct_count;
+    /* Expected number of valid SCTS */
+    int expected_valid_sct_count;
     /* Set the following to test handling of SCTs in TLS format */
     const unsigned char *tls_sct_list;
     size_t tls_sct_list_len;
@@ -49,7 +55,6 @@ typedef struct ct_test_fixture {
     const char *sct_text_file;
     /* Whether to test the validity of the SCT(s) */
     int test_validity;
-
 } CT_TEST_FIXTURE;
 
 static CT_TEST_FIXTURE set_up(const char *const test_case_name)
@@ -75,6 +80,7 @@ static CT_TEST_FIXTURE set_up(const char *const test_case_name)
     }
 
     fixture.test_case_name = test_case_name;
+    fixture.epoch_time_in_ms = 1473269626000; /* Sep 7 17:33:46 2016 GMT */
     fixture.ctlog_store = ctlog_store;
 
 end:
@@ -252,7 +258,7 @@ static int assert_validity(CT_TEST_FIXTURE fixture,
         }
     }
 
-    if (valid_sct_count != fixture.expected_sct_count) {
+    if (valid_sct_count != fixture.expected_valid_sct_count) {
         int unverified_sct_count = sk_SCT_num(scts) -
                 invalid_sct_count - valid_sct_count;
 
@@ -262,7 +268,7 @@ static int assert_validity(CT_TEST_FIXTURE fixture,
                 "%d SCTs were unverified\n",
                 invalid_sct_count,
                 valid_sct_count,
-                fixture.expected_sct_count,
+                fixture.expected_valid_sct_count,
                 unverified_sct_count);
         return 0;
     }
@@ -299,6 +305,8 @@ static int execute_cert_test(CT_TEST_FIXTURE fixture)
     CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(
             ct_policy_ctx, fixture.ctlog_store);
 
+    CT_POLICY_EVAL_CTX_set_time(ct_policy_ctx, fixture.epoch_time_in_ms);
+
     if (fixture.certificate_file != NULL) {
         int sct_extension_index;
         X509_EXTENSION *sct_extension = NULL;
@@ -445,7 +453,7 @@ static int test_verify_one_sct()
     fixture.certs_dir = certs_dir;
     fixture.certificate_file = "embeddedSCTs1.pem";
     fixture.issuer_file = "embeddedSCTs1_issuer.pem";
-    fixture.expected_sct_count = 1;
+    fixture.expected_sct_count = fixture.expected_valid_sct_count = 1;
     fixture.test_validity = 1;
     EXECUTE_CT_TEST();
 }
@@ -456,7 +464,20 @@ static int test_verify_multiple_scts()
     fixture.certs_dir = certs_dir;
     fixture.certificate_file = "embeddedSCTs3.pem";
     fixture.issuer_file = "embeddedSCTs3_issuer.pem";
-    fixture.expected_sct_count = 3;
+    fixture.expected_sct_count = fixture.expected_valid_sct_count = 3;
+    fixture.test_validity = 1;
+    EXECUTE_CT_TEST();
+}
+
+static int test_verify_fails_for_future_sct()
+{
+    SETUP_CT_TEST_FIXTURE();
+    fixture.epoch_time_in_ms = 1365094800000; /* Apr 4 17:00:00 2013 GMT */
+    fixture.certs_dir = certs_dir;
+    fixture.certificate_file = "embeddedSCTs1.pem";
+    fixture.issuer_file = "embeddedSCTs1_issuer.pem";
+    fixture.expected_sct_count = 1;
+    fixture.expected_valid_sct_count = 0;
     fixture.test_validity = 1;
     EXECUTE_CT_TEST();
 }
@@ -530,6 +551,30 @@ static int test_encode_tls_sct()
     EXECUTE_CT_TEST();
 }
 
+/*
+ * Tests that the CT_POLICY_EVAL_CTX default time is approximately now.
+ * Allow +-10 minutes, as it may compensate for clock skew.
+ */
+static int test_default_ct_policy_eval_ctx_time_is_now()
+{
+    int success = 0;
+    CT_POLICY_EVAL_CTX *ct_policy_ctx = CT_POLICY_EVAL_CTX_new();
+    const time_t default_time = CT_POLICY_EVAL_CTX_get_time(ct_policy_ctx) /
+            1000;
+    const time_t time_tolerance = 600;  /* 10 minutes */
+
+    if (fabs(difftime(time(NULL), default_time)) > time_tolerance) {
+        fprintf(stderr,
+                "Default CT_POLICY_EVAL_CTX time is not approximately now.\n");
+        goto end;
+    }
+
+    success = 1;
+end:
+    CT_POLICY_EVAL_CTX_free(ct_policy_ctx);
+    return success;
+}
+
 int test_main(int argc, char *argv[])
 {
     int result = 0;
@@ -545,8 +590,10 @@ int test_main(int argc, char *argv[])
     ADD_TEST(test_multiple_scts_in_certificate);
     ADD_TEST(test_verify_one_sct);
     ADD_TEST(test_verify_multiple_scts);
+    ADD_TEST(test_verify_fails_for_future_sct);
     ADD_TEST(test_decode_tls_sct);
     ADD_TEST(test_encode_tls_sct);
+    ADD_TEST(test_default_ct_policy_eval_ctx_time_is_now);
 
     result = run_tests(argv[0]);
 
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 0b4190b..a1fdc3e 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4218,3 +4218,5 @@ BIO_meth_get_write_ex                   4168	1_1_1	EXIST::FUNCTION:
 BIO_meth_set_write_ex                   4169	1_1_1	EXIST::FUNCTION:
 DSO_pathbyaddr                          4170	1_1_0c	EXIST::FUNCTION:
 DSO_dsobyaddr                           4171	1_1_0c	EXIST::FUNCTION:
+CT_POLICY_EVAL_CTX_get_time             4172	1_1_1	EXIST::FUNCTION:CT
+CT_POLICY_EVAL_CTX_set_time             4173	1_1_1	EXIST::FUNCTION:CT


More information about the openssl-commits mailing list