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 "utils/s2n_safety.h" 20 : : 21 : : bool s2n_cert_authorities_supported_from_trust_store() 22 : 20 : { 23 : 20 : #if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST 24 : 20 : return true; 25 : : #else 26 : : return false; 27 : : #endif 28 : 20 : } 29 : : 30 : : static S2N_RESULT s2n_cert_authorities_set_from_trust_store(struct s2n_config *config) 31 : 9 : { 32 [ - + ][ # # ]: 9 : RESULT_ENSURE_REF(config); 33 : : 34 [ + + ]: 9 : if (!config->trust_store.trust_store) { 35 : 2 : return S2N_RESULT_OK; 36 : 2 : } 37 : : 38 : 7 : #if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST 39 : 7 : DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free); 40 [ - + ]: 7 : RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&output, 256)); 41 : : 42 : 7 : STACK_OF(X509_OBJECT) *objects = X509_STORE_get0_objects(config->trust_store.trust_store); 43 [ # # ][ - + ]: 7 : RESULT_ENSURE(objects, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 44 : : 45 : 7 : int objects_count = sk_X509_OBJECT_num(objects); 46 [ # # ][ - + ]: 7 : RESULT_ENSURE(objects_count >= 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 47 : : 48 [ + + ]: 195 : for (int i = 0; i < objects_count; i++) { 49 : 189 : X509_OBJECT *x509_object = sk_X509_OBJECT_value(objects, i); 50 [ - + ][ # # ]: 189 : RESULT_ENSURE(x509_object, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 51 : : 52 : 189 : X509 *cert = X509_OBJECT_get0_X509(x509_object); 53 [ - + ]: 189 : if (cert == NULL) { 54 : : /* X509_OBJECTs can also be CRLs, resulting in NULL here. Skip. */ 55 : 0 : continue; 56 : 0 : } 57 : : 58 : 189 : X509_NAME *name = X509_get_subject_name(cert); 59 [ - + ][ # # ]: 189 : RESULT_ENSURE(name, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 60 : : 61 : 189 : const uint8_t *name_bytes = NULL; 62 : 189 : size_t name_size = 0; 63 [ - + ][ # # ]: 189 : RESULT_GUARD_OSSL(X509_NAME_get0_der(name, &name_bytes, &name_size), 64 : 189 : S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); 65 : : 66 [ - + ]: 189 : RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(&output, name_size)); 67 [ - + ]: 189 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&output, name_bytes, name_size)); 68 [ + + ][ + - ]: 189 : RESULT_ENSURE(s2n_stuffer_data_available(&output) <= S2N_CERT_AUTHORITIES_MAX_SIZE, 69 : 189 : S2N_ERR_TOO_MANY_CAS); 70 : 189 : } 71 : : 72 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_extract_blob(&output, &config->cert_authorities)); 73 : 6 : return S2N_RESULT_OK; 74 : : #else 75 : : RESULT_BAIL(S2N_ERR_API_UNSUPPORTED_BY_LIBCRYPTO); 76 : : #endif 77 : 6 : } 78 : : 79 : : int s2n_config_set_cert_authorities_from_trust_store(struct s2n_config *config) 80 : 11 : { 81 [ + + ][ + - ]: 11 : POSIX_ENSURE_REF(config); 82 [ + + ][ + - ]: 10 : POSIX_ENSURE(!config->trust_store.loaded_system_certs, S2N_ERR_INVALID_STATE); 83 [ + + ]: 9 : POSIX_GUARD_RESULT(s2n_cert_authorities_set_from_trust_store(config)); 84 : 8 : return S2N_SUCCESS; 85 : 9 : } 86 : : 87 : : int s2n_cert_authorities_send(struct s2n_connection *conn, struct s2n_stuffer *out) 88 : 137 : { 89 [ - + ][ # # ]: 137 : POSIX_ENSURE_REF(conn); 90 [ - + ][ # # ]: 137 : POSIX_ENSURE_REF(conn->config); 91 [ - + ][ # # ]: 137 : POSIX_ENSURE_EQ(conn->mode, S2N_SERVER); 92 : 137 : struct s2n_blob *cert_authorities = &conn->config->cert_authorities; 93 [ - + ]: 137 : POSIX_GUARD(s2n_stuffer_write_uint16(out, cert_authorities->size)); 94 [ - + ]: 137 : POSIX_GUARD(s2n_stuffer_write(out, cert_authorities)); 95 : 137 : return S2N_SUCCESS; 96 : 137 : } 97 : : 98 : : int s2n_cert_authorities_recv(struct s2n_connection *conn, struct s2n_stuffer *in) 99 : 16 : { 100 [ # # ][ - + ]: 16 : POSIX_ENSURE_REF(conn); 101 [ # # ][ - + ]: 16 : POSIX_ENSURE_REF(conn->config); 102 : : 103 : : /* For now, we don't support receiving certificate authorities on the 104 : : * server side. s2n-tls doesn't send them from clients today. 105 : : * 106 : : * Only allocate the buffer if the callback which reads it is set, to save 107 : : * time and memory for other customers. 108 : : */ 109 [ + - ][ + + ]: 16 : if (conn->mode == S2N_CLIENT && conn->config->cert_request_cb) { 110 : 6 : uint16_t length = 0; 111 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &length)); 112 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_extract_blob(in, &conn->cert_authorities)); 113 [ # # ][ - + ]: 6 : POSIX_ENSURE_EQ(conn->cert_authorities.size, length); 114 : 6 : } 115 : : 116 : 16 : return S2N_SUCCESS; 117 : 16 : } 118 : : 119 : : static bool s2n_cert_authorities_should_send(struct s2n_connection *conn) 120 : 67 : { 121 [ + - ][ + - ]: 67 : return conn && conn->config && conn->config->cert_authorities.size > 0; [ + + ] 122 : 67 : } 123 : : 124 : : const s2n_extension_type s2n_cert_authorities_extension = { 125 : : .iana_value = TLS_EXTENSION_CERT_AUTHORITIES, 126 : : .minimum_version = S2N_TLS13, 127 : : .is_response = false, 128 : : .send = s2n_cert_authorities_send, 129 : : .should_send = s2n_cert_authorities_should_send, 130 : : /* 131 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.4 132 : : *# The "certificate_authorities" extension is used to indicate the 133 : : *# certificate authorities (CAs) which an endpoint supports and which 134 : : *# SHOULD be used by the receiving endpoint to guide certificate 135 : : *# selection. 136 : : */ 137 : : .recv = s2n_cert_authorities_recv, 138 : : .if_missing = s2n_extension_noop_if_missing, 139 : : };