s2n_auth_selection.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. #include "tls/s2n_auth_selection.h"
  16. #include "crypto/s2n_certificate.h"
  17. #include "crypto/s2n_ecdsa.h"
  18. #include "crypto/s2n_signature.h"
  19. #include "tls/s2n_cipher_suites.h"
  20. #include "tls/s2n_kex.h"
  21. #include "utils/s2n_safety.h"
  22. /* This module should contain any logic related to choosing a valid combination of
  23. * signature algorithm, authentication method, and certificate to use for authentication.
  24. *
  25. * We choose our auth methods by:
  26. * 1. Finding a cipher suite with an auth method that we have valid certs for. In TLS1.3,
  27. * this is a no-op -- cipher suites do not specify an auth method.
  28. * 2. Choosing a signature algorithm that matches both the auth method (if set) and the
  29. * available certs.
  30. * 3. Selecting the cert that matches the chosen signature algorithm.
  31. *
  32. * This is a break from the original s2n pre-TLS1.3 flow, when we could choose certs and
  33. * ciphers at the same time. Our cipher suites differentiate between "RSA" and "ECDSA",
  34. * but not between "RSA" and "RSA-PSS". To make that decision, we need to wait until
  35. * we've chosen a signature algorithm. This allows us to use RSA-PSS with existing
  36. * TLS1.2 cipher suites.
  37. */
  38. int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authentication_method *auth_method)
  39. {
  40. switch (cert_type) {
  41. case S2N_PKEY_TYPE_RSA:
  42. case S2N_PKEY_TYPE_RSA_PSS:
  43. *auth_method = S2N_AUTHENTICATION_RSA;
  44. return S2N_SUCCESS;
  45. case S2N_PKEY_TYPE_ECDSA:
  46. *auth_method = S2N_AUTHENTICATION_ECDSA;
  47. return S2N_SUCCESS;
  48. case S2N_PKEY_TYPE_UNKNOWN:
  49. case S2N_PKEY_TYPE_SENTINEL:
  50. POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
  51. }
  52. POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
  53. }
  54. static int s2n_get_cert_type_for_sig_alg(s2n_signature_algorithm sig_alg, s2n_pkey_type *cert_type)
  55. {
  56. switch (sig_alg) {
  57. case S2N_SIGNATURE_RSA_PSS_RSAE:
  58. case S2N_SIGNATURE_RSA:
  59. *cert_type = S2N_PKEY_TYPE_RSA;
  60. return S2N_SUCCESS;
  61. case S2N_SIGNATURE_ECDSA:
  62. *cert_type = S2N_PKEY_TYPE_ECDSA;
  63. return S2N_SUCCESS;
  64. case S2N_SIGNATURE_RSA_PSS_PSS:
  65. *cert_type = S2N_PKEY_TYPE_RSA_PSS;
  66. return S2N_SUCCESS;
  67. case S2N_SIGNATURE_ANONYMOUS:
  68. POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
  69. }
  70. POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
  71. }
  72. static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg, struct s2n_cipher_suite *cipher_suite)
  73. {
  74. POSIX_ENSURE_REF(cipher_suite);
  75. s2n_pkey_type cert_type_for_sig_alg;
  76. POSIX_GUARD(s2n_get_cert_type_for_sig_alg(sig_alg, &cert_type_for_sig_alg));
  77. /* Non-ephemeral key exchange methods require encryption, and RSA-PSS certificates
  78. * do not support encryption.
  79. *
  80. * Therefore, if a cipher suite uses a non-ephemeral kex, then any signature
  81. * algorithm that requires RSA-PSS certificates is not valid.
  82. */
  83. if (cipher_suite->key_exchange_alg != NULL && !cipher_suite->key_exchange_alg->is_ephemeral) {
  84. POSIX_ENSURE_NE(cert_type_for_sig_alg, S2N_PKEY_TYPE_RSA_PSS);
  85. }
  86. /* If a cipher suite includes an auth method, then the signature algorithm
  87. * must match that auth method.
  88. */
  89. if (cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) {
  90. s2n_authentication_method auth_method_for_sig_alg;
  91. POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type_for_sig_alg, &auth_method_for_sig_alg));
  92. POSIX_ENSURE_EQ(cipher_suite->auth_method, auth_method_for_sig_alg);
  93. }
  94. return S2N_SUCCESS;
  95. }
  96. static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme)
  97. {
  98. POSIX_ENSURE_REF(sig_scheme);
  99. s2n_pkey_type cert_type;
  100. POSIX_GUARD(s2n_get_cert_type_for_sig_alg(sig_scheme->sig_alg, &cert_type));
  101. /* A valid cert must exist for the authentication method. */
  102. struct s2n_cert_chain_and_key *cert = s2n_get_compatible_cert_chain_and_key(conn, cert_type);
  103. POSIX_ENSURE_REF(cert);
  104. /* For sig_algs that include a curve, the group must also match. */
  105. if (sig_scheme->signature_curve != NULL) {
  106. POSIX_ENSURE_REF(cert->private_key);
  107. POSIX_ENSURE_REF(cert->cert_chain);
  108. POSIX_ENSURE_REF(cert->cert_chain->head);
  109. POSIX_ENSURE_EQ(cert->cert_chain->head->pkey_type, S2N_PKEY_TYPE_ECDSA);
  110. POSIX_ENSURE_EQ(cert->cert_chain->head->ec_curve_nid, sig_scheme->signature_curve->libcrypto_nid);
  111. }
  112. return S2N_SUCCESS;
  113. }
  114. static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method)
  115. {
  116. if (auth_method == S2N_AUTHENTICATION_METHOD_SENTINEL) {
  117. return S2N_SUCCESS;
  118. }
  119. s2n_authentication_method auth_method_for_cert_type;
  120. for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
  121. POSIX_GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type));
  122. if (auth_method != auth_method_for_cert_type) {
  123. continue;
  124. }
  125. if (s2n_get_compatible_cert_chain_and_key(conn, i) != NULL) {
  126. return S2N_SUCCESS;
  127. }
  128. }
  129. POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
  130. }
  131. /* TLS1.3 ciphers are always valid, as they don't include an auth method.
  132. *
  133. * A pre-TLS1.3 cipher suite is valid if:
  134. * - At least one compatible cert is configured
  135. *
  136. * This method is called by the server when choosing a cipher suite.
  137. */
  138. int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite)
  139. {
  140. POSIX_ENSURE_REF(cipher_suite);
  141. POSIX_GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method));
  142. return S2N_SUCCESS;
  143. }
  144. /* A signature algorithm is valid if:
  145. * - At least one compatible cert is configured.
  146. * - The signature algorithm is allowed by the cipher suite's auth method
  147. * (if running as a pre-TLS1.3 server).
  148. *
  149. * This method is called by the both server and client when choosing a signature algorithm.
  150. */
  151. int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme)
  152. {
  153. POSIX_ENSURE_REF(conn);
  154. POSIX_ENSURE_REF(conn->secure);
  155. POSIX_ENSURE_REF(sig_scheme);
  156. struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
  157. POSIX_ENSURE_REF(cipher_suite);
  158. POSIX_GUARD(s2n_certs_exist_for_sig_scheme(conn, sig_scheme));
  159. /* For the client side, signature algorithm does not need to match the cipher suite. */
  160. if (conn->mode == S2N_SERVER) {
  161. POSIX_GUARD(s2n_is_sig_alg_valid_for_cipher_suite(sig_scheme->sig_alg, cipher_suite));
  162. }
  163. return S2N_SUCCESS;
  164. }
  165. /* A cert is valid if:
  166. * - The configured cipher suite's auth method (if present) supports the cert.
  167. *
  168. * We could also verify that at least one of our supported sig algs
  169. * supports the cert, but that seems unnecessary. If we don't have a valid
  170. * sig alg, we'll fail on CertVerify.
  171. *
  172. * This method is called by the client when receiving the server's cert.
  173. */
  174. int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type cert_type)
  175. {
  176. POSIX_ENSURE_REF(conn);
  177. POSIX_ENSURE_REF(conn->secure);
  178. POSIX_ENSURE_REF(conn->secure->cipher_suite);
  179. s2n_authentication_method auth_method;
  180. POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type, &auth_method));
  181. if (conn->secure->cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) {
  182. S2N_ERROR_IF(auth_method != conn->secure->cipher_suite->auth_method, S2N_ERR_CERT_TYPE_UNSUPPORTED);
  183. }
  184. return S2N_SUCCESS;
  185. }
  186. /* Choose the cert associated with our configured signature algorithm.
  187. *
  188. * This method is called by the server after configuring its cipher suite and sig algs.
  189. */
  190. int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs)
  191. {
  192. POSIX_ENSURE_REF(conn);
  193. POSIX_ENSURE_REF(conn->handshake_params.server_cert_sig_scheme);
  194. s2n_signature_algorithm sig_alg = conn->handshake_params.server_cert_sig_scheme->sig_alg;
  195. s2n_pkey_type cert_type = 0;
  196. POSIX_GUARD(s2n_get_cert_type_for_sig_alg(sig_alg, &cert_type));
  197. *chosen_certs = s2n_get_compatible_cert_chain_and_key(conn, cert_type);
  198. S2N_ERROR_IF(*chosen_certs == NULL, S2N_ERR_CERT_TYPE_UNSUPPORTED);
  199. return S2N_SUCCESS;
  200. }