From 43341433a88a6a2cd38c35359f48653e809b10cd Mon Sep 17 00:00:00 2001 From: Viktor Dukhovni Date: Thu, 7 Apr 2016 14:17:37 -0400 Subject: Suppress CT callback as appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suppress CT callbacks with aNULL or PSK ciphersuites that involve no certificates. Ditto when the certificate chain is validated via DANE-TA(2) or DANE-EE(3) TLSA records. Also skip SCT processing when the chain is fails verification. Move and consolidate CT callbacks from libcrypto to libssl. We also simplify the interface to SSL_{,CTX_}_enable_ct() which can specify either a permissive mode that just collects information or a strict mode that requires at least one valid SCT or else asks to abort the connection. Simplified SCT processing and options in s_client(1) which now has just a simple pair of "-noct" vs. "-ct" options, the latter enables the permissive callback so that we can complete the handshake and report all relevant information. When printing SCTs, print the validation status if set and not valid. Signed-off-by: Rob Percival Reviewed-by: Emilia Käsper --- crypto/ct/ct_sct.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'crypto/ct/ct_sct.c') diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c index 9eefa0c..1fc7456 100644 --- a/crypto/ct/ct_sct.c +++ b/crypto/ct/ct_sct.c @@ -334,17 +334,22 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) X509_PUBKEY *pub = NULL, *log_pkey = NULL; const CTLOG *log; + /* + * With an unrecognized SCT version we don't know what such an SCT means, + * let alone validate one. So we return validation failure (0). + */ if (sct->version != SCT_VERSION_V1) { sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION; - goto end; + return 0; } log = CTLOG_STORE_get0_log_by_id(ctx->log_store, sct->log_id, sct->log_id_len); + /* Similarly, an SCT from an unknown log also cannot be validated. */ if (log == NULL) { sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG; - goto end; + return 0; } sctx = SCT_CTX_new(); @@ -372,10 +377,28 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) goto err; } + /* + * XXX: Potential for optimization. This repeats some idempotent heavy + * lifting on the certificate for each candidate SCT, and appears to not + * use any information in the SCT itself, only the certificate is + * processed. So it may make more sense to to do this just once, perhaps + * associated with the shared (by all SCTs) policy eval ctx. + * + * XXX: Failure here is global (SCT independent) and represents either an + * issue with the certificate (e.g. duplicate extensions) or an out of + * memory condition. When the certificate is incompatible with CT, we just + * mark the SCTs invalid, rather than report a failure to determine the + * validation status. That way, callbacks that want to do "soft" SCT + * processing will not abort handshakes with false positive internal + * errors. Since the function does not distinguish between certificate + * issues (peer's fault) and internal problems (out fault) the safe thing + * to do is to report a validation failure and let the callback or + * application decide what to do. + */ if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1) - goto err; - - sct->validation_status = SCT_verify(sctx, sct) == 1 ? + sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; + else + sct->validation_status = SCT_verify(sctx, sct) == 1 ? SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; end: -- cgit v1.1