LCOV - code coverage report
Current view: top level - tls/extensions - s2n_cert_authorities.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 64 66 97.0 %
Date: 2025-08-14 07:26:07 Functions: 6 6 100.0 %
Branches: 43 94 45.7 %

           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                 :            : };

Generated by: LCOV version 1.14