X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fct%2Fct_sct.c;h=1dc16857ba50ba6176d4abee00044f01bbe47826;hp=20bb156afcd21d54fa58741fbe59adf9e43c7e64;hb=cc4e37f1e4af060dc41a3c84041a183ecd7aa80e;hpb=21b908a8f95a4b2e095c64876c6991020e6c099e diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c index 20bb156afc..1dc16857ba 100644 --- a/crypto/ct/ct_sct.c +++ b/crypto/ct/ct_sct.c @@ -1,59 +1,10 @@ /* - * Written by Rob Stradling (rob@comodo.com), Stephen Henson (steve@openssl.org) - * and Adam Eijdenberg (adam.eijdenberg@gmail.com) for the OpenSSL project 2016. - */ -/* ==================================================================== - * Copyright (c) 2014 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (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 */ #ifdef OPENSSL_NO_CT @@ -94,6 +45,11 @@ void SCT_free(SCT *sct) OPENSSL_free(sct); } +void SCT_LIST_free(STACK_OF(SCT) *a) +{ + sk_SCT_pop_free(a, SCT_free); +} + int SCT_set_version(SCT *sct, sct_version_t version) { if (version != SCT_VERSION_V1) { @@ -114,10 +70,11 @@ int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type) case CT_LOG_ENTRY_TYPE_PRECERT: sct->entry_type = entry_type; return 1; - default: - CTerr(CT_F_SCT_SET_LOG_ENTRY_TYPE, CT_R_UNSUPPORTED_ENTRY_TYPE); - return 0; + case CT_LOG_ENTRY_TYPE_NOT_SET: + break; } + CTerr(CT_F_SCT_SET_LOG_ENTRY_TYPE, CT_R_UNSUPPORTED_ENTRY_TYPE); + return 0; } int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len) @@ -166,7 +123,7 @@ void SCT_set_timestamp(SCT *sct, uint64_t timestamp) int SCT_set_signature_nid(SCT *sct, int nid) { - switch (nid) { + switch (nid) { case NID_sha256WithRSAEncryption: sct->hash_alg = TLSEXT_hash_sha256; sct->sig_alg = TLSEXT_signature_rsa; @@ -251,11 +208,6 @@ size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id) return sct->log_id_len; } -const char *SCT_get0_log_name(const SCT *sct) -{ - return CTLOG_get0_name(sct->log); -} - uint64_t SCT_get_timestamp(const SCT *sct) { return sct->timestamp; @@ -316,56 +268,18 @@ sct_source_t SCT_get_source(const SCT *sct) int SCT_set_source(SCT *sct, sct_source_t source) { sct->source = source; + sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; switch (source) { case SCT_SOURCE_TLS_EXTENSION: case SCT_SOURCE_OCSP_STAPLED_RESPONSE: return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509); case SCT_SOURCE_X509V3_EXTENSION: return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT); - default: /* if we aren't sure, leave the log entry type alone */ - return 1; - } -} - -int SCT_LIST_set_source(const STACK_OF(SCT) *scts, sct_source_t source) -{ - int i, ret = 0; - - for (i = 0; i < sk_SCT_num(scts); ++i) { - if (SCT_set_source(sk_SCT_value(scts, i), source)) - ++ret; - } - - return ret; -} - -const CTLOG *SCT_get0_log(const SCT *sct) -{ - return sct->log; -} - -int SCT_set0_log(SCT *sct, const CTLOG_STORE *ct_logs) -{ - sct->log = CTLOG_STORE_get0_log_by_id(ct_logs, sct->log_id, sct->log_id_len); - - return sct->log != NULL; -} - -int SCT_LIST_set0_logs(STACK_OF(SCT) *sct_list, const CTLOG_STORE *ct_logs) -{ - int sct_logs_found = 0; - int i; - - for (i = 0; i < sk_SCT_num(sct_list); ++i) { - SCT *sct = sk_SCT_value(sct_list, i); - - if (sct->log == NULL) - SCT_set0_log(sct, ct_logs); - if (sct->log != NULL) - ++sct_logs_found; + case SCT_SOURCE_UNKNOWN: + break; } - - return sct_logs_found; + /* if we aren't sure, leave the log entry type alone */ + return 1; } sct_validation_status_t SCT_get_validation_status(const SCT *sct) @@ -378,29 +292,31 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) int is_sct_valid = -1; SCT_CTX *sctx = NULL; X509_PUBKEY *pub = NULL, *log_pkey = NULL; + const CTLOG *log; - switch (sct->version) { - case SCT_VERSION_V1: - if (sct->log == NULL) - sct->log = CTLOG_STORE_get0_log_by_id(ctx->log_store, - sct->log_id, - CT_V1_HASHLEN); - break; - default: + /* + * 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; } - if (sct->log == NULL) { + 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(); if (sctx == NULL) goto err; - if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(sct->log)) != 1) + if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1) goto err; if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1) goto err; @@ -421,10 +337,30 @@ 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 + * 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_CTX_verify(sctx, sct) == 1 ? SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; end: