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