diff options
Diffstat (limited to 'extra/yassl/src/yassl_imp.cpp')
-rw-r--r-- | extra/yassl/src/yassl_imp.cpp | 151 |
1 files changed, 120 insertions, 31 deletions
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index bd07f8b70f2..bf10c4b8932 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -87,7 +87,7 @@ void EncryptedPreMasterSecret::build(SSL& ssl) opaque tmp[SECRET_LEN]; memset(tmp, 0, sizeof(tmp)); ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN); - ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; tmp[0] = pv.major_; tmp[1] = pv.minor_; ssl.set_preMaster(tmp, SECRET_LEN); @@ -233,6 +233,10 @@ void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input) rsa.decrypt(preMasterSecret, secret_, length_, ssl.getCrypto().get_random()); + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; + if (pv.major_ != preMasterSecret[0] || pv.minor_ != preMasterSecret[1]) + ssl.SetError(pms_version_error); // continue deriving for timing attack + ssl.set_preMaster(preMasterSecret, SECRET_LEN); ssl.makeMasterSecret(); } @@ -437,6 +441,7 @@ Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, ProtocolVersion pv, bool haveDH) : entity_(ce) { pending_ = true; // suite not set yet + strncpy(cipher_name_, "NONE", 5); if (ciphers.setSuites_) { // use user set list suites_size_ = ciphers.suiteSz_; @@ -445,6 +450,7 @@ Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, } else SetSuites(pv, ce == server_end && !haveDH); // defaults + } @@ -613,14 +619,18 @@ output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr) void HandShakeHeader::Process(input_buffer& input, SSL& ssl) { ssl.verifyState(*this); + if (ssl.GetError()) return; const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_)); if (!hs.get()) { ssl.SetError(factory_error); return; } - hashHandShake(ssl, input, c24to32(length_)); + uint len = c24to32(length_); + hashHandShake(ssl, input, len); + + hs->set_length(len); input >> *hs; hs->Process(input, ssl); } @@ -849,11 +859,17 @@ void Alert::Process(input_buffer& input, SSL& ssl) opaque mac[SHA_LEN]; input.read(mac, digestSz); + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + int ivExtra = 0; opaque fill; - int padSz = ssl.getSecurity().get_parms().encrypt_size_ - aSz - - digestSz; + + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - + aSz - digestSz; for (int i = 0; i < padSz; i++) fill = input[AUTO]; + } // verify if (memcmp(mac, verify, digestSz)) { @@ -879,9 +895,13 @@ Data::Data(uint16 len, opaque* b) {} -Data::Data(uint16 len, const opaque* w) - : length_(len), buffer_(0), write_buffer_(w) -{} +void Data::SetData(uint16 len, const opaque* buffer) +{ + assert(write_buffer_ == 0); + + length_ = len; + write_buffer_ = buffer; +} input_buffer& Data::set(input_buffer& in) { @@ -907,17 +927,12 @@ uint16 Data::get_length() const } -const opaque* Data::get_buffer() const -{ - return write_buffer_; -} - - void Data::set_length(uint16 l) { length_ = l; } + opaque* Data::set_buffer() { return buffer_; @@ -937,27 +952,42 @@ void Data::Process(input_buffer& input, SSL& ssl) { int msgSz = ssl.getSecurity().get_parms().encrypt_size_; int pad = 0, padByte = 0; + int ivExtra = 0; + if (ssl.getSecurity().get_parms().cipher_type_ == block) { - pad = *(input.get_buffer() + input.get_current() + msgSz - 1); + if (ssl.isTLSv1_1()) // IV + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + pad = *(input.get_buffer() + input.get_current() + msgSz -ivExtra - 1); padByte = 1; } int digestSz = ssl.getCrypto().get_digest().get_digestSize(); - int dataSz = msgSz - digestSz - pad - padByte; + int dataSz = msgSz - ivExtra - digestSz - pad - padByte; opaque verify[SHA_LEN]; + const byte* rawData = input.get_buffer() + input.get_current(); + // read data - if (dataSz) { + if (dataSz) { // could be compressed + if (ssl.CompressionOn()) { + input_buffer tmp; + if (DeCompress(input, dataSz, tmp) == -1) { + ssl.SetError(decompress_error); + return; + } + ssl.addData(NEW_YS input_buffer(tmp.get_size(), + tmp.get_buffer(), tmp.get_size())); + } + else { input_buffer* data; ssl.addData(data = NEW_YS input_buffer(dataSz)); input.read(data->get_buffer(), dataSz); data->add_size(dataSz); + } if (ssl.isTLS()) - TLS_hmac(ssl, verify, data->get_buffer(), dataSz, application_data, - true); + TLS_hmac(ssl, verify, rawData, dataSz, application_data, true); else - hmac(ssl, verify, data->get_buffer(), dataSz, application_data, - true); + hmac(ssl, verify, rawData, dataSz, application_data, true); } // read mac and fill @@ -1220,6 +1250,13 @@ void ServerHello::Process(input_buffer&, SSL& ssl) if (ssl.isTLS() && server_version_.minor_ < 1) // downgrade to SSLv3 ssl.useSecurity().use_connection().TurnOffTLS(); + else if (ssl.isTLSv1_1() && server_version_.minor_ == 1) + // downdrage to TLSv1 + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && server_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; } else if (ssl.isTLS() && server_version_.minor_ < 1) { ssl.SetError(badVersion_error); @@ -1252,6 +1289,10 @@ void ServerHello::Process(input_buffer&, SSL& ssl) ssl.useSecurity().set_resuming(false); ssl.useLog().Trace("server denied resumption"); } + + if (ssl.CompressionOn() && !compression_method_) + ssl.UnSetCompression(); // server isn't supporting yaSSL zlib request + ssl.useStates().useClient() = serverHelloComplete; } @@ -1263,8 +1304,9 @@ ServerHello::ServerHello() } -ServerHello::ServerHello(ProtocolVersion pv) - : server_version_(pv) +ServerHello::ServerHello(ProtocolVersion pv, bool useCompression) + : server_version_(pv), + compression_method_(useCompression ? zlib : no_compression) { memset(random_, 0, RAN_LEN); memset(session_id_, 0, ID_LEN); @@ -1341,6 +1383,8 @@ opaque* ClientKeyBase::get_clientKey() const // input operator for Client Hello input_buffer& operator>>(input_buffer& input, ClientHello& hello) { + uint begin = input.get_current(); // could have extensions at end + // Protocol hello.client_version_.major_ = input[AUTO]; hello.client_version_.minor_ = input[AUTO]; @@ -1361,8 +1405,19 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) // Compression hello.comp_len_ = input[AUTO]; - while (hello.comp_len_--) // ignore for now - hello.compression_methods_ = CompressionMethod(input[AUTO]); + hello.compression_methods_ = no_compression; + while (hello.comp_len_--) { + CompressionMethod cm = CompressionMethod(input[AUTO]); + if (cm == zlib) + hello.compression_methods_ = zlib; + } + + uint read = input.get_current() - begin; + uint expected = hello.get_length(); + + // ignore client hello extensions for now + if (read < expected) + input.set_current(input.get_current() + expected - read); return input; } @@ -1400,6 +1455,13 @@ output_buffer& operator<<(output_buffer& output, const ClientHello& hello) // Client Hello processing handler void ClientHello::Process(input_buffer&, SSL& ssl) { + // store version for pre master secret + ssl.useSecurity().use_connection().chVersion_ = client_version_; + + if (client_version_.major_ != 3) { + ssl.SetError(badVersion_error); + return; + } if (ssl.GetMultiProtocol()) { // SSLv23 support if (ssl.isTLS() && client_version_.minor_ < 1) { // downgrade to SSLv3 @@ -1407,20 +1469,29 @@ void ClientHello::Process(input_buffer&, SSL& ssl) ProtocolVersion pv = ssl.getSecurity().get_connection().version_; ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites } + else if (ssl.isTLSv1_1() && client_version_.minor_ == 1) + // downgrade to TLSv1, but use same suites + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && client_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; } else if (ssl.isTLS() && client_version_.minor_ < 1) { ssl.SetError(badVersion_error); return; } - else if (!ssl.isTLS() && (client_version_.major_ == 3 && - client_version_.minor_ >= 1)) { + else if (!ssl.isTLS() && client_version_.minor_ >= 1) { ssl.SetError(badVersion_error); return; } + ssl.set_random(random_, client_end); while (id_len_) { // trying to resume - SSL_SESSION* session = GetSessions().lookup(session_id_); + SSL_SESSION* session = 0; + if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) + session = GetSessions().lookup(session_id_); if (!session) { ssl.useLog().Trace("session lookup failed"); break; @@ -1444,6 +1515,9 @@ void ClientHello::Process(input_buffer&, SSL& ssl) ssl.matchSuite(cipher_suites_, suite_len_); ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); + if (compression_methods_ == zlib) + ssl.SetCompression(); + ssl.useStates().useServer() = clientHelloComplete; } @@ -1478,8 +1552,9 @@ ClientHello::ClientHello() } -ClientHello::ClientHello(ProtocolVersion pv) - : client_version_(pv) +ClientHello::ClientHello(ProtocolVersion pv, bool useCompression) + : client_version_(pv), + compression_methods_(useCompression ? zlib : no_compression) { memset(random_, 0, RAN_LEN); } @@ -1943,8 +2018,13 @@ void Finished::Process(input_buffer& input, SSL& ssl) int digestSz = ssl.getCrypto().get_digest().get_digestSize(); input.read(mac, digestSz); + uint ivExtra = 0; + if (ssl.getSecurity().get_parms().cipher_type_ == block) + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + opaque fill; - int padSz = ssl.getSecurity().get_parms().encrypt_size_ - + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - HANDSHAKE_HEADER - finishedSz - digestSz; for (int i = 0; i < padSz; i++) fill = input[AUTO]; @@ -2018,7 +2098,9 @@ void clean(volatile opaque* p, uint sz, RandomPool& ran) Connection::Connection(ProtocolVersion v, RandomPool& ran) : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0), pre_secret_len_(0), send_server_key_(false), master_clean_(false), - TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran) + TLS_(v.major_ >= 3 && v.minor_ >= 1), + TLSv1_1_(v.major_ >= 3 && v.minor_ >= 2), compression_(false), + version_(v), random_(ran) { memset(sessionID_, 0, sizeof(sessionID_)); } @@ -2043,6 +2125,13 @@ void Connection::TurnOffTLS() } +void Connection::TurnOffTLS1_1() +{ + TLSv1_1_ = false; + version_.minor_ = 1; +} + + // wipeout master secret void Connection::CleanMaster() { |