[openssl-commits] [openssl] OpenSSL_1_1_0-stable update

Rich Salz rsalz at openssl.org
Tue Nov 15 21:43:29 UTC 2016


The branch OpenSSL_1_1_0-stable has been updated
       via  18ad46297dcd44c1ac6c9f7f2f966e19c4d45e91 (commit)
       via  5229bbe73909c1f62b8696f20d0a291f7afc767c (commit)
       via  f567076cf343cbfe084c133c5bfc59b3d55122ef (commit)
       via  af8852e9957ce00c44653a73ba2f3e332b493c52 (commit)
       via  81d5808064949e6f23c1eaac4b24f09c8b1255db (commit)
       via  6d1584aebae9e6f34b80fef4fb147c298cc723d2 (commit)
       via  609673d93b8d9d53b687d84afe40b7f30f43adf3 (commit)
       via  fd7138ddeed4b577c1a37cc58fef6e715753698d (commit)
       via  9c9d136156abf4741bddf04ee83807bbc013f353 (commit)
       via  a99be00636e73206f7a40b626595466003fa250e (commit)
      from  5be6f71858a66060c7dcb46d0c015a55fc0b569d (commit)


- Log -----------------------------------------------------------------
commit 18ad46297dcd44c1ac6c9f7f2f966e19c4d45e91
Author: Rich Salz <rsalz at openssl.org>
Date:   Tue Nov 15 16:34:18 2016 -0500

    Cherry-pick doc updates from PR 1554
    
    Also fix version in libcrypto.num, from backporting new
    functions.
    
    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)
    (cherry picked from commit ebcb536858a271e8812fb9bbafbc0b825e5ece24)

commit 5229bbe73909c1f62b8696f20d0a291f7afc767c
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)
    (cherry picked from commit ebcb536858a271e8812fb9bbafbc0b825e5ece24)

commit f567076cf343cbfe084c133c5bfc59b3d55122ef
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)
    (cherry picked from commit 08e588b7d5cefbfd107c88416900165a28a5b59e)

commit af8852e9957ce00c44653a73ba2f3e332b493c52
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)
    (cherry picked from commit 5e08606619c0b0e065f1ffa12ce6411f321ed174)

commit 81d5808064949e6f23c1eaac4b24f09c8b1255db
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)
    (cherry picked from commit c22aa33e29ce162c672c9b2f0df591db977d4e9b)

commit 6d1584aebae9e6f34b80fef4fb147c298cc723d2
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)
    (cherry picked from commit f0f535e92b096db4a308ecc49ba7f0fd3f0f7945)

commit 609673d93b8d9d53b687d84afe40b7f30f43adf3
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)
    (cherry picked from commit e25233d99c30885bdf97bfb6df657e13ca2bf1da)

commit fd7138ddeed4b577c1a37cc58fef6e715753698d
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)
    (cherry picked from commit 1871a5aa8a538c2b8ac3d302c1e9e72867f5ee0f)

commit 9c9d136156abf4741bddf04ee83807bbc013f353
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)
    (cherry picked from commit 333c2e43729a92cf37d4bd12d6a3531b4bd7e1da)

commit a99be00636e73206f7a40b626595466003fa250e
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)
    (cherry picked from commit 1fa9ffd934429f140edcfbaf76d2f32cc21e449b)

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

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/{crypto => }/CT_POLICY_EVAL_CTX_new.pod        | 21 ++++++--
 doc/{crypto => }/SCT_validate.pod                  | 10 ++--
 .../SSL_CTX_set_ct_validation_callback.pod         |  8 ++-
 include/openssl/ct.h                               | 19 +++++++-
 ssl/ssl_lib.c                                      |  1 +
 test/ct_test.c                                     | 57 ++++++++++++++++++++--
 util/libcrypto.num                                 |  2 +
 13 files changed, 150 insertions(+), 17 deletions(-)
 copy doc/{crypto => }/CT_POLICY_EVAL_CTX_new.pod (79%)
 copy doc/{crypto => }/SCT_validate.pod (90%)
 copy doc/{ssl => }/SSL_CTX_set_ct_validation_callback.pod (96%)

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 67adcfa..92cee8d 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 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/crypto/CT_POLICY_EVAL_CTX_new.pod b/doc/CT_POLICY_EVAL_CTX_new.pod
similarity index 79%
copy from doc/crypto/CT_POLICY_EVAL_CTX_new.pod
copy to doc/CT_POLICY_EVAL_CTX_new.pod
index 6279299..fedc58d 100644
--- a/doc/crypto/CT_POLICY_EVAL_CTX_new.pod
+++ b/doc/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.
@@ -78,7 +93,7 @@ CT_POLICY_EVAL_CTX_new() will return NULL if malloc fails.
 
 =head1 SEE ALSO
 
-L<ct(3)>
+L<ct(7)>
 
 =head1 HISTORY
 
diff --git a/doc/crypto/SCT_validate.pod b/doc/SCT_validate.pod
similarity index 90%
copy from doc/crypto/SCT_validate.pod
copy to doc/SCT_validate.pod
index 713bcd2..9868a28 100644
--- a/doc/crypto/SCT_validate.pod
+++ b/doc/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
 
@@ -78,7 +80,7 @@ returned value will be SCT_VALIDATION_STATUS_NOT_SET.
 
 =head1 SEE ALSO
 
-L<ct(3)>
+L<ct(7)>
 
 =head1 HISTORY
 
diff --git a/doc/ssl/SSL_CTX_set_ct_validation_callback.pod b/doc/SSL_CTX_set_ct_validation_callback.pod
similarity index 96%
copy from doc/ssl/SSL_CTX_set_ct_validation_callback.pod
copy to doc/SSL_CTX_set_ct_validation_callback.pod
index c481ecb..d818e00 100644
--- a/doc/ssl/SSL_CTX_set_ct_validation_callback.pod
+++ b/doc/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
@@ -119,12 +122,13 @@ callback) is set.
 
 =head1 SEE ALSO
 
-L<ssl(3)>,
+L<ssl(7)>,
 <SSL_get_verify_result(3)>,
 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 bd0fbf8..002b2e5 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -4175,6 +4175,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 6c96268..8ab2f7d 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:
@@ -250,7 +256,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;
 
@@ -260,7 +266,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;
     }
@@ -297,6 +303,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;
@@ -443,7 +451,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();
 }
@@ -454,7 +462,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();
 }
@@ -528,6 +549,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 main(int argc, char *argv[])
 {
     int result = 0;
@@ -548,8 +593,10 @@ int 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]);
     ERR_print_errors_fp(stderr);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index a16cc9f..15cf3f6 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4208,3 +4208,5 @@ OCSP_RESPID_set_by_key                  4158	1_1_0a	EXIST::FUNCTION:OCSP
 OCSP_RESPID_match                       4159	1_1_0a	EXIST::FUNCTION:OCSP
 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_0d	EXIST::FUNCTION:CT
+CT_POLICY_EVAL_CTX_set_time             4173	1_1_0d	EXIST::FUNCTION:CT


More information about the openssl-commits mailing list