diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tls/c_kex.cpp | 2 | ||||
-rw-r--r-- | src/tls/cert_req.cpp | 4 | ||||
-rw-r--r-- | src/tls/cert_ver.cpp | 8 | ||||
-rw-r--r-- | src/tls/finished.cpp | 6 | ||||
-rw-r--r-- | src/tls/hello.cpp | 12 | ||||
-rw-r--r-- | src/tls/rec_read.cpp | 12 | ||||
-rw-r--r-- | src/tls/rec_wri.cpp | 2 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 5 | ||||
-rw-r--r-- | src/tls/tls_alerts.h | 11 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 24 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.cpp | 18 | ||||
-rw-r--r-- | src/tls/tls_handshake_hash.h | 12 | ||||
-rw-r--r-- | src/tls/tls_magic.h | 5 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 28 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 32 | ||||
-rw-r--r-- | src/tls/tls_state.h | 2 |
17 files changed, 123 insertions, 62 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index b55973ca3..ced31f870 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -21,7 +21,7 @@ namespace Botan { */ Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng, Record_Writer& writer, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const Public_Key* pub_key, Version_Code using_version, Version_Code pref_version) diff --git a/src/tls/cert_req.cpp b/src/tls/cert_req.cpp index cc77509df..85c017fac 100644 --- a/src/tls/cert_req.cpp +++ b/src/tls/cert_req.cpp @@ -18,7 +18,7 @@ namespace Botan { * Create a new Certificate Request message */ Certificate_Req::Certificate_Req(Record_Writer& writer, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const std::vector<X509_Certificate>& ca_certs, const std::vector<Certificate_Type>& cert_types) { @@ -90,7 +90,7 @@ void Certificate_Req::deserialize(const MemoryRegion<byte>& buf) */ Certificate::Certificate(Record_Writer& writer, const std::vector<X509_Certificate>& cert_list, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { certs = cert_list; send(writer, hash); diff --git a/src/tls/cert_ver.cpp b/src/tls/cert_ver.cpp index 0d8256e5e..4203e2542 100644 --- a/src/tls/cert_ver.cpp +++ b/src/tls/cert_ver.cpp @@ -1,6 +1,6 @@ /* * Certificate Verify Message -* (C) 2004-2010 Jack Lloyd +* (C) 2004-2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -20,7 +20,7 @@ namespace Botan { */ Certificate_Verify::Certificate_Verify(RandomNumberGenerator& rng, Record_Writer& writer, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const Private_Key* priv_key) { std::string padding = ""; @@ -71,7 +71,7 @@ void Certificate_Verify::deserialize(const MemoryRegion<byte>& buf) * Verify a Certificate Verify message */ bool Certificate_Verify::verify(const X509_Certificate& cert, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { // FIXME: duplicate of Server_Key_Exchange::verify @@ -92,7 +92,7 @@ bool Certificate_Verify::verify(const X509_Certificate& cert, " is invalid/unknown for TLS signatures"); PK_Verifier verifier(*key, padding, format); - return verifier.verify_message(hash.final(), signature); + return verifier.verify_message(hash.get_contents(), signature); } } diff --git a/src/tls/finished.cpp b/src/tls/finished.cpp index dff977d31..bc072bc9d 100644 --- a/src/tls/finished.cpp +++ b/src/tls/finished.cpp @@ -16,7 +16,7 @@ namespace Botan { Finished::Finished(Record_Writer& writer, Version_Code version, Connection_Side side, const MemoryRegion<byte>& master_secret, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { verification_data = compute_verify(master_secret, hash, side, version); send(writer, hash); @@ -42,7 +42,7 @@ void Finished::deserialize(const MemoryRegion<byte>& buf) * Verify a Finished message */ bool Finished::verify(const MemoryRegion<byte>& secret, Version_Code version, - const HandshakeHash& hash, Connection_Side side) + const TLS_Handshake_Hash& hash, Connection_Side side) { MemoryVector<byte> computed = compute_verify(secret, hash, side, version); if(computed == verification_data) @@ -54,7 +54,7 @@ bool Finished::verify(const MemoryRegion<byte>& secret, Version_Code version, * Compute the verify_data */ MemoryVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, - HandshakeHash hash, + TLS_Handshake_Hash hash, Connection_Side side, Version_Code version) { diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp index 207c3d097..45eedbd76 100644 --- a/src/tls/hello.cpp +++ b/src/tls/hello.cpp @@ -15,7 +15,7 @@ namespace Botan { /* * Encode and send a Handshake message */ -void HandshakeMessage::send(Record_Writer& writer, HandshakeHash& hash) const +void HandshakeMessage::send(Record_Writer& writer, TLS_Handshake_Hash& hash) const { MemoryVector<byte> buf = serialize(); MemoryVector<byte> send_buf(4); @@ -40,7 +40,7 @@ void HandshakeMessage::send(Record_Writer& writer, HandshakeHash& hash) const */ Hello_Request::Hello_Request(Record_Writer& writer) { - HandshakeHash dummy; // FIXME: *UGLY* + TLS_Handshake_Hash dummy; // FIXME: *UGLY* send(writer, dummy); } @@ -67,7 +67,7 @@ void Hello_Request::deserialize(const MemoryRegion<byte>& buf) Client_Hello::Client_Hello(RandomNumberGenerator& rng, Record_Writer& writer, const TLS_Policy& policy, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { c_random = rng.random_vec(32); @@ -229,7 +229,7 @@ Server_Hello::Server_Hello(RandomNumberGenerator& rng, const Client_Hello& c_hello, const MemoryRegion<byte>& session_id, Version_Code ver, - HandshakeHash& hash) : + TLS_Handshake_Hash& hash) : s_version(ver), sess_id(session_id), s_random(rng.random_vec(32)) @@ -266,7 +266,7 @@ Server_Hello::Server_Hello(RandomNumberGenerator& rng, u16bit ciphersuite, byte compression, Version_Code ver, - HandshakeHash& hash) : + TLS_Handshake_Hash& hash) : s_version(ver), sess_id(session_id), s_random(rng.random_vec(32)), @@ -328,7 +328,7 @@ void Server_Hello::deserialize(const MemoryRegion<byte>& buf) * Create a new Server Hello Done message */ Server_Hello_Done::Server_Hello_Done(Record_Writer& writer, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { send(writer, hash); } diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp index 9b71bfec3..84a96f508 100644 --- a/src/tls/rec_read.cpp +++ b/src/tls/rec_read.cpp @@ -176,12 +176,16 @@ size_t Record_Reader::get_record(byte& msg_type, input_queue.read(header, sizeof(header)); // pull off the header input_queue.read(&buffer[0], buffer.size()); - /* - * We are handshaking, no crypto to do so return as-is - * TODO: Check msg_type to confirm a handshake? - */ + // We are handshaking, no crypto to do so return as-is if(mac_size == 0) { + if(header[0] != CHANGE_CIPHER_SPEC && + header[0] != ALERT && + header[0] != HANDSHAKE) + { + throw TLS_Exception(DECODE_ERROR, "Invalid msg type received during handshake"); + } + msg_type = header[0]; output = buffer; return 0; // got a full record diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index b1edde64b..4803621f6 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -206,7 +206,7 @@ void Record_Writer::send_record(byte type, const byte buf[], size_t length) SecureVector<byte> buf_mac = mac->final(); - // TODO: This could all use a single buffer + // FIXME: this could be done in place in a single buffer cipher.start_msg(); if(iv_size) diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index b11892923..bb2ed7c1d 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -25,7 +25,7 @@ Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, const Private_Key* priv_key, const MemoryRegion<byte>& c_random, const MemoryRegion<byte>& s_random, - HandshakeHash& hash) + TLS_Handshake_Hash& hash) { const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(kex_key); const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(kex_key); @@ -44,7 +44,7 @@ Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, else throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA"); - + // FIXME: cut and paste std::string padding = ""; Signature_Format format = IEEE_1363; @@ -153,6 +153,7 @@ bool Server_Key_Exchange::verify(const X509_Certificate& cert, std::auto_ptr<Public_Key> key(cert.subject_public_key()); + // FIXME: cut and paste std::string padding = ""; Signature_Format format = IEEE_1363; diff --git a/src/tls/tls_alerts.h b/src/tls/tls_alerts.h index 241599aa8..c74361930 100644 --- a/src/tls/tls_alerts.h +++ b/src/tls/tls_alerts.h @@ -1,6 +1,6 @@ /* * Alert Message -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2006,2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -40,9 +40,14 @@ class Alert if(buf[0] == 1) fatal = false; else if(buf[0] == 2) fatal = true; else - throw Decoding_Error("Alert: Bad type code for alert level"); + throw Decoding_Error("Alert: Bad code for alert level"); - type_code = static_cast<Alert_Type>(buf[1]); + const byte dc = buf[1]; + + if(dc == 255) + throw Decoding_Error("Alert: description code 255, rejecting"); + + type_code = static_cast<Alert_Type>(dc); } private: bool fatal; diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 399568a44..553f65836 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -54,7 +54,7 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size) * following record. Avoid spurious callbacks. */ if(record.size() > 0) - proc_fn(&record[0], record.size(), NO_ALERT_TYPE); + proc_fn(&record[0], record.size(), NULL_ALERT); } else { @@ -76,7 +76,7 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size) if(alert_msg.type() == CLOSE_NOTIFY) alert(FATAL, CLOSE_NOTIFY); else - alert(FATAL, NO_ALERT_TYPE); + alert(FATAL, NULL_ALERT); } } else @@ -90,6 +90,11 @@ size_t TLS_Channel::received_data(const byte buf[], size_t buf_size) alert(FATAL, e.type()); throw; } + catch(Decoding_Error& e) + { + alert(FATAL, DECODE_ERROR); + throw; + } catch(std::exception& e) { alert(FATAL, INTERNAL_ERROR); @@ -167,16 +172,19 @@ void TLS_Channel::queue_for_sending(const byte buf[], size_t buf_size) pre_handshake_write_queue.write(buf, buf_size); } -void TLS_Channel::alert(Alert_Level level, Alert_Type alert_code) +void TLS_Channel::alert(Alert_Level alert_level, Alert_Type alert_code) { - try + if(alert_code != NULL_ALERT) { - writer.alert(level, alert_code); - writer.flush(); + try + { + writer.alert(alert_level, alert_code); + writer.flush(); + } + catch(...) { /* swallow it */ } } - catch(...) { /* swallow it */ } - if(active && level == FATAL) + if(active && alert_level == FATAL) { reader.reset(); writer.reset(); diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index dfa5c57df..d8861459c 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -55,8 +55,6 @@ TLS_Client::~TLS_Client() void TLS_Client::process_handshake_msg(Handshake_Type type, const MemoryRegion<byte>& contents) { - rng.add_entropy(&contents[0], contents.size()); - if(type == HELLO_REQUEST) { if(state == 0) diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp index 7c1e2e385..9621af535 100644 --- a/src/tls/tls_handshake_hash.cpp +++ b/src/tls/tls_handshake_hash.cpp @@ -1,6 +1,6 @@ /* * TLS Handshake Hash -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2006,2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -12,10 +12,22 @@ namespace Botan { +void TLS_Handshake_Hash::update(Handshake_Type handshake_type, + const MemoryRegion<byte>& handshake_msg) + { + update(static_cast<byte>(handshake_type)); + + const size_t record_length = handshake_msg.size(); + for(size_t i = 0; i != 3; i++) + update(get_byte<u32bit>(i+1, record_length)); + + update(handshake_msg); + } + /** * Return a TLS Handshake Hash */ -SecureVector<byte> HandshakeHash::final() +SecureVector<byte> TLS_Handshake_Hash::final() { MD5 md5; SHA_160 sha1; @@ -32,7 +44,7 @@ SecureVector<byte> HandshakeHash::final() /** * Return a SSLv3 Handshake Hash */ -SecureVector<byte> HandshakeHash::final_ssl3(const MemoryRegion<byte>& secret) +SecureVector<byte> TLS_Handshake_Hash::final_ssl3(const MemoryRegion<byte>& secret) { const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C; diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h index cea612a71..4ee1fc1b9 100644 --- a/src/tls/tls_handshake_hash.h +++ b/src/tls/tls_handshake_hash.h @@ -1,6 +1,6 @@ /* * TLS Handshake Hash -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2006,2011 Jack Lloyd * * Released under the terms of the Botan license */ @@ -9,6 +9,7 @@ #define BOTAN_TLS_HANDSHAKE_HASH_H__ #include <botan/secmem.h> +#include <botan/tls_magic.h> namespace Botan { @@ -17,7 +18,7 @@ using namespace Botan; /** * TLS Handshake Hash */ -class HandshakeHash +class TLS_Handshake_Hash { public: void update(const byte in[], size_t length) @@ -29,8 +30,15 @@ class HandshakeHash void update(byte in) { data.push_back(in); } + void update(Handshake_Type handshake_type, + const MemoryRegion<byte>& handshake_msg); + SecureVector<byte> final(); SecureVector<byte> final_ssl3(const MemoryRegion<byte>&); + + const SecureVector<byte>& get_contents() const + { return data; } + private: SecureVector<byte> data; }; diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h index 805519787..da6578c0a 100644 --- a/src/tls/tls_magic.h +++ b/src/tls/tls_magic.h @@ -84,9 +84,12 @@ enum Alert_Type { USER_CANCELED = 90, NO_RENEGOTIATION = 100, + UNSUPPORTED_EXTENSION = 110, + UNRECOGNIZED_NAME = 112, + UNKNOWN_PSK_IDENTITY = 115, - NO_ALERT_TYPE = 0xFFFF + NULL_ALERT = 255 }; enum Certificate_Type { diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index c4920066e..880f77c98 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -28,7 +28,7 @@ class Record_Reader; class HandshakeMessage { public: - void send(Record_Writer&, HandshakeHash&) const; + void send(Record_Writer&, TLS_Handshake_Hash&) const; virtual Handshake_Type type() const = 0; @@ -68,7 +68,7 @@ class Client_Hello : public HandshakeMessage bool offered_suite(u16bit) const; Client_Hello(RandomNumberGenerator& rng, - Record_Writer&, const TLS_Policy&, HandshakeHash&); + Record_Writer&, const TLS_Policy&, TLS_Handshake_Hash&); Client_Hello(const MemoryRegion<byte>& buf, Handshake_Type type) @@ -108,7 +108,7 @@ class Client_Key_Exchange : public HandshakeMessage Client_Key_Exchange(RandomNumberGenerator& rng, Record_Writer& output, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const Public_Key* my_key, Version_Code using_version, Version_Code pref_version); @@ -137,7 +137,7 @@ class Certificate : public HandshakeMessage bool empty() const { return certs.empty(); } Certificate(Record_Writer&, const std::vector<X509_Certificate>&, - HandshakeHash&); + TLS_Handshake_Hash&); Certificate(const MemoryRegion<byte>& buf) { deserialize(buf); } private: MemoryVector<byte> serialize() const; @@ -157,7 +157,7 @@ class Certificate_Req : public HandshakeMessage std::vector<X509_DN> acceptable_CAs() const { return names; } Certificate_Req(Record_Writer& writer, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const std::vector<X509_Certificate>& allowed_cas, const std::vector<Certificate_Type>& types = std::vector<Certificate_Type>()); @@ -180,11 +180,11 @@ class Certificate_Verify : public HandshakeMessage Handshake_Type type() const { return CERTIFICATE_VERIFY; } bool verify(const X509_Certificate& cert, - HandshakeHash& hash); + TLS_Handshake_Hash& hash); Certificate_Verify(RandomNumberGenerator& rng, Record_Writer& writer, - HandshakeHash& hash, + TLS_Handshake_Hash& hash, const Private_Key* key); Certificate_Verify(const MemoryRegion<byte>& buf) { deserialize(buf); } @@ -204,17 +204,17 @@ class Finished : public HandshakeMessage Handshake_Type type() const { return FINISHED; } bool verify(const MemoryRegion<byte>&, Version_Code, - const HandshakeHash&, Connection_Side); + const TLS_Handshake_Hash&, Connection_Side); Finished(Record_Writer&, Version_Code, Connection_Side, - const MemoryRegion<byte>&, HandshakeHash&); + const MemoryRegion<byte>&, TLS_Handshake_Hash&); Finished(const MemoryRegion<byte>& buf) { deserialize(buf); } private: MemoryVector<byte> serialize() const; void deserialize(const MemoryRegion<byte>&); MemoryVector<byte> compute_verify(const MemoryRegion<byte>&, - HandshakeHash, Connection_Side, + TLS_Handshake_Hash, Connection_Side, Version_Code); Connection_Side side; @@ -264,7 +264,7 @@ class Server_Hello : public HandshakeMessage const Client_Hello& other, const MemoryRegion<byte>& session_id, Version_Code version, - HandshakeHash& hash); + TLS_Handshake_Hash& hash); Server_Hello(RandomNumberGenerator& rng, Record_Writer& writer, @@ -272,7 +272,7 @@ class Server_Hello : public HandshakeMessage u16bit ciphersuite, byte compression, Version_Code ver, - HandshakeHash& hash); + TLS_Handshake_Hash& hash); Server_Hello(const MemoryRegion<byte>& buf) { deserialize(buf); } private: @@ -300,7 +300,7 @@ class Server_Key_Exchange : public HandshakeMessage Server_Key_Exchange(RandomNumberGenerator& rng, Record_Writer&, const Public_Key*, const Private_Key*, const MemoryRegion<byte>&, - const MemoryRegion<byte>&, HandshakeHash&); + const MemoryRegion<byte>&, TLS_Handshake_Hash&); Server_Key_Exchange(const MemoryRegion<byte>& buf) { deserialize(buf); } private: @@ -320,7 +320,7 @@ class Server_Hello_Done : public HandshakeMessage public: Handshake_Type type() const { return SERVER_HELLO_DONE; } - Server_Hello_Done(Record_Writer&, HandshakeHash&); + Server_Hello_Done(Record_Writer&, TLS_Handshake_Hash&); Server_Hello_Done(const MemoryRegion<byte>& buf) { deserialize(buf); } private: MemoryVector<byte> serialize() const; diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index f9de0a2b6..581d562be 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -12,6 +12,8 @@ #include <botan/rsa.h> #include <botan/dh.h> +#include <stdio.h> + namespace Botan { namespace { @@ -126,14 +128,12 @@ void TLS_Server::read_handshake(byte rec_type, void TLS_Server::process_handshake_msg(Handshake_Type type, const MemoryRegion<byte>& contents) { - rng.add_entropy(&contents[0], contents.size()); - if(state == 0) throw Unexpected_Message("Unexpected handshake message"); state->confirm_transition_to(type); - if(type != HANDSHAKE_CCS && type != FINISHED) + if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY) { if(type != CLIENT_HELLO_SSLV2) { @@ -252,7 +252,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, /* * If the client doesn't have a cert they want to use they are * allowed to send either an empty cert message or proceed - * directly to the client key exchange. + * directly to the client key exchange, so allow either case. */ state->set_expected_next(CLIENT_KEX); @@ -263,6 +263,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, { state->client_certs = new Certificate(contents); + // Is this allowed by the protocol? if(state->client_certs->count() > 1) throw TLS_Exception(CERTIFICATE_UNKNOWN, "Client sent more than one certificate"); @@ -293,7 +294,28 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, std::vector<X509_Certificate> client_certs = state->client_certs->cert_chain(); - //const bool ok = state->client_verify->verify(client_certs[0]); + const bool sig_valid = state->client_verify->verify(client_certs[0], + state->hash); + + state->hash.update(static_cast<byte>(type)); + + const size_t record_length = contents.size(); + for(size_t i = 0; i != 3; i++) + state->hash.update(get_byte<u32bit>(i+1, record_length)); + + state->hash.update(contents); + + /* + * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for + * "A handshake cryptographic operation failed, including being + * unable to correctly verify a signature, ..." + */ + if(!sig_valid && false) + throw TLS_Exception(DECRYPT_ERROR, "Client cert verify failed"); + + printf("Sig valid? %d\n", sig_valid); + + // Check cert was issued by a CA we requested, signatures, etc. state->set_expected_next(HANDSHAKE_CCS); } diff --git a/src/tls/tls_state.h b/src/tls/tls_state.h index 63f89132d..4d1ae9d6d 100644 --- a/src/tls/tls_state.h +++ b/src/tls/tls_state.h @@ -46,7 +46,7 @@ class Handshake_State CipherSuite suite; SessionKeys keys; - HandshakeHash hash; + TLS_Handshake_Hash hash; SecureQueue queue; |