Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS 1.2 Refactoring #2808

Merged
merged 2 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/bogo_shim/bogo_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ std::string map_to_bogo_error(const std::string& e)
{ "Certificate key type did not match ciphersuite", ":WRONG_CERTIFICATE_TYPE:" },
{ "Certificate usage constraints do not allow this ciphersuite", ":KEY_USAGE_BIT_INCORRECT:" },
{ "Certificate: Message malformed", ":DECODE_ERROR:" },
{ "Channel::key_material_export cannot export during renegotiation", "failed to export keying material" },
{ "Channel_Impl_12::key_material_export cannot export during renegotiation", "failed to export keying material" },
{ "Client cert verify failed", ":BAD_SIGNATURE:" },
{ "Client certificate does not support signing", ":KEY_USAGE_BIT_INCORRECT:" },
{ "Client did not offer NULL compression", ":INVALID_COMPRESSION_LIST:" },
Expand Down Expand Up @@ -1529,7 +1529,9 @@ int main(int /*argc*/, char* argv[])

for(size_t i = 0; i != resume_count+1; ++i)
{
Shim_Socket socket("localhost", port);

auto execute_test = [&](const std::string& hostname) {
Shim_Socket socket(hostname, port);

shim_log("Connection " + std::to_string(i+1) + "/" + std::to_string(resume_count+1));

Expand All @@ -1547,7 +1549,7 @@ int main(int /*argc*/, char* argv[])
Botan::TLS::Protocol_Version offer_version = policy.latest_supported_version(is_datagram);
shim_log("Offering " + offer_version.to_string());

std::string host_name = args->get_string_opt_or_else("host-name", "localhost");
std::string host_name = args->get_string_opt_or_else("host-name", hostname);
if(args->test_name().find("UnsolicitedServerNameAck") == 0)
host_name = ""; // avoid sending SNI for this test

Expand Down Expand Up @@ -1642,8 +1644,23 @@ int main(int /*argc*/, char* argv[])
" exp " + std::to_string(exp));
}
shim_log("End of resume loop");
};
try
{
execute_test("localhost");
}
catch (const Shim_Exception& e)
{
if (std::string(e.what()) == "Failed to connect to host")
{
execute_test("::1");
}
else
{
throw e;
}
}
}

}
catch(Shim_Exception& e)
{
Expand Down
13 changes: 12 additions & 1 deletion src/lib/tls/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,23 @@ tls_version.h
</header:public>

<header:internal>
msg_client_hello_impl.h
msg_certificate_impl.h
msg_cert_verify_impl.h
msg_cert_req_impl.h
msg_finished_impl.h
msg_server_hello_impl.h
tls_channel_impl.h
tls_client_impl.h
tls_handshake_hash.h
tls_handshake_io.h
tls_handshake_state.h
tls_reader.h
tls_record.h
tls_server_impl.h
tls_seq_numbers.h
tls_session_key.h
tls_message_factory.h
tls_mock_msg_impl_13.h
</header:internal>

<requires>
Expand All @@ -49,5 +59,6 @@ rng
rsa
sha2_32
sha2_64
tls12
x509
</requires>
121 changes: 26 additions & 95 deletions src/lib/tls/msg_cert_req.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Certificate Request Message
* (C) 2004-2006,2012 Jack Lloyd
* 2021 Elektrobit Automotive GmbH
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
Expand All @@ -10,136 +11,66 @@
#include <botan/internal/tls_reader.h>
#include <botan/internal/tls_handshake_io.h>
#include <botan/internal/tls_handshake_hash.h>
#include <botan/internal/tls_message_factory.h>
#include <botan/internal/msg_cert_req_impl_12.h>
#include <botan/internal/msg_cert_req_impl.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>

namespace Botan {

namespace TLS {

namespace {

std::string cert_type_code_to_name(uint8_t code)
Handshake_Type Certificate_Req::type() const
{
switch(code)
{
case 1:
return "RSA";
case 2:
return "DSA";
case 64:
return "ECDSA";
default:
return ""; // DH or something else
}
return m_impl->type();
}

uint8_t cert_type_name_to_code(const std::string& name)
const std::vector<std::string>& Certificate_Req::acceptable_cert_types() const
{
if(name == "RSA")
return 1;
if(name == "DSA")
return 2;
if(name == "ECDSA")
return 64;
return m_impl->acceptable_cert_types();
}

throw Invalid_Argument("Unknown cert type " + name);
const std::vector<X509_DN>& Certificate_Req::acceptable_CAs() const
{
return m_impl->acceptable_CAs();
}

}
const std::vector<Signature_Scheme>& Certificate_Req::signature_schemes() const
{
return m_impl->signature_schemes();
}

/**
* Create a new Certificate Request message
*/
Certificate_Req::Certificate_Req(Handshake_IO& io,
Certificate_Req::Certificate_Req(const Protocol_Version& protocol_version,
Handshake_IO& io,
Handshake_Hash& hash,
const Policy& policy,
const std::vector<X509_DN>& ca_certs) :
m_names(ca_certs),
m_cert_key_types({ "RSA", "ECDSA", "DSA" })
m_impl(Message_Factory::create<Certificate_Req_Impl>(protocol_version, io, hash, policy, ca_certs))
{
m_schemes = policy.acceptable_signature_schemes();
hash.update(io.send(*this));
}

/**
* Deserialize a Certificate Request message
*/
Certificate_Req::Certificate_Req(const std::vector<uint8_t>& buf)
Certificate_Req::Certificate_Req(const Protocol_Version& protocol_version, const std::vector<uint8_t>& buf) :
m_impl(Message_Factory::create<Certificate_Req_Impl>(protocol_version, buf))
{
if(buf.size() < 4)
throw Decoding_Error("Certificate_Req: Bad certificate request");

TLS_Data_Reader reader("CertificateRequest", buf);

std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255);

for(size_t i = 0; i != cert_type_codes.size(); ++i)
{
const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]);

if(cert_type_name.empty()) // something we don't know
continue;

m_cert_key_types.emplace_back(cert_type_name);
}

const std::vector<uint8_t> algs = reader.get_range_vector<uint8_t>(2, 2, 65534);

if(algs.size() % 2 != 0)
throw Decoding_Error("Bad length for signature IDs in certificate request");

for(size_t i = 0; i != algs.size(); i += 2)
{
m_schemes.push_back(static_cast<Signature_Scheme>(make_uint16(algs[i], algs[i+1])));
}

const uint16_t purported_size = reader.get_uint16_t();

if(reader.remaining_bytes() != purported_size)
throw Decoding_Error("Inconsistent length in certificate request");

while(reader.has_remaining())
{
std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535);

BER_Decoder decoder(name_bits.data(), name_bits.size());
X509_DN name;
decoder.decode(name);
m_names.emplace_back(name);
}
}

