LCOV - code coverage report
Current view: top level - crypto - s2n_fips_rules.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 71 72 98.6 %
Date: 2025-08-15 07:28:39 Functions: 7 7 100.0 %
Branches: 47 70 67.1 %

           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 "crypto/s2n_fips.h"
      17                 :            : #include "tls/s2n_cipher_suites.h"
      18                 :            : #include "tls/s2n_tls_parameters.h"
      19                 :            : #include "utils/s2n_result.h"
      20                 :            : 
      21                 :            : /* FIPS requires at least 112 bits of security.
      22                 :            :  * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-107r1.pdf */
      23                 :            : const s2n_hash_algorithm fips_hash_algs[] = {
      24                 :            :     S2N_HASH_SHA224,
      25                 :            :     S2N_HASH_SHA256,
      26                 :            :     S2N_HASH_SHA384,
      27                 :            :     S2N_HASH_SHA512,
      28                 :            : };
      29                 :            : S2N_RESULT s2n_fips_validate_hash_algorithm(s2n_hash_algorithm hash_alg, bool *valid)
      30                 :        258 : {
      31 [ +  + ][ +  - ]:        258 :     RESULT_ENSURE_REF(valid);
      32                 :        257 :     *valid = false;
      33         [ +  + ]:        755 :     for (size_t i = 0; i < s2n_array_len(fips_hash_algs); i++) {
      34         [ +  + ]:        745 :         if (fips_hash_algs[i] == hash_alg) {
      35                 :        247 :             *valid = true;
      36                 :        247 :             return S2N_RESULT_OK;
      37                 :        247 :         }
      38                 :        745 :     }
      39                 :         10 :     return S2N_RESULT_OK;
      40                 :        257 : }
      41                 :            : 
      42                 :            : /* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf */
      43                 :            : const uint8_t fips_cipher_suite_ianas[][2] = {
      44                 :            :     /* 3.3.1.1.1 Cipher Suites for ECDSA Certificates */
      45                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 },
      46                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 },
      47                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 },
      48                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 },
      49                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA },
      50                 :            :     { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA },
      51                 :            : 
      52                 :            :     /* 3.3.1.1.2 Cipher Suites for RSA Certificates */
      53                 :            :     { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 },
      54                 :            :     { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 },
      55                 :            :     { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 },
      56                 :            :     { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 },
      57                 :            :     { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 },
      58                 :            :     { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 },
      59                 :            :     { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 },
      60                 :            :     { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 },
      61                 :            :     { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA },
      62                 :            :     { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA },
      63                 :            :     { TLS_DHE_RSA_WITH_AES_128_CBC_SHA },
      64                 :            :     { TLS_DHE_RSA_WITH_AES_256_CBC_SHA },
      65                 :            : 
      66                 :            :     /* 3.3.1.2 Cipher Suites for TLS 1.3 */
      67                 :            :     { TLS_AES_128_GCM_SHA256 },
      68                 :            :     { TLS_AES_256_GCM_SHA384 },
      69                 :            : };
      70                 :            : 
      71                 :            : S2N_RESULT s2n_fips_validate_cipher_suite(const struct s2n_cipher_suite *cipher_suite, bool *valid)
      72                 :        151 : {
      73 [ +  - ][ +  + ]:        151 :     RESULT_ENSURE_REF(cipher_suite);
      74 [ +  + ][ +  - ]:        150 :     RESULT_ENSURE_REF(valid);
      75                 :            : 
      76                 :        149 :     *valid = false;
      77         [ +  + ]:       1607 :     for (size_t i = 0; i < s2n_array_len(fips_cipher_suite_ianas); i++) {
      78         [ +  + ]:       1588 :         if (fips_cipher_suite_ianas[i][0] != cipher_suite->iana_value[0]) {
      79                 :        822 :             continue;
      80                 :        822 :         }
      81         [ +  + ]:        766 :         if (fips_cipher_suite_ianas[i][1] != cipher_suite->iana_value[1]) {
      82                 :        636 :             continue;
      83                 :        636 :         }
      84                 :        130 :         *valid = true;
      85                 :        130 :         return S2N_RESULT_OK;
      86                 :        766 :     }
      87                 :         19 :     return S2N_RESULT_OK;
      88                 :        149 : }
      89                 :            : 
      90                 :            : S2N_RESULT s2n_fips_validate_signature_scheme(const struct s2n_signature_scheme *sig_alg, bool *valid)
      91                 :        239 : {
      92 [ +  - ][ +  + ]:        239 :     RESULT_ENSURE_REF(sig_alg);
      93         [ +  + ]:        238 :     RESULT_GUARD(s2n_fips_validate_hash_algorithm(sig_alg->hash_alg, valid));
      94                 :        237 :     return S2N_RESULT_OK;
      95                 :        238 : }
      96                 :            : 
      97                 :            : /* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf */
      98                 :            : const struct s2n_ecc_named_curve *fips_curves[] = {
      99                 :            :     &s2n_ecc_curve_secp256r1,
     100                 :            :     &s2n_ecc_curve_secp384r1,
     101                 :            :     &s2n_ecc_curve_secp521r1,
     102                 :            : };
     103                 :            : S2N_RESULT s2n_fips_validate_curve(const struct s2n_ecc_named_curve *curve, bool *valid)
     104                 :         48 : {
     105 [ +  - ][ +  + ]:         48 :     RESULT_ENSURE_REF(curve);
     106 [ +  + ][ +  - ]:         47 :     RESULT_ENSURE_REF(valid);
     107                 :         46 :     *valid = false;
     108         [ +  + ]:         90 :     for (size_t i = 0; i < s2n_array_len(fips_curves); i++) {
     109         [ +  + ]:         88 :         if (fips_curves[i] == curve) {
     110                 :         44 :             *valid = true;
     111                 :         44 :             return S2N_RESULT_OK;
     112                 :         44 :         }
     113                 :         88 :     }
     114                 :          2 :     return S2N_RESULT_OK;
     115                 :         46 : }
     116                 :            : 
     117                 :            : /* https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf */
     118                 :            : const struct s2n_kem *fips_kems[] = {
     119                 :            :     &s2n_mlkem_768,
     120                 :            :     &s2n_mlkem_1024
     121                 :            : };
     122                 :            : 
     123                 :            : S2N_RESULT s2n_fips_validate_kem(const struct s2n_kem *kem, bool *valid)
     124                 :          1 : {
     125 [ -  + ][ #  # ]:          1 :     RESULT_ENSURE_REF(kem);
     126 [ #  # ][ -  + ]:          1 :     RESULT_ENSURE_REF(valid);
     127                 :          1 :     *valid = false;
     128                 :            : 
     129         [ +  - ]:          1 :     for (size_t i = 0; i < s2n_array_len(fips_kems); i++) {
     130         [ +  - ]:          1 :         if (fips_kems[i] == kem) {
     131                 :          1 :             *valid = true;
     132                 :          1 :             return S2N_RESULT_OK;
     133                 :          1 :         }
     134                 :          1 :     }
     135                 :          0 :     return S2N_RESULT_OK;
     136                 :          1 : }
     137                 :            : 
     138                 :            : S2N_RESULT s2n_fips_validate_hybrid_group(const struct s2n_kem_group *hybrid_group, bool *valid)
     139                 :         10 : {
     140 [ -  + ][ #  # ]:         10 :     RESULT_ENSURE_REF(hybrid_group);
     141 [ -  + ][ #  # ]:         10 :     RESULT_ENSURE_REF(valid);
     142                 :         10 :     *valid = false;
     143                 :            : 
     144                 :            :     /* The first share in a Hybrid Group must be FIPS-approved, see page 33 of NIST 800-56Cr2.
     145                 :            :      *
     146                 :            :      * "Recommendation is expanded to permit the use of “hybrid” shared secrets of the form Z' = Z || T,
     147                 :            :      * which is a concatenation consisting of a “standard” shared secret Z that was generated during the
     148                 :            :      * execution of a key-establishment scheme as currently specified in [SP 800-56A] or [SP 800-56B],
     149                 :            :      * followed by an auxiliary shared secret T that has been generated using some other method."
     150                 :            :      *
     151                 :            :      * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf
     152                 :            :      */
     153         [ +  + ]:         10 :     if (hybrid_group->send_kem_first) {
     154         [ -  + ]:          1 :         RESULT_GUARD(s2n_fips_validate_kem(hybrid_group->kem, valid));
     155                 :          9 :     } else {
     156         [ -  + ]:          9 :         RESULT_GUARD(s2n_fips_validate_curve(hybrid_group->curve, valid));
     157                 :          9 :     }
     158                 :            : 
     159                 :         10 :     return S2N_RESULT_OK;
     160                 :         10 : }
     161                 :            : 
     162                 :            : S2N_RESULT s2n_fips_validate_version(uint8_t version, bool *valid)
     163                 :        276 : {
     164 [ +  + ][ +  - ]:        276 :     RESULT_ENSURE_REF(valid);
     165                 :            :     /* Technically FIPS 140-3 still allows TLS1.0 and TLS1.1 for some use cases,
     166                 :            :      * but for simplicity s2n-tls does not.
     167                 :            :      */
     168                 :        275 :     *valid = (version >= S2N_TLS12);
     169                 :        275 :     return S2N_RESULT_OK;
     170                 :        276 : }

Generated by: LCOV version 1.14