Branch data Line data Source code
1 : : /* 2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 : : * 4 : : * Licensed under the Apache License, Version 2.0 (the "License"). 5 : : * You may not use this file except in compliance with the License. 6 : : * A copy of the License is located at 7 : : * 8 : : * http://aws.amazon.com/apache2.0 9 : : * 10 : : * or in the "license" file accompanying this file. This file is distributed 11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 : : * express or implied. See the License for the specific language governing 13 : : * permissions and limitations under the License. 14 : : */ 15 : : #include "tls/extensions/s2n_cert_authorities.h" 16 : : 17 : : #include <openssl/x509.h> 18 : : 19 : : #include "crypto/s2n_openssl_x509.h" 20 : : #include "utils/s2n_safety.h" 21 : : 22 : : bool s2n_cert_authorities_supported_from_trust_store() 23 : 20 : { 24 : 20 : #if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST 25 : 20 : return true; 26 : : #else 27 : : return false; 28 : : #endif 29 : 20 : } 30 : : 31 : : static S2N_RESULT s2n_cert_authorities_set_from_trust_store(struct s2n_config *config) 32 : 9 : { 33 [ - + ][ # # ]: 9 : RESULT_ENSURE_REF(config); 34 : : 35 [ + + ]: 9 : if (!config->trust_store.trust_store) { 36 : 2 : return S2N_RESULT_OK; 37 : 2 : } 38 : : 39 : 7 : #if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST 40 : 7 : DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free); 41 [ - + ]: 7 : RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&output, 256)); 42 : : 43 : 7 : STACK_OF(X509_OBJECT) *objects = X509_STORE_get0_objects(config->trust_store.trust_store); 44 [ # # ][ - + ]: 7 : RESULT_ENSURE(objects, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 45 : : 46 : 7 : int objects_count = sk_X509_OBJECT_num(objects); 47 [ # # ][ - + ]: 7 : RESULT_ENSURE(objects_count >= 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 48 : : 49 [ + + ]: 195 : for (int i = 0; i < objects_count; i++) { 50 : 189 : X509_OBJECT *x509_object = sk_X509_OBJECT_value(objects, i); 51 [ - + ][ # # ]: 189 : RESULT_ENSURE(x509_object, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 52 : : 53 : 189 : X509 *cert = X509_OBJECT_get0_X509(x509_object); 54 [ - + ]: 189 : if (cert == NULL) { 55 : : /* X509_OBJECTs can also be CRLs, resulting in NULL here. Skip. */ 56 : 0 : continue; 57 : 0 : } 58 : : 59 : 189 : S2N_X509_CONST X509_NAME *name = X509_get_subject_name(cert); 60 [ - + ][ # # ]: 189 : RESULT_ENSURE(name, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 61 : : 62 : 189 : const uint8_t *name_bytes = NULL; 63 : 189 : size_t name_size = 0; 64 : : /* Some libcryptos (AWS-LC) return a const X509_NAME* from 65 : : * X509_get_subject_name but still take a non-const X509_NAME* in 66 : : * X509_NAME_get0_der, which only reads the name. Cast to bridge that. */ 67 [ - + ][ # # ]: 189 : RESULT_GUARD_OSSL(X509_NAME_get0_der((X509_NAME *) (uintptr_t) name, &name_bytes, &name_size), 68 : 189 : S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 69 : : 70 [ - + ]: 189 : RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(&output, name_size)); 71 [ - + ]: 189 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&output, name_bytes, name_size)); 72 [ + + ][ + - ]: 189 : RESULT_ENSURE(s2n_stuffer_data_available(&output) <= S2N_CERT_AUTHORITIES_MAX_SIZE, 73 : 189 : S2N_ERR_TOO_MANY_CAS); 74 : 189 : } 75 : : 76 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_extract_blob(&output, &config->cert_authorities)); 77 : 6 : return S2N_RESULT_OK; 78 : : #else 79 : : RESULT_BAIL(S2N_ERR_API_UNSUPPORTED_BY_LIBCRYPTO); 80 : : #endif 81 : 6 : } 82 : : 83 : : int s2n_config_set_cert_authorities_from_trust_store(struct s2n_config *config) 84 : 11 : { 85 [ + + ][ + - ]: 11 : POSIX_ENSURE_REF(config); 86 [ + + ][ + - ]: 10 : POSIX_ENSURE(!config->trust_store.loaded_system_certs, S2N_ERR_INVALID_STATE); 87 [ + + ]: 9 : POSIX_GUARD_RESULT(s2n_cert_authorities_set_from_trust_store(config)); 88 : 8 : return S2N_SUCCESS; 89 : 9 : } 90 : : 91 : : int s2n_cert_authorities_send(struct s2n_connection *conn, struct s2n_stuffer *out) 92 : 144 : { 93 [ - + ][ # # ]: 144 : POSIX_ENSURE_REF(conn); 94 [ - + ][ # # ]: 144 : POSIX_ENSURE_REF(conn->config); 95 [ - + ][ # # ]: 144 : POSIX_ENSURE_EQ(conn->mode, S2N_SERVER); 96 : 144 : struct s2n_blob *cert_authorities = &conn->config->cert_authorities; 97 [ - + ]: 144 : POSIX_GUARD(s2n_stuffer_write_uint16(out, cert_authorities->size)); 98 [ - + ]: 144 : POSIX_GUARD(s2n_stuffer_write(out, cert_authorities)); 99 : 144 : return S2N_SUCCESS; 100 : 144 : } 101 : : 102 : : int s2n_cert_authorities_recv(struct s2n_connection *conn, struct s2n_stuffer *in) 103 : 16 : { 104 [ # # ][ - + ]: 16 : POSIX_ENSURE_REF(conn); 105 [ # # ][ - + ]: 16 : POSIX_ENSURE_REF(conn->config); 106 : : 107 : : /* For now, we don't support receiving certificate authorities on the 108 : : * server side. s2n-tls doesn't send them from clients today. 109 : : * 110 : : * Only allocate the buffer if the callback which reads it is set, to save 111 : : * time and memory for other customers. 112 : : */ 113 [ + - ][ + + ]: 16 : if (conn->mode == S2N_CLIENT && conn->config->cert_request_cb) { 114 : 6 : uint16_t length = 0; 115 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &length)); 116 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_extract_blob(in, &conn->cert_authorities)); 117 [ # # ][ - + ]: 6 : POSIX_ENSURE_EQ(conn->cert_authorities.size, length); 118 : 6 : } 119 : : 120 : 16 : return S2N_SUCCESS; 121 : 16 : } 122 : : 123 : : static bool s2n_cert_authorities_should_send(struct s2n_connection *conn) 124 : 121 : { 125 [ + - ][ + - ]: 121 : return conn && conn->config && conn->config->cert_authorities.size > 0; [ + + ] 126 : 121 : } 127 : : 128 : : const s2n_extension_type s2n_cert_authorities_extension = { 129 : : .iana_value = TLS_EXTENSION_CERT_AUTHORITIES, 130 : : .minimum_version = S2N_TLS13, 131 : : .is_response = false, 132 : : .send = s2n_cert_authorities_send, 133 : : .should_send = s2n_cert_authorities_should_send, 134 : : /* 135 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.4 136 : : *# The "certificate_authorities" extension is used to indicate the 137 : : *# certificate authorities (CAs) which an endpoint supports and which 138 : : *# SHOULD be used by the receiving endpoint to guide certificate 139 : : *# selection. 140 : : */ 141 : : .recv = s2n_cert_authorities_recv, 142 : : .if_missing = s2n_extension_noop_if_missing, 143 : : };