summaryrefslogtreecommitdiff
path: root/extra/yassl/src
diff options
context:
space:
mode:
authormsvensson@shellback.(none) <>2006-11-29 09:21:37 +0100
committermsvensson@shellback.(none) <>2006-11-29 09:21:37 +0100
commit838d1d53b4e65980fbd10e496b43f49251e04790 (patch)
tree5d536b5e9188dd4985d4f225dd2cf252fbba06d2 /extra/yassl/src
parent45ea756c5fae0ffe6c2e5f32ad42ba956f37abec (diff)
downloadmariadb-git-838d1d53b4e65980fbd10e496b43f49251e04790.tar.gz
Import version 1.50 of yaSSL
Diffstat (limited to 'extra/yassl/src')
-rw-r--r--extra/yassl/src/handshake.cpp101
-rw-r--r--extra/yassl/src/make.bat2
-rw-r--r--extra/yassl/src/socket_wrapper.cpp10
-rw-r--r--extra/yassl/src/ssl.cpp152
-rw-r--r--extra/yassl/src/yassl_error.cpp12
-rw-r--r--extra/yassl/src/yassl_imp.cpp151
-rw-r--r--extra/yassl/src/yassl_int.cpp160
7 files changed, 471 insertions, 117 deletions
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
index 25f36c4ea8c..c03d72ff2ef 100644
--- a/extra/yassl/src/handshake.cpp
+++ b/extra/yassl/src/handshake.cpp
@@ -40,9 +40,11 @@ namespace yaSSL {
// Build a client hello message from cipher suites and compression method
-void buildClientHello(SSL& ssl, ClientHello& hello,
- CompressionMethod compression = no_compression)
+void buildClientHello(SSL& ssl, ClientHello& hello)
{
+ // store for pre master secret
+ ssl.useSecurity().use_connection().chVersion_ = hello.client_version_;
+
ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
if (ssl.getSecurity().get_resuming()) {
hello.id_len_ = ID_LEN;
@@ -55,7 +57,6 @@ void buildClientHello(SSL& ssl, ClientHello& hello,
memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_,
hello.suite_len_);
hello.comp_len_ = 1;
- hello.compression_methods_ = compression;
hello.set_length(sizeof(ProtocolVersion) +
RAN_LEN +
@@ -83,7 +84,7 @@ void buildServerHello(SSL& ssl, ServerHello& hello)
hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0];
hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1];
- hello.compression_method_ = no_compression;
+ hello.compression_method_ = hello.compression_method_;
hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN +
sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);
@@ -151,12 +152,18 @@ void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader,
// add handshake from buffer into md5 and sha hashes, exclude record header
-void hashHandShake(SSL& ssl, const output_buffer& output)
+void hashHandShake(SSL& ssl, const output_buffer& output, bool removeIV = false)
{
uint sz = output.get_size() - RECORD_HEADER;
const opaque* buffer = output.get_buffer() + RECORD_HEADER;
+ if (removeIV) { // TLSv1_1 IV
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ sz -= blockSz;
+ buffer += blockSz;
+ }
+
ssl.useHashes().use_MD5().update(buffer, sz);
ssl.useHashes().use_SHA().update(buffer, sz);
}
@@ -229,6 +236,18 @@ void decrypt_message(SSL& ssl, input_buffer& input, uint sz)
ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz);
memcpy(cipher, plain.get_buffer(), sz);
ssl.useSecurity().use_parms().encrypt_size_ = sz;
+
+ if (ssl.isTLSv1_1()) // IV
+ input.set_current(input.get_current() +
+ ssl.getCrypto().get_cipher().get_blockSize());
+}
+
+
+// output operator for input_buffer
+output_buffer& operator<<(output_buffer& output, const input_buffer& input)
+{
+ output.write(input.get_buffer(), input.get_size());
+ return output;
}
@@ -239,9 +258,12 @@ void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz;
uint pad = 0;
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+
if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ if (ssl.isTLSv1_1())
+ sz += blockSz; // IV
sz += 1; // pad byte
- uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
pad = (sz - RECORD_HEADER) % blockSz;
pad = blockSz - pad;
sz += pad;
@@ -252,14 +274,21 @@ void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
buildHeaders(ssl, hsHeader, rlHeader, fin);
rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
// and pad, hanshake doesn't
+ input_buffer iv;
+ if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){
+ iv.allocate(blockSz);
+ ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz);
+ iv.add_size(blockSz);
+ }
+ uint ivSz = iv.get_size();
output.allocate(sz);
- output << rlHeader << hsHeader << fin;
+ output << rlHeader << iv << hsHeader << fin;
- hashHandShake(ssl, output);
+ hashHandShake(ssl, output, ssl.isTLSv1_1() ? true : false);
opaque digest[SHA_LEN]; // max size
if (ssl.isTLS())
- TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
- output.get_size() - RECORD_HEADER, handshake);
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz,
+ output.get_size() - RECORD_HEADER - ivSz, handshake);
else
hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
output.get_size() - RECORD_HEADER, handshake);
@@ -282,9 +311,12 @@ void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
uint sz = RECORD_HEADER + msg.get_length() + digestSz;
uint pad = 0;
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+
if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ if (ssl.isTLSv1_1()) // IV
+ sz += blockSz;
sz += 1; // pad byte
- uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
pad = (sz - RECORD_HEADER) % blockSz;
pad = blockSz - pad;
sz += pad;
@@ -294,13 +326,21 @@ void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
buildHeader(ssl, rlHeader, msg);
rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
// and pad, hanshake doesn't
+ input_buffer iv;
+ if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){
+ iv.allocate(blockSz);
+ ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz);
+ iv.add_size(blockSz);
+ }
+
+ uint ivSz = iv.get_size();
output.allocate(sz);
- output << rlHeader << msg;
+ output << rlHeader << iv << msg;
opaque digest[SHA_LEN]; // max size
if (ssl.isTLS())
- TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
- output.get_size() - RECORD_HEADER, msg.get_type());
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz,
+ output.get_size() - RECORD_HEADER - ivSz, msg.get_type());
else
hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
output.get_size() - RECORD_HEADER, msg.get_type());
@@ -456,6 +496,10 @@ void buildSHA_CertVerify(SSL& ssl, byte* digest)
// some clients still send sslv2 client hello
void ProcessOldClientHello(input_buffer& input, SSL& ssl)
{
+ if (input.get_remaining() < 2) {
+ ssl.SetError(bad_input);
+ return;
+ }
byte b0 = input[AUTO];
byte b1 = input[AUTO];
@@ -721,6 +765,7 @@ int DoProcessReply(SSL& ssl)
// each message in record, can be more than 1 if not encrypted
if (ssl.getSecurity().get_parms().pending_ == false) // cipher on
decrypt_message(ssl, buffer, hdr.length_);
+
mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_));
if (!msg.get()) {
ssl.SetError(factory_error);
@@ -744,13 +789,13 @@ void processReply(SSL& ssl)
if (DoProcessReply(ssl))
// didn't complete process
- if (!ssl.getSocket().IsBlocking()) {
- // keep trying now
+ if (!ssl.getSocket().IsNonBlocking()) {
+ // keep trying now, blocking ok
while (!ssl.GetError())
if (DoProcessReply(ssl) == 0) break;
}
else
- // user will have try again later
+ // user will have try again later, non blocking
ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
}
@@ -761,7 +806,8 @@ void sendClientHello(SSL& ssl)
ssl.verifyState(serverNull);
if (ssl.GetError()) return;
- ClientHello ch(ssl.getSecurity().get_connection().version_);
+ ClientHello ch(ssl.getSecurity().get_connection().version_,
+ ssl.getSecurity().get_connection().compression_);
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
output_buffer out;
@@ -859,6 +905,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
}
else {
+ if (!ssl.getSecurity().GetContext()->GetSessionCacheOff())
GetSessions().add(ssl); // store session
if (side == client_end)
buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
@@ -885,7 +932,20 @@ int sendData(SSL& ssl, const void* buffer, int sz)
for (;;) {
int len = min(sz - sent, MAX_RECORD_SIZE);
output_buffer out;
- const Data data(len, static_cast<const opaque*>(buffer) + sent);
+ input_buffer tmp;
+
+ Data data;
+
+ if (ssl.CompressionOn()) {
+ if (Compress(static_cast<const opaque*>(buffer) + sent, len,
+ tmp) == -1) {
+ ssl.SetError(compress_error);
+ return -1;
+ }
+ data.SetData(tmp.get_size(), tmp.get_buffer());
+ }
+ else
+ data.SetData(len, static_cast<const opaque*>(buffer) + sent);
buildMessage(ssl, out, data);
ssl.Send(out.get_buffer(), out.get_size());
@@ -947,7 +1007,8 @@ void sendServerHello(SSL& ssl, BufferOutput buffer)
ssl.verifyState(clientHelloComplete);
if (ssl.GetError()) return;
- ServerHello sh(ssl.getSecurity().get_connection().version_);
+ ServerHello sh(ssl.getSecurity().get_connection().version_,
+ ssl.getSecurity().get_connection().compression_);
RecordLayerHeader rlHeader;
HandShakeHeader hsHeader;
mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer);
diff --git a/extra/yassl/src/make.bat b/extra/yassl/src/make.bat
index 148427a6f41..dde305721a7 100644
--- a/extra/yassl/src/make.bat
+++ b/extra/yassl/src/make.bat
@@ -1,7 +1,7 @@
REM quick and dirty build file for testing different MSDEVs
setlocal
-set myFLAGS= /I../include /I../mySTL /I../taocrypt/include /W3 /c /ZI
+set myFLAGS= /I../include /I../taocrypt/mySTL /I../taocrypt/include /W3 /c /ZI
cl %myFLAGS% buffer.cpp
cl %myFLAGS% cert_wrapper.cpp
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
index 70944831884..f281b81a24a 100644
--- a/extra/yassl/src/socket_wrapper.cpp
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -63,7 +63,7 @@ namespace yaSSL {
Socket::Socket(socket_t s)
- : socket_(s), wouldBlock_(false), blocking_(false)
+ : socket_(s), wouldBlock_(false), nonBlocking_(false)
{}
@@ -148,8 +148,8 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags)
if (recvd == -1) {
if (get_lastError() == SOCKET_EWOULDBLOCK ||
get_lastError() == SOCKET_EAGAIN) {
- wouldBlock_ = true;
- blocking_ = true; // socket can block, only way to tell for win32
+ wouldBlock_ = true; // would have blocked this time only
+ nonBlocking_ = true; // socket nonblocking, win32 only way to tell
return 0;
}
}
@@ -191,9 +191,9 @@ bool Socket::WouldBlock() const
}
-bool Socket::IsBlocking() const
+bool Socket::IsNonBlocking() const
{
- return blocking_;
+ return nonBlocking_;
}
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index a008ea7228b..e0e27502f3d 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -184,10 +184,22 @@ SSL_METHOD* TLSv1_client_method()
}
+SSL_METHOD* TLSv1_1_server_method()
+{
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2));
+}
+
+
+SSL_METHOD* TLSv1_1_client_method()
+{
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2));
+}
+
+
SSL_METHOD* SSLv23_server_method()
{
// compatibility only, no version 2 support, but does SSL 3 and TLS 1
- return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1), true);
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true);
}
@@ -196,7 +208,7 @@ SSL_METHOD* SSLv23_client_method()
// compatibility only, no version 2 support, but does SSL 3 and TLS 1
// though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline
// TODO: maybe add support to send SSLv2 hello ???
- return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1), true);
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true);
}
@@ -407,7 +419,6 @@ int SSL_shutdown(SSL* ssl)
Alert alert(warning, close_notify);
sendAlert(*ssl, alert);
ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
- ssl->useSocket().closeSocket();
GetErrors().Remove();
@@ -415,8 +426,21 @@ int SSL_shutdown(SSL* ssl)
}
+/* on by default but allow user to turn off */
+long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode)
+{
+ if (mode == SSL_SESS_CACHE_OFF)
+ ctx->SetSessionCacheOff();
+
+ return SSL_SUCCESS;
+}
+
+
SSL_SESSION* SSL_get_session(SSL* ssl)
{
+ if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
+ return 0;
+
return GetSessions().lookup(
ssl->getSecurity().get_connection().sessionID_);
}
@@ -424,6 +448,9 @@ SSL_SESSION* SSL_get_session(SSL* ssl)
int SSL_set_session(SSL* ssl, SSL_SESSION* session)
{
+ if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
+ return SSL_FAILURE;
+
ssl->set_session(session);
return SSL_SUCCESS;
}
@@ -512,6 +539,19 @@ int SSL_get_error(SSL* ssl, int /*previous*/)
}
+
+/* turn on yaSSL zlib compression
+ returns 0 for success, else error (not built in)
+ only need to turn on for client, becuase server on by default if built in
+ but calling for server will tell you whether it's available or not
+*/
+int SSL_set_compression(SSL* ssl)
+{
+ return ssl->SetCompression();
+}
+
+
+
X509* SSL_get_peer_certificate(SSL* ssl)
{
return ssl->getCrypto().get_certManager().get_peerX509();
@@ -1359,6 +1399,56 @@ int SSL_pending(SSL* ssl)
}
+void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
+{
+ ctx->SetPasswordCb(cb);
+}
+
+
+int SSLeay_add_ssl_algorithms() // compatibility only
+{
+ return 1;
+}
+
+
+void ERR_remove_state(unsigned long)
+{
+ GetErrors().Remove();
+}
+
+
+int ERR_GET_REASON(int l)
+{
+ return l & 0xfff;
+}
+
+
+unsigned long err_helper(bool peek = false)
+{
+ int ysError = GetErrors().Lookup(peek);
+
+ // translate cert error for libcurl, it uses OpenSSL hex code
+ switch (ysError) {
+ case TaoCrypt::SIG_OTHER_E:
+ return CERTFICATE_ERROR;
+ break;
+ default :
+ return 0;
+ }
+}
+
+
+unsigned long ERR_peek_error()
+{
+ return err_helper(true);
+}
+
+
+unsigned long ERR_get_error()
+{
+ return err_helper();
+}
+
// functions for stunnel
@@ -1477,13 +1567,6 @@ int SSL_pending(SSL* ssl)
}
- long SSL_CTX_set_session_cache_mode(SSL_CTX*, long)
- {
- // TDOD:
- return SSL_SUCCESS;
- }
-
-
long SSL_CTX_set_timeout(SSL_CTX*, long)
{
// TDOD:
@@ -1498,12 +1581,6 @@ int SSL_pending(SSL* ssl)
}
- void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
- {
- ctx->SetPasswordCb(cb);
- }
-
-
int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
{
// TDOD:
@@ -1555,49 +1632,6 @@ int SSL_pending(SSL* ssl)
}
- int SSLeay_add_ssl_algorithms() // compatibility only
- {
- return 1;
- }
-
-
- void ERR_remove_state(unsigned long)
- {
- GetErrors().Remove();
- }
-
-
- int ERR_GET_REASON(int l)
- {
- return l & 0xfff;
- }
-
- unsigned long err_helper(bool peek = false)
- {
- int ysError = GetErrors().Lookup(peek);
-
- // translate cert error for libcurl, it uses OpenSSL hex code
- switch (ysError) {
- case TaoCrypt::SIG_OTHER_E:
- return CERTFICATE_ERROR;
- break;
- default :
- return 0;
- }
- }
-
-
- unsigned long ERR_peek_error()
- {
- return err_helper(true);
- }
-
-
- unsigned long ERR_get_error()
- {
- return err_helper();
- }
-
// end stunnel needs
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
index 3531c0a2c74..25c595f40bc 100644
--- a/extra/yassl/src/yassl_error.cpp
+++ b/extra/yassl/src/yassl_error.cpp
@@ -133,6 +133,18 @@ void SetErrorString(YasslError error, char* buffer)
strncpy(buffer, "protocl version mismatch", max);
break;
+ case compress_error :
+ strncpy(buffer, "compression error", max);
+ break;
+
+ case decompress_error :
+ strncpy(buffer, "decompression error", max);
+ break;
+
+ case pms_version_error :
+ strncpy(buffer, "bad PreMasterSecret version error", max);
+ break;
+
// openssl errors
case SSL_ERROR_WANT_READ :
strncpy(buffer, "the read operation would block", max);
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()
{
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index 5288acb2bcd..1a407ca8ba5 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -38,6 +38,11 @@
#endif
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+
#ifdef YASSL_PURE_C
void* operator new(size_t sz, yaSSL::new_t)
@@ -727,6 +732,32 @@ void SSL::set_preMaster(const opaque* pre, uint sz)
}
+// set yaSSL zlib type compression
+int SSL::SetCompression()
+{
+#ifdef HAVE_LIBZ
+ secure_.use_connection().compression_ = true;
+ return 0;
+#else
+ return -1; // not built in
+#endif
+}
+
+
+// unset yaSSL zlib type compression
+void SSL::UnSetCompression()
+{
+ secure_.use_connection().compression_ = false;
+}
+
+
+// is yaSSL zlib compression on
+bool SSL::CompressionOn() const
+{
+ return secure_.get_connection().compression_;
+}
+
+
// store master secret
void SSL::set_masterSecret(const opaque* sec)
{
@@ -1109,6 +1140,11 @@ void SSL::verifyState(const RecordLayerHeader& rlHeader)
{
if (GetError()) return;
+ if (rlHeader.version_.major_ != 3 || rlHeader.version_.minor_ > 2) {
+ SetError(badVersion_error);
+ return;
+ }
+
if (states_.getRecord() == recordNotReady ||
(rlHeader.type_ == application_data && // data and handshake
states_.getHandShake() != handShakeReady) ) // isn't complete yet
@@ -1247,6 +1283,9 @@ void SSL::matchSuite(const opaque* peer, uint length)
void SSL::set_session(SSL_SESSION* s)
{
+ if (getSecurity().GetContext()->GetSessionCacheOff())
+ return;
+
if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) {
secure_.set_resuming(true);
crypto_.use_certManager().setPeerX509(s->GetPeerX509());
@@ -1344,6 +1383,12 @@ bool SSL::isTLS() const
}
+bool SSL::isTLSv1_1() const
+{
+ return secure_.get_connection().TLSv1_1_;
+}
+
+
void SSL::addData(input_buffer* data)
{
buffers_.useData().push_back(data);
@@ -1703,7 +1748,7 @@ bool SSL_METHOD::multipleProtocol() const
SSL_CTX::SSL_CTX(SSL_METHOD* meth)
: method_(meth), certificate_(0), privateKey_(0), passwordCb_(0),
- userData_(0)
+ userData_(0), sessionCacheOff_(false)
{}
@@ -1784,12 +1829,24 @@ void* SSL_CTX::GetUserData() const
}
+bool SSL_CTX::GetSessionCacheOff() const
+{
+ return sessionCacheOff_;
+}
+
+
void SSL_CTX::SetUserData(void* data)
{
userData_ = data;
}
+void SSL_CTX::SetSessionCacheOff()
+{
+ sessionCacheOff_ = true;
+}
+
+
void SSL_CTX::setVerifyPeer()
{
method_->setVerifyPeer();
@@ -2312,9 +2369,110 @@ ASN1_STRING* StringHolder::GetString()
}
+#ifdef HAVE_LIBZ
+
+ void* myAlloc(void* /* opaque */, unsigned int item, unsigned int size)
+ {
+ return NEW_YS unsigned char[item * size];
+ }
+
+
+ void myFree(void* /* opaque */, void* memory)
+ {
+ unsigned char* ptr = static_cast<unsigned char*>(memory);
+ yaSSL::ysArrayDelete(ptr);
+ }
+
+
+ // put size in front of compressed data
+ int Compress(const byte* in, int sz, input_buffer& buffer)
+ {
+ byte tmp[LENGTH_SZ];
+ z_stream c_stream; /* compression stream */
+
+ buffer.allocate(sz + sizeof(uint16) + COMPRESS_EXTRA);
+
+ c_stream.zalloc = myAlloc;
+ c_stream.zfree = myFree;
+ c_stream.opaque = (voidpf)0;
+
+ c_stream.next_in = const_cast<byte*>(in);
+ c_stream.avail_in = sz;
+ c_stream.next_out = buffer.get_buffer() + sizeof(tmp);
+ c_stream.avail_out = buffer.get_capacity() - sizeof(tmp);
+
+ if (deflateInit(&c_stream, 8) != Z_OK) return -1;
+ int err = deflate(&c_stream, Z_FINISH);
+ deflateEnd(&c_stream);
+ if (err != Z_OK && err != Z_STREAM_END) return -1;
+
+ c16toa(sz, tmp);
+ memcpy(buffer.get_buffer(), tmp, sizeof(tmp));
+ buffer.add_size(c_stream.total_out + sizeof(tmp));
+
+ return 0;
+ }
+
+
+ // get uncompressed size in front
+ int DeCompress(input_buffer& in, int sz, input_buffer& out)
+ {
+ byte tmp[LENGTH_SZ];
+
+ in.read(tmp, sizeof(tmp));
+
+ uint16 len;
+ ato16(tmp, len);
+
+ out.allocate(len);
+
+ z_stream d_stream; /* decompression stream */
+
+ d_stream.zalloc = myAlloc;
+ d_stream.zfree = myFree;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = in.get_buffer() + in.get_current();
+ d_stream.avail_in = sz - sizeof(tmp);
+ d_stream.next_out = out.get_buffer();
+ d_stream.avail_out = out.get_capacity();
+
+ if (inflateInit(&d_stream) != Z_OK) return -1;
+ int err = inflate(&d_stream, Z_FINISH);
+ inflateEnd(&d_stream);
+ if (err != Z_OK && err != Z_STREAM_END) return -1;
+
+ out.add_size(d_stream.total_out);
+ in.set_current(in.get_current() + sz - sizeof(tmp));
+
+ return 0;
+ }
+
+
+#else // LIBZ
+
+ // these versions should never get called
+ int Compress(const byte* in, int sz, input_buffer& buffer)
+ {
+ assert(0);
+ return -1;
+ }
+
+
+ int DeCompress(input_buffer& in, int sz, input_buffer& out)
+ {
+ assert(0);
+ return -1;
+ }
+
+
+#endif // LIBZ
+
+
} // namespace
+
extern "C" void yaSSL_CleanUp()
{
TaoCrypt::CleanUp();