// Needed for std::unique_ptr<> m_impl member, as *_Impl type
// is available as a forward declaration in the header only.
Certificate_Req::~Certificate_Req() = default;

/**
* Serialize a Certificate Request message
*/
std::vector<uint8_t> Certificate_Req::serialize() const
{
std::vector<uint8_t> buf;

std::vector<uint8_t> cert_types;

for(size_t i = 0; i != m_cert_key_types.size(); ++i)
cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i]));

append_tls_length_value(buf, cert_types, 1);

if(m_schemes.size() > 0)
buf += Signature_Algorithms(m_schemes).serialize(Connection_Side::SERVER);

std::vector<uint8_t> encoded_names;

for(size_t i = 0; i != m_names.size(); ++i)
{
DER_Encoder encoder;
encoder.encode(m_names[i]);

append_tls_length_value(encoded_names, encoder.get_contents(), 2);
}

append_tls_length_value(buf, encoded_names, 2);

return buf;
return m_impl->serialize();
}

}
Expand Down
31 changes: 31 additions & 0 deletions src/lib/tls/msg_cert_req_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Certificate Request Message
* (C) 2004-2006,2012 Jack Lloyd
* 2021 Elektrobit Automotive GmbH
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/tls_messages.h>
#include <botan/tls_extensions.h>
#include <botan/internal/tls_reader.h>
#include <botan/internal/tls_handshake_io.h>
#include <botan/internal/tls_handshake_hash.h>
#include <botan/internal/msg_cert_req_impl.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove superfluous includes


namespace Botan {

namespace TLS {

Certificate_Req_Impl::Certificate_Req_Impl() = default;

Handshake_Type Certificate_Req_Impl::type() const
{
return CERTIFICATE_REQUEST;
}

}

}
44 changes: 44 additions & 0 deletions src/lib/tls/msg_cert_req_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* TLS Certificate Message interface
* (C) 2004-2011,2015 Jack Lloyd
* 2016 Matthias Gierlings
* 2021 Elektrobit Automotive GmbH
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_MSG_CERT_REQ_IMPL_H_
#define BOTAN_MSG_CERT_REQ_IMPL_H_

#include <botan/tls_handshake_msg.h>
#include <botan/tls_algos.h>
#include <botan/x509cert.h>

#include <vector>
#include <string>

namespace Botan {

namespace TLS {

/**
* Interface of pimpl for Certificate Request Message
*/
class Certificate_Req_Impl : public Handshake_Message
{
public:
Handshake_Type type() const override;

virtual const std::vector<std::string>& acceptable_cert_types() const = 0;

virtual const std::vector<X509_DN>& acceptable_CAs() const = 0;

virtual const std::vector<Signature_Scheme>& signature_schemes() const = 0;

explicit Certificate_Req_Impl();
};
}

}

#endif
Loading