Skip to content

Commit

Permalink
TLS 1.2 refactoring
Browse files Browse the repository at this point in the history
Co-authored-by: Marek Kocik <extern.Marek.Kocik@elektrobit.com>
Co-authored-by: Grzegorz Dulewicz <extern.Grzegorz.Dulewicz@elektrobit.com>
Co-authored-by: Pawel Bazelewski <extern.pawel.bazelewski@elektrobit.com>
Co-authored-by: Pawel Jarosz <extern.pawel.jarosz@elektrobit.com>
  • Loading branch information
5 people authored and reneme committed Oct 25, 2021
1 parent e43f1ce commit 1a2df36
Show file tree
Hide file tree
Showing 68 changed files with 6,534 additions and 3,309 deletions.
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
12 changes: 11 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 Down
123 changes: 28 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,68 @@
#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( protocol_version == Protocol_Version::TLS_V13
? TLS_Message_Factory::create<Certificate_Req_Impl, Protocol_Version::TLS_V13>()
: TLS_Message_Factory::create<Certificate_Req_Impl, Protocol_Version::TLS_V12>(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( protocol_version == Protocol_Version::TLS_V13
? TLS_Message_Factory::create<Certificate_Req_Impl, Protocol_Version::TLS_V13>()
: TLS_Message_Factory::create<Certificate_Req_Impl, Protocol_Version::TLS_V12>(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);
}
}

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
33 changes: 33 additions & 0 deletions src/lib/tls/msg_cert_req_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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>

namespace Botan {

namespace TLS {

Certificate_Req_Impl::Certificate_Req_Impl() = default;

Certificate_Req_Impl::~Certificate_Req_Impl() = default;

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

}

}
46 changes: 46 additions & 0 deletions src/lib/tls/msg_cert_req_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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();

virtual ~Certificate_Req_Impl() = 0;
};
}

}

#endif
Loading

0 comments on commit 1a2df36

Please sign in to comment.