From a1b438469c23079a92b8a89e7df7e95fa0eae0ce Mon Sep 17 00:00:00 2001 From: lloyd Date: Tue, 24 Jan 2012 12:52:47 +0000 Subject: PEM encoding. Fix BER decoding. Encode the entire cert chain in the session. --- src/tls/tls_session.cpp | 68 ++++++++++++++++++++++++++++++++++--------------- src/tls/tls_session.h | 23 ++++++++++++++--- 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp index d9ccd6df4..2e25a8ab3 100644 --- a/src/tls/tls_session.cpp +++ b/src/tls/tls_session.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Botan { @@ -35,12 +36,10 @@ Session::Session(const MemoryRegion& session_identifier, m_connection_side(side), m_secure_renegotiation_supported(secure_renegotiation_supported), m_fragment_size(fragment_size), + m_peer_certs(certs), m_sni_hostname(sni_hostname), m_srp_identifier(srp_identifier) { - // FIXME: encode all of them? - if(certs.size()) - m_peer_certificate = certs[0].BER_encode(); } Session::Session(const byte ber[], size_t ber_len) @@ -53,31 +52,55 @@ Session::Session(const byte ber[], size_t ber_len) byte major_version = 0, minor_version = 0; + MemoryVector peer_cert_bits; + BER_Decoder(ber, ber_len) - .decode_and_check(static_cast(TLS_SESSION_PARAM_STRUCT_VERSION), - "Unknown version in session structure") - .decode(m_identifier, OCTET_STRING) - .decode_integer_type(m_start_time) - .decode_integer_type(major_version) - .decode_integer_type(minor_version) - .decode_integer_type(m_ciphersuite) - .decode_integer_type(m_compression_method) - .decode_integer_type(side_code) - .decode_integer_type(m_fragment_size) - .decode(m_secure_renegotiation_supported) - .decode(m_master_secret, OCTET_STRING) - .decode(m_peer_certificate, OCTET_STRING) - .decode(sni_hostname_str) - .decode(srp_identifier_str); + .start_cons(SEQUENCE) + .decode_and_check(static_cast(TLS_SESSION_PARAM_STRUCT_VERSION), + "Unknown version in session structure") + .decode(m_identifier, OCTET_STRING) + .decode_integer_type(m_start_time) + .decode_integer_type(major_version) + .decode_integer_type(minor_version) + .decode_integer_type(m_ciphersuite) + .decode_integer_type(m_compression_method) + .decode_integer_type(side_code) + .decode_integer_type(m_fragment_size) + .decode(m_secure_renegotiation_supported) + .decode(m_master_secret, OCTET_STRING) + .decode(peer_cert_bits, OCTET_STRING) + .decode(sni_hostname_str) + .decode(srp_identifier_str) + .end_cons() + .verify_end(); m_version = Protocol_Version(major_version, minor_version); m_sni_hostname = sni_hostname_str.value(); m_srp_identifier = srp_identifier_str.value(); m_connection_side = static_cast(side_code); + + if(!peer_cert_bits.empty()) + { + DataSource_Memory certs(peer_cert_bits); + + while(!certs.end_of_data()) + m_peer_certs.push_back(X509_Certificate(certs)); + } } -SecureVector Session::BER_encode() const +Session::Session(const std::string& pem) { + SecureVector der = PEM_Code::decode_check_label(pem, "SSL SESSION"); + + *this = Session(&der[0], der.size()); + } + +SecureVector Session::DER_encode() const + { + MemoryVector peer_cert_bits; + for(size_t i = 0; i != m_peer_certs.size(); ++i) + peer_cert_bits += m_peer_certs[i].BER_encode(); + return DER_Encoder() .start_cons(SEQUENCE) .encode(static_cast(TLS_SESSION_PARAM_STRUCT_VERSION)) @@ -91,13 +114,18 @@ SecureVector Session::BER_encode() const .encode(static_cast(m_fragment_size)) .encode(m_secure_renegotiation_supported) .encode(m_master_secret, OCTET_STRING) - .encode(m_peer_certificate, OCTET_STRING) + .encode(peer_cert_bits, OCTET_STRING) .encode(ASN1_String(m_sni_hostname, UTF8_STRING)) .encode(ASN1_String(m_srp_identifier, UTF8_STRING)) .end_cons() .get_contents(); } +std::string Session::PEM_encode() const + { + return PEM_Code::encode(this->DER_encode(), "SSL SESSION"); + } + } } diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h index 96ef6514e..297ff5f96 100644 --- a/src/tls/tls_session.h +++ b/src/tls/tls_session.h @@ -54,16 +54,28 @@ class BOTAN_DLL Session const std::string& srp_identifier = ""); /** - * Load a session from BER (created by BER_encode) + * Load a session from DER representation (created by DER_encode) */ Session(const byte ber[], size_t ber_len); + /** + * Load a session from PEM representation (created by PEM_encode) + */ + Session(const std::string& pem); + + /** + * Encode this session data for storage + * @warning if the master secret is compromised so is the + * session traffic + */ + SecureVector DER_encode() const; + /** * Encode this session data for storage * @warning if the master secret is compromised so is the * session traffic */ - SecureVector BER_encode() const; + std::string PEM_encode() const; /** * Get the version of the saved session @@ -124,6 +136,11 @@ class BOTAN_DLL Session bool secure_renegotiation() const { return m_secure_renegotiation_supported; } + /** + * Return the certificate chain of the peer (possibly empty) + */ + std::vector peer_certs() const { return m_peer_certs; } + /** * Get the time this session began (seconds since Epoch) */ @@ -145,7 +162,7 @@ class BOTAN_DLL Session bool m_secure_renegotiation_supported; size_t m_fragment_size; - MemoryVector m_peer_certificate; // optional + std::vector m_peer_certs; std::string m_sni_hostname; // optional std::string m_srp_identifier; // optional }; -- cgit v1.2.3