LCOV - code coverage report
Current view: top level - tls/policy - s2n_policy_builder.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 111 113 98.2 %
Date: 2025-09-30 07:28:05 Functions: 15 15 100.0 %
Branches: 110 238 46.2 %

           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/policy/s2n_policy_feature.h"
      17                 :            : #include "tls/s2n_security_policies.h"
      18                 :            : 
      19                 :            : struct s2n_security_policy_builder {
      20                 :            :     const struct s2n_security_policy *base_policy;
      21                 :            : };
      22                 :            : 
      23                 :            : /* All our lists behave the same, but use different types and field names.
      24                 :            :  * Use a macro to avoid writing multiple copies of the same basic methods.
      25                 :            :  */
      26                 :            : #define S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(pref_type, entry_type, list_name, count_name)              \
      27                 :            :     static S2N_RESULT pref_type##_copy(const struct pref_type *original, const struct pref_type **copy) \
      28                 :        822 :     {                                                                                                   \
      29 [ #  # ][ -  + ]:        822 :         RESULT_ENSURE_REF(copy);                                                                        \
         [ #  # ][ -  + ]
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
         [ -  + ][ #  # ]
      30 [ -  + ][ +  + ]:        822 :         if (original == NULL) {                                                                         \
         [ -  + ][ +  + ]
                 [ -  + ]
      31                 :        251 :             *copy = NULL;                                                                               \
      32                 :        251 :             return S2N_RESULT_OK;                                                                       \
      33                 :        251 :         }                                                                                               \
      34                 :        822 :         DEFER_CLEANUP(struct s2n_blob pref_mem = { 0 }, s2n_free);                                      \
      35 [ -  + ][ -  + ]:        571 :         RESULT_GUARD_POSIX(s2n_alloc(&pref_mem, sizeof(struct pref_type)));                             \
         [ -  + ][ -  + ]
                 [ -  + ]
      36 [ -  + ][ #  # ]:        571 :         RESULT_CHECKED_MEMCPY(pref_mem.data, original, pref_mem.size);                                  \
         [ -  + ][ -  + ]
         [ #  # ][ -  + ]
         [ #  # ][ -  + ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      37                 :        571 :                                                                                                         \
      38                 :        571 :         DEFER_CLEANUP(struct s2n_blob list_mem = { 0 }, s2n_free);                                      \
      39                 :        571 :         size_t list_mem_size = original->count_name * sizeof(entry_type);                               \
      40 [ -  + ][ -  + ]:        571 :         RESULT_GUARD_POSIX(s2n_alloc(&list_mem, list_mem_size));                                        \
         [ -  + ][ -  + ]
                 [ -  + ]
      41 [ #  # ][ #  # ]:        571 :         RESULT_CHECKED_MEMCPY(list_mem.data, original->list_name, list_mem.size);                       \
         [ -  + ][ #  # ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ -  + ][ -  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  - ]
      42                 :        571 :                                                                                                         \
      43                 :        571 :         struct pref_type *prefs = (struct pref_type *) (void *) pref_mem.data;                          \
      44                 :        571 :         prefs->list_name = (entry_type *) (void *) list_mem.data;                                       \
      45                 :        571 :         *copy = prefs;                                                                                  \
      46                 :        571 :                                                                                                         \
      47                 :        571 :         ZERO_TO_DISABLE_DEFER_CLEANUP(pref_mem);                                                        \
      48                 :        571 :         ZERO_TO_DISABLE_DEFER_CLEANUP(list_mem);                                                        \
      49                 :        571 :         return S2N_RESULT_OK;                                                                           \
      50                 :        571 :     }                                                                                                   \
      51                 :            :                                                                                                         \
      52                 :            :     static S2N_CLEANUP_RESULT pref_type##_free(const struct pref_type **prefs_ptr)                      \
      53                 :        822 :     {                                                                                                   \
      54 [ -  + ][ -  + ]:        822 :         if (!prefs_ptr) {                                                                               \
         [ -  + ][ -  + ]
                 [ -  + ]
      55                 :          0 :             return S2N_RESULT_OK;                                                                       \
      56                 :          0 :         }                                                                                               \
      57                 :        822 :         const struct pref_type *prefs = *prefs_ptr;                                                     \
      58 [ +  + ][ -  + ]:        822 :         if (!prefs) {                                                                                   \
         [ -  + ][ +  + ]
                 [ -  + ]
      59                 :        251 :             return S2N_RESULT_OK;                                                                       \
      60                 :        251 :         }                                                                                               \
      61                 :        822 :         size_t size = prefs->count_name * sizeof(entry_type);                                           \
      62                 :        571 :         /* Safety: we only free preferences allocated by the builder, so stripping
      63                 :        571 :          * the `const` in order to free is a known safe mutation.
      64                 :        571 :          */                      \
      65 [ -  + ][ -  + ]:        571 :         RESULT_GUARD_POSIX(s2n_free_object(                                                             \
         [ -  + ][ -  + ]
                 [ -  + ]
      66                 :        571 :                 (uint8_t **) (void *) (uintptr_t) (const void *) &prefs->list_name, size));             \
      67 [ -  + ][ -  + ]:        571 :         RESULT_GUARD_POSIX(s2n_free_object(                                                             \
         [ -  + ][ -  + ]
                 [ -  + ]
      68                 :        571 :                 (uint8_t **) (void *) (uintptr_t) (const void *) prefs_ptr, sizeof(struct pref_type))); \
      69                 :        571 :         return S2N_RESULT_OK;                                                                           \
      70                 :        571 :     }
      71                 :            : 
      72                 :            : S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(
      73                 :            :         s2n_cipher_preferences, struct s2n_cipher_suite *, suites, count)
      74                 :            : S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(
      75                 :            :         s2n_signature_preferences, const struct s2n_signature_scheme *const, signature_schemes, count)
      76                 :            : S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(
      77                 :            :         s2n_ecc_preferences, const struct s2n_ecc_named_curve *const, ecc_curves, count)
      78                 :            : S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(
      79                 :            :         s2n_certificate_key_preferences, const struct s2n_certificate_key *const, certificate_keys, count)
      80                 :            : /* s2n_kem_preferences actually has two lists, but the `kems` list is deprecated
      81                 :            :  * and no longer set for any policies. */
      82                 :            : S2N_DEFINE_PREFERENCE_LIST_FUNCTIONS(
      83                 :            :         s2n_kem_preferences, const struct s2n_kem_group *, tls13_kem_groups, tls13_kem_group_count)
      84                 :            : 
      85                 :            : /* Safety: this method does not break if new lists are added to s2n_security_policy.
      86                 :            :  * The copy will simply inherit the static version of the new list from the original,
      87                 :            :  * just like it inherits the values of non-list fields.
      88                 :            :  * The only requirement is that s2n_security_policy_free free every list created
      89                 :            :  * by s2n_security_policy_copy.
      90                 :            :  */
      91                 :            : static S2N_RESULT s2n_security_policy_copy(const struct s2n_security_policy *original, struct s2n_security_policy **copy)
      92                 :        137 : {
      93 [ -  + ][ #  # ]:        137 :     RESULT_ENSURE_REF(original);
      94 [ #  # ][ -  + ]:        137 :     RESULT_ENSURE_REF(copy);
      95 [ #  # ][ -  + ]:        137 :     RESULT_ENSURE_EQ(*copy, NULL);
      96                 :            : 
      97                 :        137 :     struct s2n_blob mem = { 0 };
      98         [ -  + ]:        137 :     RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_security_policy)));
      99                 :        137 :     DEFER_CLEANUP(struct s2n_security_policy *policy =
     100                 :        137 :                           (struct s2n_security_policy *) (void *) mem.data,
     101                 :        137 :             s2n_security_policy_free);
     102 [ -  + ][ #  # ]:        137 :     RESULT_CHECKED_MEMCPY(mem.data, original, mem.size);
                 [ +  - ]
     103                 :        137 :     policy->alloced = true;
     104                 :            : 
     105                 :            :     /* No existing policy still has TLS1.2 KEMs. Ignore them for simplicity. */
     106 [ -  + ][ #  # ]:        137 :     RESULT_ENSURE(original->kem_preferences->kem_count == 0, S2N_ERR_DEPRECATED_SECURITY_POLICY);
     107                 :            : 
     108         [ -  + ]:        137 :     RESULT_GUARD(s2n_cipher_preferences_copy(
     109                 :        137 :             original->cipher_preferences, &policy->cipher_preferences));
     110         [ -  + ]:        137 :     RESULT_GUARD(s2n_signature_preferences_copy(
     111                 :        137 :             original->signature_preferences, &policy->signature_preferences));
     112         [ -  + ]:        137 :     RESULT_GUARD(s2n_signature_preferences_copy(
     113                 :        137 :             original->certificate_signature_preferences, &policy->certificate_signature_preferences));
     114         [ -  + ]:        137 :     RESULT_GUARD(s2n_ecc_preferences_copy(
     115                 :        137 :             original->ecc_preferences, &policy->ecc_preferences));
     116         [ -  + ]:        137 :     RESULT_GUARD(s2n_certificate_key_preferences_copy(
     117                 :        137 :             original->certificate_key_preferences, &policy->certificate_key_preferences));
     118         [ -  + ]:        137 :     RESULT_GUARD(s2n_kem_preferences_copy(
     119                 :        137 :             original->kem_preferences, &policy->kem_preferences));
     120                 :            : 
     121                 :        137 :     *copy = policy;
     122                 :        137 :     ZERO_TO_DISABLE_DEFER_CLEANUP(policy);
     123                 :        137 :     return S2N_RESULT_OK;
     124                 :        137 : }
     125                 :            : 
     126                 :            : int s2n_security_policy_free(struct s2n_security_policy **policy_ptr)
     127                 :        412 : {
     128         [ +  + ]:        412 :     if (!policy_ptr) {
     129                 :          1 :         return S2N_SUCCESS;
     130                 :          1 :     }
     131                 :        411 :     struct s2n_security_policy *policy = *policy_ptr;
     132         [ +  + ]:        411 :     if (!policy) {
     133                 :        139 :         return S2N_SUCCESS;
     134                 :        139 :     }
     135                 :            : 
     136                 :            :     /* Static policies should always be const, so this method's non-const
     137                 :            :      * argument should prevent mistakes. However, there are ways to circumvent
     138                 :            :      * const in C, so add an extra safety check.
     139                 :            :      */
     140 [ +  + ][ +  - ]:        272 :     POSIX_ENSURE(policy->alloced, S2N_ERR_INVALID_ARGUMENT);
     141                 :            : 
     142         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_cipher_preferences_free(&policy->cipher_preferences));
     143         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_signature_preferences_free(&policy->signature_preferences));
     144         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_signature_preferences_free(&policy->certificate_signature_preferences));
     145         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_ecc_preferences_free(&policy->ecc_preferences));
     146         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_certificate_key_preferences_free(&policy->certificate_key_preferences));
     147         [ -  + ]:        137 :     POSIX_GUARD_RESULT(s2n_kem_preferences_free(&policy->kem_preferences));
     148                 :            : 
     149         [ -  + ]:        137 :     POSIX_GUARD(s2n_free_object((uint8_t **) policy_ptr, sizeof(struct s2n_security_policy)));
     150                 :        137 :     return S2N_SUCCESS;
     151                 :        137 : }
     152                 :            : 
     153                 :            : struct s2n_security_policy_builder *s2n_security_policy_builder_from_version(const char *version)
     154                 :        275 : {
     155 [ +  + ][ +  - ]:        275 :     PTR_ENSURE(version, S2N_ERR_INVALID_ARGUMENT);
     156                 :        274 :     DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
     157         [ -  + ]:        274 :     PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_security_policy_builder)));
     158                 :        274 :     struct s2n_security_policy_builder *builder =
     159                 :        274 :             (struct s2n_security_policy_builder *) (void *) mem.data;
     160                 :            : 
     161         [ +  + ]:        274 :     PTR_GUARD_POSIX(s2n_find_security_policy_from_version(version, &builder->base_policy));
     162 [ -  + ][ #  # ]:        273 :     PTR_ENSURE_REF(builder->base_policy);
     163 [ -  + ][ #  # ]:        273 :     PTR_ENSURE_EQ(builder->base_policy->alloced, false);
     164                 :            : 
     165                 :        273 :     ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
     166                 :        273 :     return builder;
     167                 :        273 : }
     168                 :            : 
     169                 :            : int s2n_security_policy_builder_free(struct s2n_security_policy_builder **builder_ptr)
     170                 :        276 : {
     171         [ +  + ]:        276 :     if (!builder_ptr) {
     172                 :          1 :         return S2N_SUCCESS;
     173                 :          1 :     }
     174         [ -  + ]:        275 :     POSIX_GUARD(s2n_free_object((uint8_t **) builder_ptr, sizeof(struct s2n_security_policy_builder)));
     175                 :        275 :     return S2N_SUCCESS;
     176                 :        275 : }
     177                 :            : 
     178                 :            : /* For now, "build" just copies the input policy.
     179                 :            :  * We will add functionality later.
     180                 :            :  */
     181                 :            : struct s2n_security_policy *s2n_security_policy_build(struct s2n_security_policy_builder *builder)
     182                 :        138 : {
     183 [ +  + ][ +  - ]:        138 :     PTR_ENSURE(builder, S2N_ERR_INVALID_ARGUMENT);
     184                 :        137 :     struct s2n_security_policy *policy = NULL;
     185         [ -  + ]:        137 :     PTR_GUARD_RESULT(s2n_security_policy_copy(builder->base_policy, &policy));
     186 [ -  + ][ #  # ]:        137 :     PTR_ENSURE_REF(policy);
     187                 :        137 :     return policy;
     188                 :        137 : }

Generated by: LCOV version 1.14