LCOV - code coverage report
Current view: top level - tls - s2n_security_rules.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 147 147 100.0 %
Date: 2025-08-15 07:28:39 Functions: 10 10 100.0 %
Branches: 67 166 40.4 %

           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                 :            : 
      16                 :            : #include "tls/s2n_security_rules.h"
      17                 :            : 
      18                 :            : #include <stdarg.h>
      19                 :            : 
      20                 :            : #include "crypto/s2n_fips.h"
      21                 :            : #include "tls/s2n_cipher_suites.h"
      22                 :            : #include "tls/s2n_signature_scheme.h"
      23                 :            : #include "utils/s2n_result.h"
      24                 :            : #include "utils/s2n_safety.h"
      25                 :            : 
      26                 :            : static S2N_RESULT s2n_security_rule_result_process(struct s2n_security_rule_result *result,
      27                 :            :         bool condition, const char *format, ...)
      28                 :       1897 : {
      29 [ #  # ][ -  + ]:       1897 :     RESULT_ENSURE_REF(result);
      30         [ +  + ]:       1897 :     if (condition) {
      31                 :       1809 :         return S2N_RESULT_OK;
      32                 :       1809 :     }
      33                 :         88 :     result->found_error = true;
      34                 :            : 
      35         [ +  + ]:         88 :     if (!result->write_output) {
      36                 :         16 :         return S2N_RESULT_OK;
      37                 :         16 :     }
      38                 :            : 
      39                 :         72 :     va_list vargs;
      40                 :         72 :     va_start(vargs, format);
      41                 :         72 :     int ret = s2n_stuffer_vprintf(&result->output, format, vargs);
      42                 :         72 :     va_end(vargs);
      43         [ -  + ]:         72 :     RESULT_GUARD_POSIX(ret);
      44         [ -  + ]:         72 :     RESULT_GUARD_POSIX(s2n_stuffer_write_char(&result->output, '\n'));
      45                 :         72 :     return S2N_RESULT_OK;
      46                 :         72 : }
      47                 :            : 
      48                 :            : static S2N_RESULT s2n_security_rule_validate_forward_secret(
      49                 :            :         const struct s2n_cipher_suite *cipher_suite, bool *valid)
      50                 :        396 : {
      51 [ -  + ][ #  # ]:        396 :     RESULT_ENSURE_REF(cipher_suite);
      52 [ -  + ][ #  # ]:        396 :     RESULT_ENSURE_REF(cipher_suite->key_exchange_alg);
      53                 :        396 :     *valid = cipher_suite->key_exchange_alg->is_ephemeral;
      54                 :        396 :     return S2N_RESULT_OK;
      55                 :        396 : }
      56                 :            : 
      57                 :            : static S2N_RESULT s2n_security_rule_all_sig_schemes(
      58                 :            :         const struct s2n_signature_scheme *sig_scheme, bool *valid)
      59                 :        758 : {
      60 [ -  + ][ #  # ]:        758 :     RESULT_ENSURE_REF(valid);
      61                 :        758 :     *valid = true;
      62                 :        758 :     return S2N_RESULT_OK;
      63                 :        758 : }
      64                 :            : 
      65                 :            : static S2N_RESULT s2n_security_rule_all_curves(
      66                 :            :         const struct s2n_ecc_named_curve *curve, bool *valid)
      67                 :        126 : {
      68 [ #  # ][ -  + ]:        126 :     RESULT_ENSURE_REF(valid);
      69                 :        126 :     *valid = true;
      70                 :        126 :     return S2N_RESULT_OK;
      71                 :        126 : }
      72                 :            : 
      73                 :            : static S2N_RESULT s2n_security_rule_all_hybrid_groups(
      74                 :            :         const struct s2n_kem_group *hybrid_group, bool *valid)
      75                 :         46 : {
      76 [ -  + ][ #  # ]:         46 :     RESULT_ENSURE_REF(valid);
      77                 :         46 :     *valid = true;
      78                 :         46 :     return S2N_RESULT_OK;
      79                 :         46 : }
      80                 :            : 
      81                 :            : static S2N_RESULT s2n_security_rule_all_versions(uint8_t version, bool *valid)
      82                 :         45 : {
      83 [ #  # ][ -  + ]:         45 :     RESULT_ENSURE_REF(valid);
      84                 :         45 :     *valid = true;
      85                 :         45 :     return S2N_RESULT_OK;
      86                 :         45 : }
      87                 :            : 
      88                 :            : const struct s2n_security_rule security_rule_definitions[S2N_SECURITY_RULES_COUNT] = {
      89                 :            :     [S2N_PERFECT_FORWARD_SECRECY] = {
      90                 :            :             .name = "Perfect Forward Secrecy",
      91                 :            :             .validate_cipher_suite = s2n_security_rule_validate_forward_secret,
      92                 :            :             .validate_sig_scheme = s2n_security_rule_all_sig_schemes,
      93                 :            :             .validate_cert_sig_scheme = s2n_security_rule_all_sig_schemes,
      94                 :            :             .validate_curve = s2n_security_rule_all_curves,
      95                 :            :             .validate_hybrid_group = s2n_security_rule_all_hybrid_groups,
      96                 :            :             .validate_version = s2n_security_rule_all_versions,
      97                 :            :     },
      98                 :            :     [S2N_FIPS_140_3] = {
      99                 :            :             .name = "FIPS 140-3 (2019)",
     100                 :            :             .validate_cipher_suite = s2n_fips_validate_cipher_suite,
     101                 :            :             .validate_sig_scheme = s2n_fips_validate_signature_scheme,
     102                 :            :             .validate_cert_sig_scheme = s2n_fips_validate_signature_scheme,
     103                 :            :             .validate_curve = s2n_fips_validate_curve,
     104                 :            :             .validate_hybrid_group = s2n_fips_validate_hybrid_group,
     105                 :            :             .validate_version = s2n_fips_validate_version,
     106                 :            :     },
     107                 :            : };
     108                 :            : 
     109                 :            : S2N_RESULT s2n_security_rule_validate_policy(const struct s2n_security_rule *rule,
     110                 :            :         const struct s2n_security_policy *policy, struct s2n_security_rule_result *result)
     111                 :         72 : {
     112 [ #  # ][ -  + ]:         72 :     RESULT_ENSURE_REF(rule);
     113 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(policy);
     114 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(result);
     115                 :            : 
     116                 :         72 :     const char *policy_name = NULL;
     117                 :         72 :     s2n_result_ignore(s2n_security_policy_get_version(policy, &policy_name));
     118         [ +  + ]:         72 :     if (policy_name == NULL) {
     119                 :         15 :         policy_name = "unnamed";
     120                 :         15 :     }
     121                 :            : 
     122                 :         72 :     const char *error_msg_format_name = "%s: policy %s: %s: %s (#%i)";
     123                 :         72 :     const char *error_msg_format_basic = "%s: policy %s: %s: %i";
     124                 :            : 
     125                 :         72 :     const struct s2n_cipher_preferences *cipher_prefs = policy->cipher_preferences;
     126 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(cipher_prefs);
     127         [ +  + ]:        632 :     for (size_t i = 0; i < cipher_prefs->count; i++) {
     128                 :        560 :         const struct s2n_cipher_suite *cipher_suite = cipher_prefs->suites[i];
     129 [ -  + ][ #  # ]:        560 :         RESULT_ENSURE_REF(cipher_suite);
     130                 :        560 :         bool is_valid = false;
     131 [ -  + ][ #  # ]:        560 :         RESULT_ENSURE_REF(rule->validate_cipher_suite);
     132         [ -  + ]:        560 :         RESULT_GUARD(rule->validate_cipher_suite(cipher_suite, &is_valid));
     133         [ -  + ]:        560 :         RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     134                 :        560 :                 error_msg_format_name, rule->name, policy_name,
     135                 :        560 :                 "cipher suite", cipher_suite->iana_name, i + 1));
     136                 :        560 :     }
     137                 :            : 
     138                 :         72 :     const struct s2n_signature_preferences *sig_prefs = policy->signature_preferences;
     139 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(sig_prefs);
     140         [ +  + ]:        790 :     for (size_t i = 0; i < sig_prefs->count; i++) {
     141                 :        718 :         const struct s2n_signature_scheme *sig_scheme = sig_prefs->signature_schemes[i];
     142 [ #  # ][ -  + ]:        718 :         RESULT_ENSURE_REF(sig_scheme);
     143                 :        718 :         bool is_valid = false;
     144 [ #  # ][ -  + ]:        718 :         RESULT_ENSURE_REF(rule->validate_sig_scheme);
     145         [ -  + ]:        718 :         RESULT_GUARD(rule->validate_sig_scheme(sig_scheme, &is_valid));
     146         [ -  + ]:        718 :         RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     147                 :        718 :                 error_msg_format_name, rule->name, policy_name,
     148                 :        718 :                 "signature scheme", sig_scheme->iana_name));
     149                 :        718 :     }
     150                 :            : 
     151                 :         72 :     const struct s2n_signature_preferences *cert_sig_prefs = policy->certificate_signature_preferences;
     152         [ +  + ]:         72 :     if (cert_sig_prefs) {
     153         [ +  + ]:        330 :         for (size_t i = 0; i < cert_sig_prefs->count; i++) {
     154                 :        295 :             const struct s2n_signature_scheme *sig_scheme = cert_sig_prefs->signature_schemes[i];
     155 [ #  # ][ -  + ]:        295 :             RESULT_ENSURE_REF(sig_scheme);
     156                 :        295 :             bool is_valid = false;
     157 [ -  + ][ #  # ]:        295 :             RESULT_ENSURE_REF(rule->validate_cert_sig_scheme);
     158         [ -  + ]:        295 :             RESULT_GUARD(rule->validate_cert_sig_scheme(sig_scheme, &is_valid));
     159         [ -  + ]:        295 :             RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     160                 :        295 :                     error_msg_format_name, rule->name, policy_name,
     161                 :        295 :                     "certificate signature scheme", sig_scheme->iana_name));
     162                 :        295 :         }
     163                 :         35 :     }
     164                 :            : 
     165                 :         72 :     const struct s2n_ecc_preferences *ecc_prefs = policy->ecc_preferences;
     166 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(ecc_prefs);
     167         [ +  + ]:        246 :     for (size_t i = 0; i < ecc_prefs->count; i++) {
     168                 :        174 :         const struct s2n_ecc_named_curve *curve = ecc_prefs->ecc_curves[i];
     169 [ #  # ][ -  + ]:        174 :         RESULT_ENSURE_REF(curve);
     170                 :        174 :         bool is_valid = false;
     171 [ #  # ][ -  + ]:        174 :         RESULT_ENSURE_REF(rule->validate_curve);
     172         [ -  + ]:        174 :         RESULT_GUARD(rule->validate_curve(curve, &is_valid));
     173         [ -  + ]:        174 :         RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     174                 :        174 :                 error_msg_format_name, rule->name, policy_name,
     175                 :        174 :                 "curve", curve->name, i + 1));
     176                 :        174 :     }
     177                 :            : 
     178                 :         72 :     const struct s2n_kem_preferences *kem_prefs = policy->kem_preferences;
     179 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(kem_prefs);
     180         [ +  + ]:        150 :     for (size_t i = 0; i < kem_prefs->tls13_kem_group_count; i++) {
     181                 :         78 :         const struct s2n_kem_group *kem_group = kem_prefs->tls13_kem_groups[i];
     182 [ -  + ][ #  # ]:         78 :         RESULT_ENSURE_REF(kem_group);
     183                 :         78 :         bool is_valid = false;
     184 [ #  # ][ -  + ]:         78 :         RESULT_ENSURE_REF(rule->validate_hybrid_group);
     185         [ -  + ]:         78 :         RESULT_GUARD(rule->validate_hybrid_group(kem_group, &is_valid));
     186         [ -  + ]:         78 :         RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     187                 :         78 :                 error_msg_format_name, rule->name, policy_name,
     188                 :         78 :                 "kem_group", kem_group->name, i + 1));
     189                 :         78 :     }
     190                 :            : 
     191                 :         72 :     bool is_valid = false;
     192 [ -  + ][ #  # ]:         72 :     RESULT_ENSURE_REF(rule->validate_version);
     193         [ -  + ]:         72 :     RESULT_GUARD(rule->validate_version(policy->minimum_protocol_version, &is_valid));
     194         [ -  + ]:         72 :     RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
     195                 :         72 :             error_msg_format_basic, rule->name, policy_name,
     196                 :         72 :             "min version", policy->minimum_protocol_version));
     197                 :            : 
     198                 :         72 :     return S2N_RESULT_OK;
     199                 :         72 : }
     200                 :            : 
     201                 :            : S2N_RESULT s2n_security_policy_validate_security_rules(
     202                 :            :         const struct s2n_security_policy *policy, struct s2n_security_rule_result *result)
     203                 :        129 : {
     204 [ -  + ][ #  # ]:        129 :     RESULT_ENSURE_REF(policy);
     205         [ +  + ]:        387 :     for (size_t rule_id = 0; rule_id < s2n_array_len(policy->rules); rule_id++) {
     206         [ +  + ]:        258 :         if (!policy->rules[rule_id]) {
     207                 :        200 :             continue;
     208                 :        200 :         }
     209 [ #  # ][ -  + ]:         58 :         RESULT_ENSURE_LT(rule_id, s2n_array_len(security_rule_definitions));
     210                 :         58 :         const struct s2n_security_rule *rule = &security_rule_definitions[rule_id];
     211         [ -  + ]:         58 :         RESULT_GUARD(s2n_security_rule_validate_policy(rule, policy, result));
     212                 :         58 :     }
     213                 :        129 :     return S2N_RESULT_OK;
     214                 :        129 : }
     215                 :            : 
     216                 :            : S2N_RESULT s2n_security_rule_result_init_output(struct s2n_security_rule_result *result)
     217                 :          5 : {
     218                 :            :     /* For the expected, happy case, the rule isn't violated, so nothing is written
     219                 :            :      * to the stuffer, so no memory is allocated.
     220                 :            :      */
     221         [ -  + ]:          5 :     RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&result->output, 0));
     222                 :          5 :     result->write_output = true;
     223                 :          5 :     return S2N_RESULT_OK;
     224                 :          5 : }
     225                 :            : 
     226                 :            : S2N_CLEANUP_RESULT s2n_security_rule_result_free(struct s2n_security_rule_result *result)
     227                 :          6 : {
     228         [ +  - ]:          6 :     if (result) {
     229         [ -  + ]:          6 :         RESULT_GUARD_POSIX(s2n_stuffer_free(&result->output));
     230                 :          6 :         *result = (struct s2n_security_rule_result){ 0 };
     231                 :          6 :     }
     232                 :          6 :     return S2N_RESULT_OK;
     233                 :          6 : }

Generated by: LCOV version 1.14