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_auth_selection.h" 17 : : 18 : : #include "crypto/s2n_certificate.h" 19 : : #include "crypto/s2n_signature.h" 20 : : #include "tls/s2n_cipher_suites.h" 21 : : #include "tls/s2n_kex.h" 22 : : #include "tls/s2n_signature_algorithms.h" 23 : : #include "utils/s2n_safety.h" 24 : : 25 : : /* This module should contain any logic related to choosing a valid combination of 26 : : * signature algorithm, authentication method, and certificate to use for authentication. 27 : : * 28 : : * We choose our auth methods by: 29 : : * 1. Finding a cipher suite with an auth method that we have valid certs for. In TLS1.3, 30 : : * this is a no-op -- cipher suites do not specify an auth method. 31 : : * 2. Choosing a signature algorithm that matches both the auth method (if set) and the 32 : : * available certs. 33 : : * 3. Selecting the cert that matches the chosen signature algorithm. 34 : : * 35 : : * This is a break from the original s2n pre-TLS1.3 flow, when we could choose certs and 36 : : * ciphers at the same time. Our cipher suites differentiate between "RSA" and "ECDSA", 37 : : * but not between "RSA" and "RSA-PSS". To make that decision, we need to wait until 38 : : * we've chosen a signature algorithm. This allows us to use RSA-PSS with existing 39 : : * TLS1.2 cipher suites. 40 : : */ 41 : : 42 : : int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authentication_method *auth_method) 43 : 14399 : { 44 [ - + ]: 14399 : switch (cert_type) { 45 [ + + ]: 8504 : case S2N_PKEY_TYPE_RSA: 46 [ + + ]: 10184 : case S2N_PKEY_TYPE_RSA_PSS: 47 : 10184 : *auth_method = S2N_AUTHENTICATION_RSA; 48 : 10184 : return S2N_SUCCESS; 49 [ + + ]: 2563 : case S2N_PKEY_TYPE_ECDSA: 50 : 2563 : *auth_method = S2N_AUTHENTICATION_ECDSA; 51 : 2563 : return S2N_SUCCESS; 52 [ + + ]: 1650 : case S2N_PKEY_TYPE_MLDSA: 53 [ + + ]: 1652 : case S2N_PKEY_TYPE_UNKNOWN: 54 [ - + ]: 1652 : case S2N_PKEY_TYPE_SENTINEL: 55 [ + - ]: 1652 : POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED); 56 : 14399 : } 57 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED); 58 : 0 : } 59 : : 60 : : static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg, struct s2n_cipher_suite *cipher_suite) 61 : 6960 : { 62 [ - + ][ # # ]: 6960 : POSIX_ENSURE_REF(cipher_suite); 63 : : 64 : 6960 : s2n_pkey_type cert_type_for_sig_alg = S2N_PKEY_TYPE_UNKNOWN; 65 [ - + ]: 6960 : POSIX_GUARD_RESULT(s2n_signature_algorithm_get_pkey_type(sig_alg, &cert_type_for_sig_alg)); 66 : : 67 : : /* Non-ephemeral key exchange methods require encryption, and RSA-PSS certificates 68 : : * do not support encryption. 69 : : * 70 : : * Therefore, if a cipher suite uses a non-ephemeral kex, then any signature 71 : : * algorithm that requires RSA-PSS certificates is not valid. 72 : : */ 73 : 6960 : const struct s2n_kex *kex = cipher_suite->key_exchange_alg; 74 [ - + ][ # # ]: 6960 : POSIX_ENSURE_REF(kex); 75 [ + + ]: 6960 : if (!kex->is_ephemeral) { 76 [ + + ][ + - ]: 1209 : POSIX_ENSURE_NE(cert_type_for_sig_alg, S2N_PKEY_TYPE_RSA_PSS); 77 : 1209 : } 78 : : 79 : : /* If a cipher suite includes an auth method, then the signature algorithm 80 : : * must match that auth method. 81 : : */ 82 [ + + ]: 6959 : if (cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) { 83 : 2596 : s2n_authentication_method auth_method_for_sig_alg = 0; 84 [ - + ]: 2596 : POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type_for_sig_alg, &auth_method_for_sig_alg)); 85 [ + + ][ + - ]: 2596 : POSIX_ENSURE_EQ(cipher_suite->auth_method, auth_method_for_sig_alg); 86 : 2596 : } 87 : : 88 : 6414 : return S2N_SUCCESS; 89 : 6959 : } 90 : : 91 : : static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme) 92 : 31743 : { 93 [ - + ][ # # ]: 31743 : POSIX_ENSURE_REF(sig_scheme); 94 : : 95 : 31743 : s2n_pkey_type cert_type = S2N_PKEY_TYPE_UNKNOWN; 96 [ - + ]: 31743 : POSIX_GUARD_RESULT(s2n_signature_algorithm_get_pkey_type(sig_scheme->sig_alg, &cert_type)); 97 : : /* A valid cert must exist for the authentication method. */ 98 : 31743 : struct s2n_cert_chain_and_key *cert = s2n_get_compatible_cert_chain_and_key(conn, cert_type); 99 [ + + ][ + - ]: 31743 : POSIX_ENSURE_REF(cert); 100 : : 101 : : /* In TLS 1.3, signature scheme may further restrict the certs */ 102 [ + + ]: 8139 : if (conn->actual_protocol_version >= S2N_TLS13) { 103 [ + + ][ + + ]: 5438 : if (cert_type == S2N_PKEY_TYPE_RSA || cert_type == S2N_PKEY_TYPE_RSA_PSS) { 104 : : /* a RSA cert is valid for any corresponding RSA signature scheme. For 105 : : * example an rsae cert can be used for both rsa_pss_rsae_sha256 106 : : * and rsa_pss_rsae_sha384 */ 107 : 3310 : return S2N_SUCCESS; 108 [ + - ]: 3310 : } else if (cert_type == S2N_PKEY_TYPE_ECDSA) { 109 : : /* TLS 1.3 ECDSA signatures schemes e.g. ecdsa_secp384r1_sha384 also specify 110 : : * a curve. We must make sure that the certificate has the correct curve */ 111 [ - + ][ # # ]: 2128 : POSIX_ENSURE_REF(cert->private_key); 112 [ # # ][ - + ]: 2128 : POSIX_ENSURE_REF(cert->cert_chain); 113 [ # # ][ - + ]: 2128 : POSIX_ENSURE_REF(cert->cert_chain->head); 114 [ - + ][ # # ]: 2128 : POSIX_ENSURE_EQ(cert->cert_chain->head->pkey_type, S2N_PKEY_TYPE_ECDSA); 115 [ + + ][ + - ]: 2128 : POSIX_ENSURE_EQ(cert->cert_chain->head->info.public_key_nid, sig_scheme->signature_curve->libcrypto_nid); 116 [ # # ]: 2128 : } else if (cert_type == S2N_PKEY_TYPE_MLDSA) { 117 : : /* ML-DSA signatures e.g. mldsa65 include a parameter set (65) which must match 118 : : * the cert. public_key_nid holds the specific ML-DSA NID (NID_MLDSA44/65/87) 119 : : * populated via EVP_PKEY_pqdsa_get_type() at cert-load time. */ 120 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(cert->private_key); 121 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(cert->cert_chain); 122 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(cert->cert_chain->head); 123 [ # # ][ # # ]: 0 : POSIX_ENSURE_EQ(cert->cert_chain->head->pkey_type, S2N_PKEY_TYPE_MLDSA); 124 [ # # ][ # # ]: 0 : POSIX_ENSURE_EQ(cert->cert_chain->head->info.public_key_nid, sig_scheme->libcrypto_nid); 125 : 0 : } else { 126 : : /* We expect any future signature schemes to also have these restrictions 127 : : * so we concretely fail here until they are properly handled */ 128 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); 129 : 0 : } 130 : 5438 : } 131 : : 132 : 3826 : return S2N_SUCCESS; 133 : 8139 : } 134 : : 135 : : static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method) 136 : 9659 : { 137 [ + + ]: 9659 : if (auth_method == S2N_AUTHENTICATION_METHOD_SENTINEL) { 138 : 5454 : return S2N_SUCCESS; 139 : 5454 : } 140 : : 141 : 4205 : s2n_authentication_method auth_method_for_cert_type = 0; 142 [ + - ]: 9511 : for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { 143 [ + + ]: 9511 : POSIX_GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type)); 144 : : 145 [ + + ]: 7861 : if (auth_method != auth_method_for_cert_type) { 146 : 2975 : continue; 147 : 2975 : } 148 : : 149 [ + + ]: 4886 : if (s2n_get_compatible_cert_chain_and_key(conn, i) != NULL) { 150 : 2555 : return S2N_SUCCESS; 151 : 2555 : } 152 : 4886 : } 153 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED); 154 : 0 : } 155 : : 156 : : /* TLS1.3 ciphers are always valid, as they don't include an auth method. 157 : : * 158 : : * A pre-TLS1.3 cipher suite is valid if: 159 : : * - At least one compatible cert is configured 160 : : * 161 : : * This method is called by the server when choosing a cipher suite. 162 : : */ 163 : : int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite) 164 : 9659 : { 165 [ - + ][ # # ]: 9659 : POSIX_ENSURE_REF(cipher_suite); 166 : : 167 [ + + ]: 9659 : POSIX_GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method)); 168 : : 169 : 8009 : return S2N_SUCCESS; 170 : 9659 : } 171 : : 172 : : /* A signature algorithm is valid if: 173 : : * - At least one compatible cert is configured. 174 : : * - The signature algorithm is allowed by the cipher suite's auth method 175 : : * (if running as a pre-TLS1.3 server). 176 : : * 177 : : * This method is called by the both server and client when choosing a signature algorithm. 178 : : */ 179 : : int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme) 180 : 31743 : { 181 [ - + ][ # # ]: 31743 : POSIX_ENSURE_REF(conn); 182 [ # # ][ - + ]: 31743 : POSIX_ENSURE_REF(conn->secure); 183 [ - + ][ # # ]: 31743 : POSIX_ENSURE_REF(sig_scheme); 184 : : 185 : 31743 : struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; 186 [ - + ][ # # ]: 31743 : POSIX_ENSURE_REF(cipher_suite); 187 : : 188 [ + + ]: 31743 : POSIX_GUARD(s2n_certs_exist_for_sig_scheme(conn, sig_scheme)); 189 : : 190 : : /* For the client side, signature algorithm does not need to match the cipher suite. */ 191 [ + + ]: 7136 : if (conn->mode == S2N_SERVER) { 192 [ + + ]: 6960 : POSIX_GUARD(s2n_is_sig_alg_valid_for_cipher_suite(sig_scheme->sig_alg, cipher_suite)); 193 : 6960 : } 194 : 6590 : return S2N_SUCCESS; 195 : 7136 : } 196 : : 197 : : /* A cert is valid if: 198 : : * - The configured cipher suite's auth method (if present) supports the cert. 199 : : * 200 : : * We could also verify that at least one of our supported sig algs 201 : : * supports the cert, but that seems unnecessary. If we don't have a valid 202 : : * sig alg, we'll fail on CertVerify. 203 : : * 204 : : * This method is called by the client when receiving the server's cert. 205 : : */ 206 : : int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type cert_type) 207 : 4837 : { 208 [ - + ][ # # ]: 4837 : POSIX_ENSURE_REF(conn); 209 [ - + ][ # # ]: 4837 : POSIX_ENSURE_REF(conn->secure); 210 [ - + ][ # # ]: 4837 : POSIX_ENSURE_REF(conn->secure->cipher_suite); 211 : 4837 : s2n_authentication_method conn_auth_method = conn->secure->cipher_suite->auth_method; 212 : : 213 : : /* TLS1.3 cipher suites do not specify an auth type */ 214 [ + + ]: 4837 : if (conn_auth_method == S2N_AUTHENTICATION_METHOD_SENTINEL) { 215 : 2550 : return S2N_SUCCESS; 216 : 2550 : } 217 : : 218 : 2287 : s2n_authentication_method cert_auth_method = 0; 219 [ + + ]: 2287 : POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type, &cert_auth_method)); 220 [ + + ][ + - ]: 2285 : POSIX_ENSURE(cert_auth_method == conn_auth_method, S2N_ERR_CERT_TYPE_UNSUPPORTED); 221 : 2282 : return S2N_SUCCESS; 222 : 2285 : } 223 : : 224 : : /* Choose the cert associated with our configured signature algorithm. 225 : : * 226 : : * This method is called by the server after configuring its cipher suite and sig algs. 227 : : */ 228 : : int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs) 229 : 6821 : { 230 [ - + ][ # # ]: 6821 : POSIX_ENSURE_REF(conn); 231 : 6821 : const struct s2n_signature_scheme *sig_scheme = conn->handshake_params.server_cert_sig_scheme; 232 [ - + ][ # # ]: 6821 : POSIX_ENSURE_REF(sig_scheme); 233 : 6821 : s2n_signature_algorithm sig_alg = sig_scheme->sig_alg; 234 : : 235 : 6821 : s2n_pkey_type cert_type = S2N_PKEY_TYPE_UNKNOWN; 236 [ + + ]: 6821 : if (sig_scheme == &s2n_null_sig_scheme) { 237 : : /* Only RSA auth (+ RSA kex) supports no signature scheme */ 238 : 341 : cert_type = S2N_PKEY_TYPE_RSA; 239 : 6480 : } else { 240 [ - + ]: 6480 : POSIX_GUARD_RESULT(s2n_signature_algorithm_get_pkey_type(sig_alg, &cert_type)); 241 : 6480 : } 242 : : 243 : 6821 : *chosen_certs = s2n_get_compatible_cert_chain_and_key(conn, cert_type); 244 [ + + ][ + - ]: 6821 : S2N_ERROR_IF(*chosen_certs == NULL, S2N_ERR_CERT_TYPE_UNSUPPORTED); 245 : : 246 : 6815 : return S2N_SUCCESS; 247 : 6821 : }