123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- /*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
- #include "tls/s2n_signature_algorithms.h"
- #include "crypto/s2n_fips.h"
- #include "crypto/s2n_rsa_pss.h"
- #include "crypto/s2n_rsa_signing.h"
- #include "error/s2n_errno.h"
- #include "tls/s2n_auth_selection.h"
- #include "tls/s2n_cipher_suites.h"
- #include "tls/s2n_kex.h"
- #include "tls/s2n_security_policies.h"
- #include "tls/s2n_signature_scheme.h"
- #include "utils/s2n_safety.h"
- static S2N_RESULT s2n_signature_scheme_validate_for_send(struct s2n_connection *conn,
- const struct s2n_signature_scheme *scheme)
- {
- RESULT_ENSURE_REF(conn);
- /* If no protocol has been negotiated yet, the actual_protocol_version will
- * be equivalent to the client_protocol_version and represent the highest
- * version supported.
- */
- RESULT_ENSURE_GTE(conn->actual_protocol_version, scheme->minimum_protocol_version);
- /* QUIC only supports TLS1.3 */
- if (s2n_connection_is_quic_enabled(conn) && scheme->maximum_protocol_version) {
- RESULT_ENSURE_GTE(scheme->maximum_protocol_version, S2N_TLS13);
- }
- if (!s2n_is_rsa_pss_signing_supported()) {
- RESULT_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_RSAE);
- }
- if (!s2n_is_rsa_pss_certs_supported()) {
- RESULT_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_PSS);
- }
- return S2N_RESULT_OK;
- }
- static bool s2n_signature_scheme_is_valid_for_send(struct s2n_connection *conn,
- const struct s2n_signature_scheme *scheme)
- {
- return s2n_result_is_ok(s2n_signature_scheme_validate_for_send(conn, scheme));
- }
- static S2N_RESULT s2n_signature_scheme_validate_for_recv(struct s2n_connection *conn,
- const struct s2n_signature_scheme *scheme)
- {
- RESULT_ENSURE_REF(scheme);
- RESULT_ENSURE_REF(conn);
- RESULT_GUARD(s2n_signature_scheme_validate_for_send(conn, scheme));
- if (scheme->maximum_protocol_version != S2N_UNKNOWN_PROTOCOL_VERSION) {
- RESULT_ENSURE_LTE(conn->actual_protocol_version, scheme->maximum_protocol_version);
- }
- RESULT_ENSURE_NE(conn->actual_protocol_version, S2N_UNKNOWN_PROTOCOL_VERSION);
- if (conn->actual_protocol_version >= S2N_TLS13) {
- RESULT_ENSURE_NE(scheme->hash_alg, S2N_HASH_SHA1);
- RESULT_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA);
- } else {
- RESULT_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_PSS);
- }
- return S2N_RESULT_OK;
- }
- static bool s2n_signature_scheme_is_valid_for_recv(struct s2n_connection *conn,
- const struct s2n_signature_scheme *scheme)
- {
- return s2n_result_is_ok(s2n_signature_scheme_validate_for_recv(conn, scheme));
- }
- static int s2n_is_signature_scheme_usable(struct s2n_connection *conn, const struct s2n_signature_scheme *candidate)
- {
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(candidate);
- POSIX_GUARD_RESULT(s2n_signature_scheme_validate_for_recv(conn, candidate));
- POSIX_GUARD(s2n_is_sig_scheme_valid_for_auth(conn, candidate));
- return S2N_SUCCESS;
- }
- static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_scheme_list *peer_wire_prefs,
- const struct s2n_signature_scheme **chosen_scheme_out)
- {
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
- const struct s2n_signature_preferences *signature_preferences = NULL;
- POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- POSIX_ENSURE_REF(signature_preferences);
- struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
- POSIX_ENSURE_REF(cipher_suite);
- for (size_t i = 0; i < signature_preferences->count; i++) {
- const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
- if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) {
- continue;
- }
- for (size_t j = 0; j < peer_wire_prefs->len; j++) {
- uint16_t their_iana_val = peer_wire_prefs->iana_list[j];
- if (candidate->iana_value == their_iana_val) {
- *chosen_scheme_out = candidate;
- return S2N_SUCCESS;
- }
- }
- }
- /* do not error even if there's no match */
- return S2N_SUCCESS;
- }
- /* similar to s2n_choose_sig_scheme() without matching client's preference */
- int s2n_tls13_default_sig_scheme(struct s2n_connection *conn,
- const struct s2n_signature_scheme **chosen_scheme_out)
- {
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
- const struct s2n_signature_preferences *signature_preferences = NULL;
- POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- POSIX_ENSURE_REF(signature_preferences);
- struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
- POSIX_ENSURE_REF(cipher_suite);
- for (size_t i = 0; i < signature_preferences->count; i++) {
- const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
- if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) {
- continue;
- }
- *chosen_scheme_out = candidate;
- return S2N_SUCCESS;
- }
- POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_SCHEME);
- }
- static S2N_RESULT s2n_signature_algorithms_get_legacy_default(struct s2n_connection *conn,
- const struct s2n_signature_scheme **default_sig_scheme)
- {
- RESULT_ENSURE_REF(conn);
- RESULT_ENSURE_REF(default_sig_scheme);
- s2n_authentication_method auth_method = 0;
- if (conn->mode == S2N_SERVER) {
- RESULT_GUARD_POSIX(s2n_get_auth_method_for_cert_type(
- conn->handshake_params.client_cert_pkey_type, &auth_method));
- } else {
- RESULT_ENSURE_REF(conn->secure);
- RESULT_ENSURE_REF(conn->secure->cipher_suite);
- auth_method = conn->secure->cipher_suite->auth_method;
- }
- if (auth_method == S2N_AUTHENTICATION_ECDSA) {
- *default_sig_scheme = &s2n_ecdsa_sha1;
- } else {
- *default_sig_scheme = &s2n_rsa_pkcs1_md5_sha1;
- }
- return S2N_RESULT_OK;
- }
- S2N_RESULT s2n_signature_algorithm_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
- {
- RESULT_ENSURE_REF(conn);
- const struct s2n_signature_scheme **chosen_sig_scheme = NULL;
- if (conn->mode == S2N_SERVER) {
- chosen_sig_scheme = &conn->handshake_params.client_cert_sig_scheme;
- } else {
- chosen_sig_scheme = &conn->handshake_params.server_cert_sig_scheme;
- }
- /* Before TLS1.2, signature algorithms were fixed instead of negotiated */
- if (conn->actual_protocol_version < S2N_TLS12) {
- return s2n_signature_algorithms_get_legacy_default(conn, chosen_sig_scheme);
- }
- uint16_t iana_value = 0;
- RESULT_ENSURE(s2n_stuffer_read_uint16(in, &iana_value) == S2N_SUCCESS,
- S2N_ERR_BAD_MESSAGE);
- const struct s2n_signature_preferences *signature_preferences = NULL;
- RESULT_GUARD_POSIX(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- RESULT_ENSURE_REF(signature_preferences);
- for (size_t i = 0; i < signature_preferences->count; i++) {
- const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
- if (candidate->iana_value != iana_value) {
- continue;
- }
- if (!s2n_signature_scheme_is_valid_for_recv(conn, candidate)) {
- continue;
- }
- *chosen_sig_scheme = candidate;
- return S2N_RESULT_OK;
- }
- RESULT_BAIL(S2N_ERR_INVALID_SIGNATURE_SCHEME);
- }
- int s2n_choose_default_sig_scheme(struct s2n_connection *conn,
- const struct s2n_signature_scheme **sig_scheme_out, s2n_mode signer)
- {
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
- POSIX_ENSURE_REF(sig_scheme_out);
- s2n_authentication_method auth_method = 0;
- if (signer == S2N_CLIENT) {
- POSIX_GUARD(s2n_get_auth_method_for_cert_type(conn->handshake_params.client_cert_pkey_type, &auth_method));
- } else {
- POSIX_ENSURE_REF(conn->secure->cipher_suite);
- auth_method = conn->secure->cipher_suite->auth_method;
- }
- /* Default our signature digest algorithms.
- * For >=TLS 1.2 this default may be overridden by the signature_algorithms extension.
- */
- const struct s2n_signature_scheme *default_sig_scheme = &s2n_rsa_pkcs1_md5_sha1;
- if (auth_method == S2N_AUTHENTICATION_ECDSA) {
- default_sig_scheme = &s2n_ecdsa_sha1;
- } else if (conn->actual_protocol_version >= S2N_TLS12) {
- default_sig_scheme = &s2n_rsa_pkcs1_sha1;
- }
- if (conn->actual_protocol_version < S2N_TLS12) {
- /* Before TLS1.2, signature algorithms were fixed, not chosen / negotiated. */
- *sig_scheme_out = default_sig_scheme;
- return S2N_SUCCESS;
- } else {
- /* If we attempt to negotiate a default in TLS1.2, we should ensure that
- * default is allowed by the local security policy.
- */
- const struct s2n_signature_preferences *signature_preferences = NULL;
- POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- POSIX_ENSURE_REF(signature_preferences);
- for (size_t i = 0; i < signature_preferences->count; i++) {
- if (signature_preferences->signature_schemes[i]->iana_value == default_sig_scheme->iana_value) {
- *sig_scheme_out = default_sig_scheme;
- return S2N_SUCCESS;
- }
- }
- /* We cannot bail with an error here because existing logic assumes
- * that this method should always succeed and calls it even when no default
- * is actually necessary.
- * If no valid default exists, set an unusable, invalid empty scheme.
- */
- *sig_scheme_out = &s2n_null_sig_scheme;
- return S2N_SUCCESS;
- }
- }
- int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn,
- struct s2n_sig_scheme_list *peer_wire_prefs,
- const struct s2n_signature_scheme **sig_scheme_out)
- {
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(sig_scheme_out);
- const struct s2n_signature_scheme *chosen_scheme = &s2n_null_sig_scheme;
- if (conn->actual_protocol_version < S2N_TLS13) {
- POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &chosen_scheme, conn->mode));
- } else {
- /* Pick a default signature algorithm in TLS 1.3 https://tools.ietf.org/html/rfc8446#section-4.4.2.2 */
- POSIX_GUARD(s2n_tls13_default_sig_scheme(conn, &chosen_scheme));
- }
- /* SignatureScheme preference list was first added in TLS 1.2. It will be empty in older TLS versions. */
- if (conn->actual_protocol_version >= S2N_TLS12 && peer_wire_prefs != NULL && peer_wire_prefs->len > 0) {
- /* Use a best effort approach to selecting a signature scheme matching client's preferences */
- POSIX_GUARD(s2n_choose_sig_scheme(conn, peer_wire_prefs, &chosen_scheme));
- }
- *sig_scheme_out = chosen_scheme;
- return S2N_SUCCESS;
- }
- S2N_RESULT s2n_signature_algorithms_supported_list_send(struct s2n_connection *conn, struct s2n_stuffer *out)
- {
- const struct s2n_signature_preferences *signature_preferences = NULL;
- RESULT_GUARD_POSIX(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- RESULT_ENSURE_REF(signature_preferences);
- struct s2n_stuffer_reservation size = { 0 };
- RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint16(out, &size));
- for (size_t i = 0; i < signature_preferences->count; i++) {
- const struct s2n_signature_scheme *const scheme = signature_preferences->signature_schemes[i];
- RESULT_ENSURE_REF(scheme);
- if (s2n_signature_scheme_is_valid_for_send(conn, scheme)) {
- RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(out, scheme->iana_value));
- }
- }
- RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&size));
- return S2N_RESULT_OK;
- }
- int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_scheme_list *sig_hash_algs)
- {
- uint16_t length_of_all_pairs;
- POSIX_GUARD(s2n_stuffer_read_uint16(in, &length_of_all_pairs));
- if (length_of_all_pairs > s2n_stuffer_data_available(in)) {
- /* Malformed length, ignore the extension */
- return 0;
- }
- if (length_of_all_pairs % 2) {
- /* Pairs occur in two byte lengths. Malformed length, ignore the extension and skip ahead */
- POSIX_GUARD(s2n_stuffer_skip_read(in, length_of_all_pairs));
- return 0;
- }
- int pairs_available = length_of_all_pairs / 2;
- if (pairs_available > TLS_SIGNATURE_SCHEME_LIST_MAX_LEN) {
- POSIX_BAIL(S2N_ERR_TOO_MANY_SIGNATURE_SCHEMES);
- }
- sig_hash_algs->len = 0;
- for (size_t i = 0; i < (size_t) pairs_available; i++) {
- uint16_t sig_scheme = 0;
- POSIX_GUARD(s2n_stuffer_read_uint16(in, &sig_scheme));
- sig_hash_algs->iana_list[sig_hash_algs->len] = sig_scheme;
- sig_hash_algs->len += 1;
- }
- return 0;
- }
|