aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/tls_handshake_state.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-12-21 15:37:39 -0500
committerJack Lloyd <[email protected]>2018-01-28 12:14:07 -0500
commitb2b55e6c2fdb824f49923b60d2c3ffff8f0fb99a (patch)
tree8d5650816329cbe176a4e1fee639094c9387b260 /src/lib/tls/tls_handshake_state.cpp
parent1c667d34bf71336d33bb76309176a993f13a2aac (diff)
Use enums to represent TLS signature and kex algorithms.
Adds support for PSS signatures (currently verifying only).
Diffstat (limited to 'src/lib/tls/tls_handshake_state.cpp')
-rw-r--r--src/lib/tls/tls_handshake_state.cpp213
1 files changed, 92 insertions, 121 deletions
diff --git a/src/lib/tls/tls_handshake_state.cpp b/src/lib/tls/tls_handshake_state.cpp
index 0fcf0d2ab..ab023834b 100644
--- a/src/lib/tls/tls_handshake_state.cpp
+++ b/src/lib/tls/tls_handshake_state.cpp
@@ -341,7 +341,7 @@ std::string Handshake_State::srp_identifier() const
{
#if defined(BOTAN_HAS_SRP6)
// Authenticated via the successful key exchange
- if(ciphersuite().valid() && ciphersuite().kex_algo() == "SRP_SHA")
+ if(ciphersuite().valid() && ciphersuite().kex_method() == Kex_Algo::SRP_SHA)
return client_hello()->srp_identifier();
#endif
@@ -373,93 +373,70 @@ KDF* Handshake_State::protocol_specific_prf() const
return get_kdf("TLS-PRF");
}
-namespace {
-
-std::string choose_hash(const std::string& sig_algo,
- std::vector<std::pair<std::string, std::string>>& supported_algos,
- Protocol_Version negotiated_version,
- const Policy& policy)
+std::pair<std::string, Signature_Format>
+Handshake_State::choose_sig_format(const Private_Key& key,
+ Signature_Scheme& chosen_scheme,
+ bool for_client_auth,
+ const Policy& policy) const
{
- if(!negotiated_version.supports_negotiable_signature_algorithms())
- {
- if(sig_algo == "RSA")
- return "Parallel(MD5,SHA-160)";
+ const std::string sig_algo = key.algo_name();
- if(sig_algo == "DSA")
- return "SHA-1";
+ if(this->version().supports_negotiable_signature_algorithms())
+ {
+ const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes();
- if(sig_algo == "ECDSA")
- return "SHA-1";
+ std::vector<Signature_Scheme> schemes =
+ (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes();
- throw Internal_Error("Unknown TLS signature algo " + sig_algo);
- }
-
- if(!supported_algos.empty())
- {
- const std::vector<std::string> hashes = policy.allowed_signature_hashes();
+ if(schemes.empty())
+ {
+ // Implicit SHA-1
+ schemes.push_back(Signature_Scheme::RSA_PKCS1_SHA1);
+ schemes.push_back(Signature_Scheme::ECDSA_SHA1);
+ schemes.push_back(Signature_Scheme::DSA_SHA1);
+ }
- /*
- * Choose our most preferred hash that the counterparty supports
- * in pairing with the signature algorithm we want to use.
- */
- for(std::string hash : hashes)
+ for(Signature_Scheme scheme : schemes)
{
- for(auto algo : supported_algos)
+ if(signature_algorithm_of_scheme(scheme) == sig_algo)
{
- if(algo.first == hash && algo.second == sig_algo)
- return hash;
+ if(std::find(allowed.begin(), allowed.end(), scheme) != allowed.end())
+ {
+ chosen_scheme = scheme;
+ break;
+ }
}
}
- }
- // TLS v1.2 default hash if the counterparty sent nothing
- return "SHA-1";
- }
+ const std::string hash = hash_function_of_scheme(chosen_scheme);
-}
-
-std::pair<std::string, Signature_Format>
-Handshake_State::choose_sig_format(const Private_Key& key,
- std::string& hash_algo_out,
- std::string& sig_algo_out,
- bool for_client_auth,
- const Policy& policy) const
- {
- const std::string sig_algo = key.algo_name();
-
- std::vector<std::pair<std::string, std::string>> supported_algos =
- (for_client_auth) ? cert_req()->supported_algos() : client_hello()->supported_algos();
-
- const std::string hash_algo = choose_hash(sig_algo,
- supported_algos,
- this->version(),
- policy);
-
- if(this->version().supports_negotiable_signature_algorithms())
- {
- // We skip this check for v1.0 since you're stuck with SHA-1 regardless
-
- if(!policy.allowed_signature_hash(hash_algo))
+ if(!policy.allowed_signature_hash(hash))
{
throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
"Policy refuses to accept signing with any hash supported by peer");
}
- hash_algo_out = hash_algo;
- sig_algo_out = sig_algo;
- }
-
- if(sig_algo == "RSA")
- {
- const std::string padding = "EMSA3(" + hash_algo + ")";
-
- return std::make_pair(padding, IEEE_1363);
+ if(sig_algo == "RSA")
+ {
+ return std::make_pair(padding_string_for_scheme(chosen_scheme), IEEE_1363);
+ }
+ else if(sig_algo == "DSA" || sig_algo == "ECDSA")
+ {
+ return std::make_pair(padding_string_for_scheme(chosen_scheme), DER_SEQUENCE);
+ }
}
- else if(sig_algo == "DSA" || sig_algo == "ECDSA")
+ else
{
- const std::string padding = "EMSA1(" + hash_algo + ")";
-
- return std::make_pair(padding, DER_SEQUENCE);
+ if(sig_algo == "RSA")
+ {
+ const std::string padding = "EMSA3(Parallel(MD5,SHA-160))";
+ return std::make_pair(padding, IEEE_1363);
+ }
+ else if(sig_algo == "DSA" || sig_algo == "ECDSA")
+ {
+ const std::string padding = "EMSA1(SHA-1)";
+ return std::make_pair(padding, DER_SEQUENCE);
+ }
}
throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures");
@@ -468,13 +445,14 @@ Handshake_State::choose_sig_format(const Private_Key& key,
namespace {
bool supported_algos_include(
- const std::vector<std::pair<std::string, std::string>>& algos,
+ const std::vector<Signature_Scheme>& schemes,
const std::string& key_type,
const std::string& hash_type)
{
- for(auto&& algo : algos)
+ for(Signature_Scheme scheme : schemes)
{
- if(algo.first == hash_type && algo.second == key_type)
+ if(hash_function_of_scheme(scheme) == hash_type &&
+ signature_algorithm_of_scheme(scheme) == key_type)
{
return true;
}
@@ -487,8 +465,7 @@ bool supported_algos_include(
std::pair<std::string, Signature_Format>
Handshake_State::parse_sig_format(const Public_Key& key,
- const std::string& input_hash_algo,
- const std::string& input_sig_algo,
+ Signature_Scheme scheme,
bool for_client_auth,
const Policy& policy) const
{
@@ -500,73 +477,67 @@ Handshake_State::parse_sig_format(const Public_Key& key,
"Rejecting " + key_type + " signature");
}
- std::string hash_algo;
-
- if(this->version().supports_negotiable_signature_algorithms())
+ if(this->version().supports_negotiable_signature_algorithms() == false)
{
- if(input_sig_algo != key_type)
- throw Decoding_Error("Counterparty sent inconsistent key and sig types");
-
- if(input_hash_algo == "")
- throw Decoding_Error("Counterparty did not send hash/sig IDS");
-
- hash_algo = input_hash_algo;
-
- if(for_client_auth && !cert_req())
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "No certificate verify set");
- }
+ if(scheme != Signature_Scheme::NONE)
+ throw Decoding_Error("Counterparty sent hash/sig IDs with old version");
/*
- Confirm the signature type we just received against the
- supported_algos list that we sent; it better be there.
+ There is no check on the acceptability of a v1.0/v1.1 hash type,
+ since it's implicit with use of the protocol
*/
- const auto supported_algos =
- for_client_auth ? cert_req()->supported_algos() :
- client_hello()->supported_algos();
-
- if(!supported_algos_include(supported_algos, key_type, hash_algo))
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "TLS signature extension did not allow for " +
- key_type + "/" + hash_algo + " signature");
- }
- }
- else
- {
- if(input_hash_algo != "" || input_sig_algo != "")
- throw Decoding_Error("Counterparty sent hash/sig IDs with old version");
-
if(key_type == "RSA")
{
- hash_algo = "Parallel(MD5,SHA-160)";
+ const std::string padding = "EMSA3(Parallel(MD5,SHA-160))";
+ return std::make_pair(padding, IEEE_1363);
}
else if(key_type == "DSA" || key_type == "ECDSA")
{
- hash_algo = "SHA-1";
+ const std::string padding = "EMSA1(SHA-1)";
+ return std::make_pair(padding, DER_SEQUENCE);
}
else
- {
throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures");
- }
+ }
- /*
- There is no check on the acceptability of a v1.0/v1.1 hash type,
- since it's implicit with use of the protocol
- */
+ if(scheme == Signature_Scheme::NONE)
+ throw Decoding_Error("Counterparty did not send hash/sig IDS");
+
+ if(key_type != signature_algorithm_of_scheme(scheme))
+ throw Decoding_Error("Counterparty sent inconsistent key and sig types");
+
+ if(for_client_auth && !cert_req())
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "No certificate verify set");
+ }
+
+ /*
+ Confirm the signature type we just received against the
+ supported_algos list that we sent; it better be there.
+ */
+
+ const std::vector<Signature_Scheme> supported_algos =
+ for_client_auth ? cert_req()->signature_schemes() :
+ client_hello()->signature_schemes();
+
+ const std::string hash_algo = hash_function_of_scheme(scheme);
+
+ if(!supported_algos_include(supported_algos, key_type, hash_algo))
+ {
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "TLS signature extension did not allow for " +
+ key_type + "/" + hash_algo + " signature");
}
if(key_type == "RSA")
{
- const std::string padding = "EMSA3(" + hash_algo + ")";
- return std::make_pair(padding, IEEE_1363);
+ return std::make_pair(padding_string_for_scheme(scheme), IEEE_1363);
}
else if(key_type == "DSA" || key_type == "ECDSA")
{
- const std::string padding = "EMSA1(" + hash_algo + ")";
- return std::make_pair(padding, DER_SEQUENCE);
+ return std::make_pair(padding_string_for_scheme(scheme), DER_SEQUENCE);
}
throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures");