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

Generated by: LCOV version 1.14