diff options
Diffstat (limited to 'mysql/extra/yassl/src/yassl_imp.cpp')
-rw-r--r-- | mysql/extra/yassl/src/yassl_imp.cpp | 2642 |
1 files changed, 0 insertions, 2642 deletions
diff --git a/mysql/extra/yassl/src/yassl_imp.cpp b/mysql/extra/yassl/src/yassl_imp.cpp deleted file mode 100644 index ea09777..0000000 --- a/mysql/extra/yassl/src/yassl_imp.cpp +++ /dev/null @@ -1,2642 +0,0 @@ -/* - Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - MA 02110-1301 USA. -*/ - -/* yaSSL source implements all SSL.v3 secification structures. - */ - -#include "runtime.hpp" -#include "yassl_int.hpp" -#include "handshake.hpp" - -#include "asn.hpp" // provide crypto wrapper?? - - - -namespace yaSSL { - - -namespace { // locals - -bool isTLS(ProtocolVersion pv) -{ - if (pv.major_ >= 3 && pv.minor_ >= 1) - return true; - - return false; -} - - -} // namespace (locals) - - -void hashHandShake(SSL&, const input_buffer&, uint); - - -ProtocolVersion::ProtocolVersion(uint8 maj, uint8 min) - : major_(maj), minor_(min) -{} - - -// construct key exchange with known ssl parms -void ClientKeyExchange::createKey(SSL& ssl) -{ - const ClientKeyFactory& ckf = ssl.getFactory().getClientKey(); - client_key_ = ckf.CreateObject(ssl.getSecurity().get_parms().kea_); - - if (!client_key_) - ssl.SetError(factory_error); -} - - -// construct key exchange with known ssl parms -void ServerKeyExchange::createKey(SSL& ssl) -{ - const ServerKeyFactory& skf = ssl.getFactory().getServerKey(); - server_key_ = skf.CreateObject(ssl.getSecurity().get_parms().kea_); - - if (!server_key_) - ssl.SetError(factory_error); -} - - -// build/set PreMaster secret and encrypt, client side -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().chVersion_; - tmp[0] = pv.major_; - tmp[1] = pv.minor_; - ssl.set_preMaster(tmp, SECRET_LEN); - - const CertManager& cert = ssl.getCrypto().get_certManager(); - RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); - bool tls = ssl.isTLS(); // if TLS, put length for encrypted data - alloc(rsa.get_cipherLength() + (tls ? 2 : 0)); - byte* holder = secret_; - if (tls) { - byte len[2]; - c16toa(rsa.get_cipherLength(), len); - memcpy(secret_, len, sizeof(len)); - holder += 2; - } - rsa.encrypt(holder, tmp, SECRET_LEN, ssl.getCrypto().get_random()); -} - - -// build/set premaster and Client Public key, client side -void ClientDiffieHellmanPublic::build(SSL& ssl) -{ - DiffieHellman& dhServer = ssl.useCrypto().use_dh(); - DiffieHellman dhClient(dhServer); - - uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same - - alloc(keyLength, true); - dhClient.makeAgreement(dhServer.get_publicKey(), - dhServer.get_publicKeyLength()); - c16toa(keyLength, Yc_); - memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength); - - ssl.set_preMaster(dhClient.get_agreedKey(), keyLength); -} - - -// build server exhange, server side -void DH_Server::build(SSL& ssl) -{ - DiffieHellman& dhServer = ssl.useCrypto().use_dh(); - - int pSz, gSz, pubSz; - dhServer.set_sizes(pSz, gSz, pubSz); - dhServer.get_parms(parms_.alloc_p(pSz), parms_.alloc_g(gSz), - parms_.alloc_pub(pubSz)); - - short sigSz = 0; - mySTL::auto_ptr<Auth> auth; - const CertManager& cert = ssl.getCrypto().get_certManager(); - - if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { - if (cert.get_keyType() != rsa_sa_algo) { - ssl.SetError(privateKey_error); - return; - } - auth.reset(NEW_YS RSA(cert.get_privateKey(), - cert.get_privateKeyLength(), false)); - } - else { - if (cert.get_keyType() != dsa_sa_algo) { - ssl.SetError(privateKey_error); - return; - } - auth.reset(NEW_YS DSS(cert.get_privateKey(), - cert.get_privateKeyLength(), false)); - sigSz += DSS_ENCODED_EXTRA; - } - - sigSz += auth->get_signatureLength(); - if (!sigSz) { - ssl.SetError(privateKey_error); - return; - } - - length_ = 8; // pLen + gLen + YsLen + SigLen - length_ += pSz + gSz + pubSz + sigSz; - - output_buffer tmp(length_); - byte len[2]; - // P - c16toa(pSz, len); - tmp.write(len, sizeof(len)); - tmp.write(parms_.get_p(), pSz); - // G - c16toa(gSz, len); - tmp.write(len, sizeof(len)); - tmp.write(parms_.get_g(), gSz); - // Ys - c16toa(pubSz, len); - tmp.write(len, sizeof(len)); - tmp.write(parms_.get_pub(), pubSz); - - // Sig - byte hash[FINISHED_SZ]; - MD5 md5; - SHA sha; - signature_ = NEW_YS byte[sigSz]; - - const Connection& conn = ssl.getSecurity().get_connection(); - // md5 - md5.update(conn.client_random_, RAN_LEN); - md5.update(conn.server_random_, RAN_LEN); - md5.update(tmp.get_buffer(), tmp.get_size()); - md5.get_digest(hash); - - // sha - sha.update(conn.client_random_, RAN_LEN); - sha.update(conn.server_random_, RAN_LEN); - sha.update(tmp.get_buffer(), tmp.get_size()); - sha.get_digest(&hash[MD5_LEN]); - - if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { - auth->sign(signature_, hash, sizeof(hash), - ssl.getCrypto().get_random()); - // check for rsa signautre fault - if (!auth->verify(hash, sizeof(hash), signature_, - auth->get_signatureLength())) { - ssl.SetError(rsaSignFault_error); - return; - } - } - else { - auth->sign(signature_, &hash[MD5_LEN], SHA_LEN, - ssl.getCrypto().get_random()); - byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA]; - TaoCrypt::EncodeDSA_Signature(signature_, encoded); - memcpy(signature_, encoded, sizeof(encoded)); - } - - c16toa(sigSz, len); - tmp.write(len, sizeof(len)); - tmp.write(signature_, sigSz); - - // key message - keyMessage_ = NEW_YS opaque[length_]; - memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size()); -} - - -// read PreMaster secret and decrypt, server side -void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - const CertManager& cert = ssl.getCrypto().get_certManager(); - RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false); - uint16 cipherLen = rsa.get_cipherLength(); - if (ssl.isTLS()) { - byte len[2]; - len[0] = input[AUTO]; - len[1] = input[AUTO]; - ato16(len, cipherLen); - } - alloc(cipherLen); - input.read(secret_, length_); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - opaque preMasterSecret[SECRET_LEN]; - memset(preMasterSecret, 0, sizeof(preMasterSecret)); - 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(); -} - - -EncryptedPreMasterSecret::EncryptedPreMasterSecret() - : secret_(0), length_(0) -{} - - -EncryptedPreMasterSecret::~EncryptedPreMasterSecret() -{ - ysArrayDelete(secret_); -} - - -int EncryptedPreMasterSecret::get_length() const -{ - return length_; -} - - -opaque* EncryptedPreMasterSecret::get_clientKey() const -{ - return secret_; -} - - -void EncryptedPreMasterSecret::alloc(int sz) -{ - length_ = sz; - secret_ = NEW_YS opaque[sz]; -} - - -// read client's public key, server side -void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input) -{ - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - - DiffieHellman& dh = ssl.useCrypto().use_dh(); - - uint16 keyLength; - byte tmp[2]; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, keyLength); - - if (keyLength < dh.get_agreedKeyLength()/2) { - ssl.SetError(bad_input); - return; - } - - alloc(keyLength); - input.read(Yc_, keyLength); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - dh.makeAgreement(Yc_, keyLength); - - ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength()); - ssl.makeMasterSecret(); -} - - -ClientDiffieHellmanPublic::ClientDiffieHellmanPublic() - : length_(0), Yc_(0) -{} - - -ClientDiffieHellmanPublic::~ClientDiffieHellmanPublic() -{ - ysArrayDelete(Yc_); -} - - -int ClientDiffieHellmanPublic::get_length() const -{ - return length_; -} - - -opaque* ClientDiffieHellmanPublic::get_clientKey() const -{ - return Yc_; -} - - -void ClientDiffieHellmanPublic::alloc(int sz, bool offset) -{ - length_ = sz + (offset ? KEY_OFFSET : 0); - Yc_ = NEW_YS opaque[length_]; -} - - -// read server's p, g, public key and sig, client side -void DH_Server::read(SSL& ssl, input_buffer& input) -{ - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - uint16 length, messageTotal = 6; // pSz + gSz + pubSz - byte tmp[2]; - - // p - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, length); - messageTotal += length; - - input.read(parms_.alloc_p(length), length); - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - - // g - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, length); - messageTotal += length; - - input.read(parms_.alloc_g(length), length); - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - - // pub - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, length); - messageTotal += length; - - input.read(parms_.alloc_pub(length), length); - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - - // save message for hash verify - input_buffer message(messageTotal); - input.set_current(input.get_current() - messageTotal); - input.read(message.get_buffer(), messageTotal); - message.add_size(messageTotal); - if (input.get_error() || input.get_remaining() < (uint)LENGTH_SZ) { - ssl.SetError(bad_input); - return; - } - - // signature - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, length); - - if (length == 0) { - ssl.SetError(bad_input); - return; - } - signature_ = NEW_YS byte[length]; - input.read(signature_, length); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - // verify signature - byte hash[FINISHED_SZ]; - MD5 md5; - SHA sha; - - const Connection& conn = ssl.getSecurity().get_connection(); - // md5 - md5.update(conn.client_random_, RAN_LEN); - md5.update(conn.server_random_, RAN_LEN); - md5.update(message.get_buffer(), message.get_size()); - md5.get_digest(hash); - - // sha - sha.update(conn.client_random_, RAN_LEN); - sha.update(conn.server_random_, RAN_LEN); - sha.update(message.get_buffer(), message.get_size()); - sha.get_digest(&hash[MD5_LEN]); - - const CertManager& cert = ssl.getCrypto().get_certManager(); - - if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { - RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); - if (!rsa.verify(hash, sizeof(hash), signature_, length)) - ssl.SetError(verify_error); - } - else { - byte decodedSig[DSS_SIG_SZ]; - length = TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, length); - - DSS dss(cert.get_peerKey(), cert.get_peerKeyLength()); - if (!dss.verify(&hash[MD5_LEN], SHA_LEN, decodedSig, length)) - ssl.SetError(verify_error); - } - - // save input - ssl.useCrypto().SetDH(NEW_YS DiffieHellman(parms_.get_p(), - parms_.get_pSize(), parms_.get_g(), parms_.get_gSize(), - parms_.get_pub(), parms_.get_pubSize(), - ssl.getCrypto().get_random())); -} - - -DH_Server::DH_Server() - : signature_(0), length_(0), keyMessage_(0) -{} - - -DH_Server::~DH_Server() -{ - ysArrayDelete(keyMessage_); - ysArrayDelete(signature_); -} - - -int DH_Server::get_length() const -{ - return length_; -} - - -opaque* DH_Server::get_serverKey() const -{ - return keyMessage_; -} - - -// set available suites -Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, - ProtocolVersion pv, bool haveDH) : entity_(ce) -{ - pending_ = true; // suite not set yet - strncpy(cipher_name_, "NONE", 5); - - removeDH_ = !haveDH; // only use on server side for set suites - - if (ciphers.setSuites_) { // use user set list - suites_size_ = ciphers.suiteSz_; - memcpy(suites_, ciphers.suites_, ciphers.suiteSz_); - SetCipherNames(); - } - else - SetSuites(pv, ce == server_end && removeDH_); // defaults - -} - - -void Parameters::SetSuites(ProtocolVersion pv, bool removeDH, bool removeRSA, - bool removeDSA) -{ - int i = 0; - // available suites, best first - // when adding more, make sure cipher_names is updated and - // MAX_CIPHERS is big enough - - if (isTLS(pv)) { - if (!removeDH) { - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; - } - if (!removeDSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA; - } - } - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA; - } - if (!removeDH) { - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; - } - if (!removeDSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA; - } - } - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_AES_128_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160; - } - if (!removeDH) { - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160; - } - if (!removeDSA) { - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_RMD160; - suites_[i++] = 0x00; - suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160; - } - } - } - - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = SSL_RSA_WITH_RC4_128_SHA; - suites_[i++] = 0x00; - suites_[i++] = SSL_RSA_WITH_RC4_128_MD5; - - suites_[i++] = 0x00; - suites_[i++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA; - suites_[i++] = 0x00; - suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA; - } - if (!removeDH) { - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA; - } - if (!removeDSA) { - suites_[i++] = 0x00; - suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA; - } - if (!removeRSA) { - suites_[i++] = 0x00; - suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA; - } - if (!removeDSA) { - suites_[i++] = 0x00; - suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA; - } - } - - suites_size_ = i; - - SetCipherNames(); -} - - -void Parameters::SetCipherNames() -{ - const int suites = suites_size_ / 2; - int pos = 0; - - for (int j = 0; j < suites; j++) { - int index = suites_[j*2 + 1]; // every other suite is suite id - size_t len = strlen(cipher_names[index]) + 1; - strncpy(cipher_list_[pos++], cipher_names[index], len); - } - cipher_list_[pos][0] = 0; -} - - -// input operator for RecordLayerHeader, adjust stream -input_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr) -{ - hdr.type_ = ContentType(input[AUTO]); - hdr.version_.major_ = input[AUTO]; - hdr.version_.minor_ = input[AUTO]; - - // length - byte tmp[2]; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, hdr.length_); - - return input; -} - - -// output operator for RecordLayerHeader -output_buffer& operator<<(output_buffer& output, const RecordLayerHeader& hdr) -{ - output[AUTO] = hdr.type_; - output[AUTO] = hdr.version_.major_; - output[AUTO] = hdr.version_.minor_; - - // length - byte tmp[2]; - c16toa(hdr.length_, tmp); - output[AUTO] = tmp[0]; - output[AUTO] = tmp[1]; - - return output; -} - - -// virtual input operator for Messages -input_buffer& operator>>(input_buffer& input, Message& msg) -{ - return msg.set(input); -} - -// virtual output operator for Messages -output_buffer& operator<<(output_buffer& output, const Message& msg) -{ - return msg.get(output); -} - - -// input operator for HandShakeHeader -input_buffer& operator>>(input_buffer& input, HandShakeHeader& hs) -{ - hs.type_ = HandShakeType(input[AUTO]); - - hs.length_[0] = input[AUTO]; - hs.length_[1] = input[AUTO]; - hs.length_[2] = input[AUTO]; - - return input; -} - - -// output operator for HandShakeHeader -output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr) -{ - output[AUTO] = hdr.type_; - output.write(hdr.length_, sizeof(hdr.length_)); - return output; -} - - -// HandShake Header Processing function -void HandShakeHeader::Process(input_buffer& input, SSL& ssl) -{ - ssl.verifyState(*this); - if (ssl.GetError()) return; - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); - mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_)); - if (!hs.get()) { - ssl.SetError(factory_error); - return; - } - - uint len = c24to32(length_); - if (len > input.get_remaining()) { - ssl.SetError(bad_input); - return; - } - hashHandShake(ssl, input, len); - - hs->set_length(len); - input >> *hs; - hs->Process(input, ssl); -} - - -ContentType HandShakeHeader::get_type() const -{ - return handshake; -} - - -uint16 HandShakeHeader::get_length() const -{ - return c24to32(length_); -} - - -HandShakeType HandShakeHeader::get_handshakeType() const -{ - return type_; -} - - -void HandShakeHeader::set_type(HandShakeType hst) -{ - type_ = hst; -} - - -void HandShakeHeader::set_length(uint32 u32) -{ - c32to24(u32, length_); -} - - -input_buffer& HandShakeHeader::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& HandShakeHeader::get(output_buffer& out) const -{ - return out << *this; -} - - - -int HandShakeBase::get_length() const -{ - return length_; -} - - -void HandShakeBase::set_length(int l) -{ - length_ = l; -} - - -// for building buffer's type field -HandShakeType HandShakeBase::get_type() const -{ - return no_shake; -} - - -input_buffer& HandShakeBase::set(input_buffer& in) -{ - return in; -} - - -output_buffer& HandShakeBase::get(output_buffer& out) const -{ - return out; -} - - -void HandShakeBase::Process(input_buffer&, SSL&) -{} - - -input_buffer& HelloRequest::set(input_buffer& in) -{ - return in; -} - - -output_buffer& HelloRequest::get(output_buffer& out) const -{ - return out; -} - - -void HelloRequest::Process(input_buffer&, SSL&) -{} - - -HandShakeType HelloRequest::get_type() const -{ - return hello_request; -} - - -// input operator for CipherSpec -input_buffer& operator>>(input_buffer& input, ChangeCipherSpec& cs) -{ - cs.type_ = CipherChoice(input[AUTO]); - return input; -} - -// output operator for CipherSpec -output_buffer& operator<<(output_buffer& output, const ChangeCipherSpec& cs) -{ - output[AUTO] = cs.type_; - return output; -} - - -ChangeCipherSpec::ChangeCipherSpec() - : type_(change_cipher_spec_choice) -{} - - -input_buffer& ChangeCipherSpec::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& ChangeCipherSpec::get(output_buffer& out) const -{ - return out << *this; -} - - -ContentType ChangeCipherSpec::get_type() const -{ - return change_cipher_spec; -} - - -uint16 ChangeCipherSpec::get_length() const -{ - return SIZEOF_ENUM; -} - - -// CipherSpec processing handler -void ChangeCipherSpec::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - // detect duplicate change_cipher - if (ssl.getSecurity().get_parms().pending_ == false) { - ssl.order_error(); - return; - } - - ssl.useSecurity().use_parms().pending_ = false; - if (ssl.getSecurity().get_resuming()) { - if (ssl.getSecurity().get_parms().entity_ == client_end) - buildFinished(ssl, ssl.useHashes().use_verify(), server); // server - } - else if (ssl.getSecurity().get_parms().entity_ == server_end) - buildFinished(ssl, ssl.useHashes().use_verify(), client); // client -} - - -Alert::Alert(AlertLevel al, AlertDescription ad) - : level_(al), description_(ad) -{} - - -ContentType Alert::get_type() const -{ - return alert; -} - - -uint16 Alert::get_length() const -{ - return SIZEOF_ENUM * 2; -} - - -input_buffer& Alert::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& Alert::get(output_buffer& out) const -{ - return out << *this; -} - - -// input operator for Alert -input_buffer& operator>>(input_buffer& input, Alert& a) -{ - a.level_ = AlertLevel(input[AUTO]); - a.description_ = AlertDescription(input[AUTO]); - - return input; -} - - -// output operator for Alert -output_buffer& operator<<(output_buffer& output, const Alert& a) -{ - output[AUTO] = a.level_; - output[AUTO] = a.description_; - return output; -} - - -// Alert processing handler -void Alert::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - if (ssl.getSecurity().get_parms().pending_ == false) { // encrypted alert - int aSz = get_length(); // alert size already read on input - opaque verify[SHA_LEN]; - const opaque* data = input.get_buffer() + input.get_current() - aSz; - - if (ssl.isTLS()) - TLS_hmac(ssl, verify, data, aSz, alert, true); - else - hmac(ssl, verify, data, aSz, alert, true); - - // read mac and skip fill - int digestSz = ssl.getCrypto().get_digest().get_digestSize(); - opaque mac[SHA_LEN]; - input.read(mac, digestSz); - - if (ssl.getSecurity().get_parms().cipher_type_ == block) { - int ivExtra = 0; - opaque fill; - - 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]; - } - - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - // verify - if (memcmp(mac, verify, digestSz)) { - ssl.SetError(verify_error); - return; - } - } - if (level_ == fatal) { - ssl.useStates().useRecord() = recordNotReady; - ssl.useStates().useHandShake() = handShakeNotReady; - ssl.SetError(YasslError(description_)); - } -} - - -Data::Data() - : length_(0), buffer_(0), write_buffer_(0) -{} - - -Data::Data(uint16 len, opaque* b) - : length_(len), buffer_(b), write_buffer_(0) -{} - - -void Data::SetData(uint16 len, const opaque* buffer) -{ - length_ = len; - write_buffer_ = buffer; -} - -input_buffer& Data::set(input_buffer& in) -{ - return in; -} - - -output_buffer& Data::get(output_buffer& out) const -{ - return out << *this; -} - - -ContentType Data::get_type() const -{ - return application_data; -} - - -uint16 Data::get_length() const -{ - return length_; -} - - -void Data::set_length(uint16 l) -{ - length_ = l; -} - - -opaque* Data::set_buffer() -{ - return buffer_; -} - - -// output operator for Data -output_buffer& operator<<(output_buffer& output, const Data& data) -{ - output.write(data.write_buffer_, data.length_); - return output; -} - - -// check all bytes for equality -static int constant_compare(const byte* a, const byte* b, int len) -{ - int good = 0; - int bad = 0; - - for (int i = 0; i < len; i++) { - if (a[i] == b[i]) - good++; - else - bad++; - } - - if (good == len) - return 0; - else - return 0 - bad; // failure -} - - -// check bytes for pad value -static int pad_check(const byte* input, byte pad, int len) -{ - int good = 0; - int bad = 0; - - for (int i = 0; i < len; i++) { - if (input[i] == pad) - good++; - else - bad++; - } - - if (good == len) - return 0; - else - return 0 - bad; // failure -} - - -// get number of compression rounds -static inline int get_rounds(int pLen, int padLen, int t) -{ - int roundL1 = 1; // round ups - int roundL2 = 1; - - int L1 = COMPRESS_CONSTANT + pLen - t; - int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t; - - L1 -= COMPRESS_UPPER; - L2 -= COMPRESS_UPPER; - - if ( (L1 % COMPRESS_LOWER) == 0) - roundL1 = 0; - if ( (L2 % COMPRESS_LOWER) == 0) - roundL2 = 0; - - L1 /= COMPRESS_LOWER; - L2 /= COMPRESS_LOWER; - - L1 += roundL1; - L2 += roundL2; - - return L1 - L2; -} - - -// do compression rounds on dummy data -static inline void compress_rounds(SSL& ssl, int rounds, const byte* dummy) -{ - if (rounds) { - Digest* digest = NULL; - - MACAlgorithm ma = ssl.getSecurity().get_parms().mac_algorithm_; - if (ma == sha) - digest = NEW_YS SHA; - else if (ma == md5) - digest = NEW_YS MD5; - else if (ma == rmd) - digest = NEW_YS RMD; - else - return; - - for (int i = 0; i < rounds; i++) - digest->update(dummy, COMPRESS_LOWER); - - ysDelete(digest); - } -} - - -// timing resistant pad verification -static int timing_verify(SSL& ssl, const byte* input, int padLen, int t, - int pLen) -{ - byte verify[SHA_LEN]; - byte dummy[MAX_PAD_SIZE]; - - memset(dummy, 1, sizeof(dummy)); - - if ( (t + padLen + 1) > pLen) { - pad_check(dummy, (byte)padLen, MAX_PAD_SIZE); - if (ssl.isTLS()) - TLS_hmac(ssl, verify, input, pLen - t, application_data, 1); - else - hmac(ssl, verify, input, pLen - t, application_data, 1); - constant_compare(verify, input + pLen - t, t); - - return -1; - } - - if (pad_check(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) { - pad_check(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); - if (ssl.isTLS()) - TLS_hmac(ssl, verify, input, pLen - t, application_data, 1); - else - hmac(ssl, verify, input, pLen - t, application_data, 1); - constant_compare(verify, input + pLen - t, t); - - return -1; - } - - pad_check(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); - if (ssl.isTLS()) - TLS_hmac(ssl, verify, input, pLen - padLen - 1 - t, application_data,1); - else - hmac(ssl, verify, input, pLen - padLen - 1 - t, application_data, 1); - - compress_rounds(ssl, get_rounds(pLen, padLen, t), dummy); - - if (constant_compare(verify, input + (pLen - padLen - 1 - t), t) != 0) - return -1; - - return 0; -} - - -// Process handler for Data -void Data::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - int msgSz = ssl.getSecurity().get_parms().encrypt_size_; - int pad = 0, padSz = 0; - int ivExtra = 0; - int digestSz = ssl.getCrypto().get_digest().get_digestSize(); - const byte* rawData = input.get_buffer() + input.get_current(); - opaque verify[SHA_LEN]; - - if (ssl.getSecurity().get_parms().cipher_type_ == block) { - if (ssl.isTLSv1_1()) // IV - ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); - pad = *(input.get_buffer() + input.get_current() + msgSz -ivExtra - 1); - padSz = 1; - - if (ssl.isTLS()) { - if (timing_verify(ssl, rawData, pad,digestSz, msgSz-ivExtra) != 0) { - ssl.SetError(verify_error); - return; - } - } - else { // SSLv3, some don't do this padding right - int sz3 = msgSz - digestSz - pad - 1; - hmac(ssl, verify, rawData, sz3, application_data, true); - if (constant_compare(verify, rawData + sz3, digestSz) != 0) { - ssl.SetError(verify_error); - return; - } - } - } - else { // stream - int streamSz = msgSz - digestSz; - if (ssl.isTLS()) - TLS_hmac(ssl, verify, rawData, streamSz, application_data, true); - else - hmac(ssl, verify, rawData, streamSz, application_data, true); - if (constant_compare(verify, rawData + streamSz, digestSz) != 0) { - ssl.SetError(verify_error); - return; - } - } - - int dataSz = msgSz - ivExtra - digestSz - pad - padSz; - - if (dataSz < 0 || dataSz > (MAX_RECORD_SIZE + COMPRESS_EXTRA)) { - ssl.SetError(bad_input); - return; - } - - // read data - 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); - } - } - - // advance past mac and fill - input.set_current(input.get_current() + digestSz + pad + padSz); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } -} - - -// virtual input operator for HandShakes -input_buffer& operator>>(input_buffer& input, HandShakeBase& hs) -{ - return hs.set(input); -} - - -// virtual output operator for HandShakes -output_buffer& operator<<(output_buffer& output, const HandShakeBase& hs) -{ - return hs.get(output); -} - - -Certificate::Certificate(const x509* cert) : cert_(cert) -{ - if (cert) - set_length(cert_->get_length() + 2 * CERT_HEADER); // list and cert size - else - set_length(CERT_HEADER); // total blank cert size, just list header -} - - -const opaque* Certificate::get_buffer() const -{ - if (cert_) - return cert_->get_buffer(); - - return NULL; -} - - -// output operator for Certificate -output_buffer& operator<<(output_buffer& output, const Certificate& cert) -{ - uint sz = cert.get_length(); - opaque tmp[CERT_HEADER]; - - if ((int)sz > CERT_HEADER) - sz -= 2 * CERT_HEADER; // actual cert, not including headers - else { - sz = 0; // blank cert case - c32to24(sz, tmp); - output.write(tmp, CERT_HEADER); - - return output; - } - - c32to24(sz + CERT_HEADER, tmp); - output.write(tmp, CERT_HEADER); - c32to24(sz, tmp); - output.write(tmp, CERT_HEADER); - output.write(cert.get_buffer(), sz); - - return output; -} - - -// certificate processing handler -void Certificate::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - CertManager& cm = ssl.useCrypto().use_certManager(); - - uint32 list_sz; - byte tmp[3]; - - if (input.get_remaining() < sizeof(tmp)) { - ssl.SetError(YasslError(bad_input)); - return; - } - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - tmp[2] = input[AUTO]; - c24to32(tmp, list_sz); - - if (list_sz > (uint)MAX_RECORD_SIZE) { // sanity check - ssl.SetError(YasslError(bad_input)); - return; - } - - while (list_sz) { - // cert size - uint32 cert_sz; - - if (input.get_remaining() < sizeof(tmp)) { - ssl.SetError(YasslError(bad_input)); - return; - } - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - tmp[2] = input[AUTO]; - c24to32(tmp, cert_sz); - - if (cert_sz > (uint)MAX_RECORD_SIZE || input.get_remaining() < cert_sz){ - ssl.SetError(YasslError(bad_input)); - return; - } - if (cert_sz) { - x509* myCert; - cm.AddPeerCert(myCert = NEW_YS x509(cert_sz)); - input.read(myCert->use_buffer(), myCert->get_length()); - } - - list_sz -= cert_sz + CERT_HEADER; - } - if (int err = cm.Validate()) - ssl.SetError(YasslError(err)); - else if (ssl.getSecurity().get_parms().entity_ == client_end) - ssl.useStates().useClient() = serverCertComplete; -} - - -Certificate::Certificate() - : cert_(0) -{} - - -input_buffer& Certificate::set(input_buffer& in) -{ - return in; -} - - -output_buffer& Certificate::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType Certificate::get_type() const -{ - return certificate; -} - - -ServerDHParams::ServerDHParams() - : pSz_(0), gSz_(0), pubSz_(0), p_(0), g_(0), Ys_(0) -{} - - -ServerDHParams::~ServerDHParams() -{ - ysArrayDelete(Ys_); - ysArrayDelete(g_); - ysArrayDelete(p_); -} - - -int ServerDHParams::get_pSize() const -{ - return pSz_; -} - - -int ServerDHParams::get_gSize() const -{ - return gSz_; -} - - -int ServerDHParams::get_pubSize() const -{ - return pubSz_; -} - - -const opaque* ServerDHParams::get_p() const -{ - return p_; -} - - -const opaque* ServerDHParams::get_g() const -{ - return g_; -} - - -const opaque* ServerDHParams::get_pub() const -{ - return Ys_; -} - - -opaque* ServerDHParams::alloc_p(int sz) -{ - p_ = NEW_YS opaque[pSz_ = sz]; - return p_; -} - - -opaque* ServerDHParams::alloc_g(int sz) -{ - g_ = NEW_YS opaque[gSz_ = sz]; - return g_; -} - - -opaque* ServerDHParams::alloc_pub(int sz) -{ - Ys_ = NEW_YS opaque[pubSz_ = sz]; - return Ys_; -} - - -int ServerKeyBase::get_length() const -{ - return 0; -} - - -opaque* ServerKeyBase::get_serverKey() const -{ - return 0; -} - - -// input operator for ServerHello -input_buffer& operator>>(input_buffer& input, ServerHello& hello) -{ - // Protocol - hello.server_version_.major_ = input[AUTO]; - hello.server_version_.minor_ = input[AUTO]; - - // Random - input.read(hello.random_, RAN_LEN); - - // Session - hello.id_len_ = input[AUTO]; - if (hello.id_len_ > ID_LEN) { - input.set_error(); - return input; - } - if (hello.id_len_) - input.read(hello.session_id_, hello.id_len_); - - // Suites - hello.cipher_suite_[0] = input[AUTO]; - hello.cipher_suite_[1] = input[AUTO]; - - // Compression - hello.compression_method_ = CompressionMethod(input[AUTO]); - - return input; -} - - -// output operator for ServerHello -output_buffer& operator<<(output_buffer& output, const ServerHello& hello) -{ - // Protocol - output[AUTO] = hello.server_version_.major_; - output[AUTO] = hello.server_version_.minor_; - - // Random - output.write(hello.random_, RAN_LEN); - - // Session - output[AUTO] = hello.id_len_; - output.write(hello.session_id_, ID_LEN); - - // Suites - output[AUTO] = hello.cipher_suite_[0]; - output[AUTO] = hello.cipher_suite_[1]; - - // Compression - output[AUTO] = hello.compression_method_; - - return output; -} - - -// Server Hello processing handler -void ServerHello::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - if (ssl.GetMultiProtocol()) { // SSLv23 support - 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); - return; - } - else if (!ssl.isTLS() && (server_version_.major_ == 3 && - server_version_.minor_ >= 1)) { - ssl.SetError(badVersion_error); - return; - } - if (cipher_suite_[0] != 0x00) { - ssl.SetError(unknown_cipher); - return; - } - ssl.set_pending(cipher_suite_[1]); - ssl.set_random(random_, server_end); - if (id_len_) - ssl.set_sessionID(session_id_); - else - ssl.useSecurity().use_connection().sessionID_Set_ = false; - - if (ssl.getSecurity().get_resuming()) { - if (memcmp(session_id_, ssl.getSecurity().get_resume().GetID(), - ID_LEN) == 0) { - ssl.set_masterSecret(ssl.getSecurity().get_resume().GetSecret()); - if (ssl.isTLS()) - ssl.deriveTLSKeys(); - else - ssl.deriveKeys(); - ssl.useStates().useClient() = serverHelloDoneComplete; - return; - } - else { - 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; -} - - -ServerHello::ServerHello() -{ - memset(random_, 0, RAN_LEN); - memset(session_id_, 0, ID_LEN); -} - - -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); -} - - -input_buffer& ServerHello::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& ServerHello::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType ServerHello::get_type() const -{ - return server_hello; -} - - -const opaque* ServerHello::get_random() const -{ - return random_; -} - - -// Server Hello Done processing handler -void ServerHelloDone::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - ssl.useStates().useClient() = serverHelloDoneComplete; -} - - -ServerHelloDone::ServerHelloDone() -{ - set_length(0); -} - - -input_buffer& ServerHelloDone::set(input_buffer& in) -{ - return in; -} - - -output_buffer& ServerHelloDone::get(output_buffer& out) const -{ - return out; -} - - -HandShakeType ServerHelloDone::get_type() const -{ - return server_hello_done; -} - - -int ClientKeyBase::get_length() const -{ - return 0; -} - - -opaque* ClientKeyBase::get_clientKey() const -{ - return 0; -} - - -// 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]; - - // Random - input.read(hello.random_, RAN_LEN); - - // Session - hello.id_len_ = input[AUTO]; - if (hello.id_len_) input.read(hello.session_id_, ID_LEN); - - // Suites - byte tmp[2]; - uint16 len; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, len); - - hello.suite_len_ = min(len, static_cast<uint16>(MAX_SUITE_SZ)); - input.read(hello.cipher_suites_, hello.suite_len_); - if (len > hello.suite_len_) // ignore extra suites - input.set_current(input.get_current() + len - hello.suite_len_); - - // Compression - hello.comp_len_ = 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; -} - - -// output operaotr for Client Hello -output_buffer& operator<<(output_buffer& output, const ClientHello& hello) -{ - // Protocol - output[AUTO] = hello.client_version_.major_; - output[AUTO] = hello.client_version_.minor_; - - // Random - output.write(hello.random_, RAN_LEN); - - // Session - output[AUTO] = hello.id_len_; - if (hello.id_len_) output.write(hello.session_id_, ID_LEN); - - // Suites - byte tmp[2]; - c16toa(hello.suite_len_, tmp); - output[AUTO] = tmp[0]; - output[AUTO] = tmp[1]; - output.write(hello.cipher_suites_, hello.suite_len_); - - // Compression - output[AUTO] = hello.comp_len_; - output[AUTO] = hello.compression_methods_; - - return output; -} - - -// Client Hello processing handler -void ClientHello::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - // 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 - ssl.useSecurity().use_connection().TurnOffTLS(); - - ProtocolVersion pv = ssl.getSecurity().get_connection().version_; - bool removeDH = ssl.getSecurity().get_parms().removeDH_; - bool removeRSA = false; - bool removeDSA = false; - - const CertManager& cm = ssl.getCrypto().get_certManager(); - if (cm.get_keyType() == rsa_sa_algo) - removeDSA = true; - else - removeRSA = true; - - // reset w/ SSL suites - ssl.useSecurity().use_parms().SetSuites(pv, removeDH, removeRSA, - removeDSA); - } - 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_.minor_ >= 1) { - ssl.SetError(badVersion_error); - return; - } - - ssl.set_random(random_, client_end); - - while (id_len_) { // trying to resume - SSL_SESSION* session = 0; - if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) - session = GetSessions().lookup(session_id_); - if (!session) { - ssl.useLog().Trace("session lookup failed"); - break; - } - ssl.set_session(session); - ssl.useSecurity().set_resuming(true); - ssl.matchSuite(session->GetSuite(), SUITE_LEN); - if (ssl.GetError()) return; - ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); - ssl.set_masterSecret(session->GetSecret()); - - opaque serverRandom[RAN_LEN]; - ssl.getCrypto().get_random().Fill(serverRandom, sizeof(serverRandom)); - ssl.set_random(serverRandom, server_end); - if (ssl.isTLS()) - ssl.deriveTLSKeys(); - else - ssl.deriveKeys(); - ssl.useStates().useServer() = clientKeyExchangeComplete; - return; - } - ssl.matchSuite(cipher_suites_, suite_len_); - if (ssl.GetError()) return; - ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); - - if (compression_methods_ == zlib) - ssl.SetCompression(); - - ssl.useStates().useServer() = clientHelloComplete; -} - - -input_buffer& ClientHello::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& ClientHello::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType ClientHello::get_type() const -{ - return client_hello; -} - - -const opaque* ClientHello::get_random() const -{ - return random_; -} - - -ClientHello::ClientHello() -{ - memset(random_, 0, RAN_LEN); -} - - -ClientHello::ClientHello(ProtocolVersion pv, bool useCompression) - : client_version_(pv), - compression_methods_(useCompression ? zlib : no_compression) -{ - memset(random_, 0, RAN_LEN); -} - - -// output operator for ServerKeyExchange -output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk) -{ - output.write(sk.getKey(), sk.getKeyLength()); - return output; -} - - -// Server Key Exchange processing handler -void ServerKeyExchange::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - createKey(ssl); - if (ssl.GetError()) return; - server_key_->read(ssl, input); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - ssl.useStates().useClient() = serverKeyExchangeComplete; -} - - -ServerKeyExchange::ServerKeyExchange(SSL& ssl) -{ - createKey(ssl); -} - - -ServerKeyExchange::ServerKeyExchange() - : server_key_(0) -{} - - -ServerKeyExchange::~ServerKeyExchange() -{ - ysDelete(server_key_); -} - - -void ServerKeyExchange::build(SSL& ssl) -{ - server_key_->build(ssl); - set_length(server_key_->get_length()); -} - - -const opaque* ServerKeyExchange::getKey() const -{ - return server_key_->get_serverKey(); -} - - -int ServerKeyExchange::getKeyLength() const -{ - return server_key_->get_length(); -} - - -input_buffer& ServerKeyExchange::set(input_buffer& in) -{ - return in; // process does -} - - -output_buffer& ServerKeyExchange::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType ServerKeyExchange::get_type() const -{ - return server_key_exchange; -} - - -// CertificateRequest -CertificateRequest::CertificateRequest() - : typeTotal_(0) -{ - memset(certificate_types_, 0, sizeof(certificate_types_)); -} - - -CertificateRequest::~CertificateRequest() -{ - - STL::for_each(certificate_authorities_.begin(), - certificate_authorities_.end(), - del_ptr_zero()) ; -} - - -void CertificateRequest::Build() -{ - certificate_types_[0] = rsa_sign; - certificate_types_[1] = dss_sign; - - typeTotal_ = 2; - - uint16 authCount = 0; - uint16 authSz = 0; - - for (int j = 0; j < authCount; j++) { - int sz = REQUEST_HEADER + MIN_DIS_SIZE; - DistinguishedName dn; - certificate_authorities_.push_back(dn = NEW_YS byte[sz]); - - opaque tmp[REQUEST_HEADER]; - c16toa(MIN_DIS_SIZE, tmp); - memcpy(dn, tmp, sizeof(tmp)); - - // fill w/ junk for now - memcpy(dn, tmp, MIN_DIS_SIZE); - authSz += sz; - } - - set_length(SIZEOF_ENUM + typeTotal_ + REQUEST_HEADER + authSz); -} - - -input_buffer& CertificateRequest::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& CertificateRequest::get(output_buffer& out) const -{ - return out << *this; -} - - -// input operator for CertificateRequest -input_buffer& operator>>(input_buffer& input, CertificateRequest& request) -{ - // types - request.typeTotal_ = input[AUTO]; - if (request.typeTotal_ > CERT_TYPES) { - input.set_error(); - return input; - } - for (int i = 0; i < request.typeTotal_; i++) - request.certificate_types_[i] = ClientCertificateType(input[AUTO]); - - byte tmp[2]; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - uint16 sz; - ato16(tmp, sz); - - // authorities - while (sz) { - uint16 dnSz; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - ato16(tmp, dnSz); - - input.set_current(input.get_current() + dnSz); - - sz -= dnSz + REQUEST_HEADER; - - if (input.get_error()) - break; - } - - return input; -} - - -// output operator for CertificateRequest -output_buffer& operator<<(output_buffer& output, - const CertificateRequest& request) -{ - // types - output[AUTO] = request.typeTotal_; - for (int i = 0; i < request.typeTotal_; i++) - output[AUTO] = request.certificate_types_[i]; - - // authorities - opaque tmp[REQUEST_HEADER]; - c16toa(request.get_length() - SIZEOF_ENUM - - request.typeTotal_ - REQUEST_HEADER, tmp); - output.write(tmp, sizeof(tmp)); - - STL::list<DistinguishedName>::const_iterator first = - request.certificate_authorities_.begin(); - STL::list<DistinguishedName>::const_iterator last = - request.certificate_authorities_.end(); - while (first != last) { - uint16 sz; - ato16(*first, sz); - output.write(*first, sz + REQUEST_HEADER); - - ++first; - } - - return output; -} - - -// CertificateRequest processing handler -void CertificateRequest::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - CertManager& cm = ssl.useCrypto().use_certManager(); - - cm.setSendVerify(); - if (cm.get_cert() == NULL || cm.get_privateKey() == NULL) - cm.setSendBlankCert(); // send blank cert, OpenSSL requires now -} - - -HandShakeType CertificateRequest::get_type() const -{ - return certificate_request; -} - - -// CertificateVerify -CertificateVerify::CertificateVerify() : signature_(0) -{} - - -CertificateVerify::~CertificateVerify() -{ - ysArrayDelete(signature_); -} - - -void CertificateVerify::Build(SSL& ssl) -{ - build_certHashes(ssl, hashes_); - - uint16 sz = 0; - byte len[VERIFY_HEADER]; - mySTL::auto_array<byte> sig; - - // sign - const CertManager& cert = ssl.getCrypto().get_certManager(); - if (cert.get_keyType() == rsa_sa_algo) { - RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false); - - sz = rsa.get_cipherLength() + VERIFY_HEADER; - sig.reset(NEW_YS byte[sz]); - - c16toa(sz - VERIFY_HEADER, len); - memcpy(sig.get(), len, VERIFY_HEADER); - rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes), - ssl.getCrypto().get_random()); - // check for rsa signautre fault - if (!rsa.verify(hashes_.md5_, sizeof(Hashes), sig.get() + VERIFY_HEADER, - rsa.get_cipherLength())) { - ssl.SetError(rsaSignFault_error); - return; - } - } - else { // DSA - DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false); - - sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER; - sig.reset(NEW_YS byte[sz]); - - c16toa(sz - VERIFY_HEADER, len); - memcpy(sig.get(), len, VERIFY_HEADER); - dss.sign(sig.get() + VERIFY_HEADER, hashes_.sha_, SHA_LEN, - ssl.getCrypto().get_random()); - - byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA]; - TaoCrypt::EncodeDSA_Signature(sig.get() + VERIFY_HEADER, encoded); - memcpy(sig.get() + VERIFY_HEADER, encoded, sizeof(encoded)); - } - set_length(sz); - signature_ = sig.release(); -} - - -input_buffer& CertificateVerify::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& CertificateVerify::get(output_buffer& out) const -{ - return out << *this; -} - - -// input operator for CertificateVerify -input_buffer& operator>>(input_buffer& input, CertificateVerify& request) -{ - byte tmp[VERIFY_HEADER]; - tmp[0] = input[AUTO]; - tmp[1] = input[AUTO]; - - uint16 sz = 0; - ato16(tmp, sz); - request.set_length(sz); - - if (sz == 0) { - input.set_error(); - return input; - } - - request.signature_ = NEW_YS byte[sz]; - input.read(request.signature_, sz); - - return input; -} - - -// output operator for CertificateVerify -output_buffer& operator<<(output_buffer& output, - const CertificateVerify& verify) -{ - output.write(verify.signature_, verify.get_length()); - - return output; -} - - -// CertificateVerify processing handler -void CertificateVerify::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - const Hashes& hashVerify = ssl.getHashes().get_certVerify(); - const CertManager& cert = ssl.getCrypto().get_certManager(); - - if (cert.get_peerKeyType() == rsa_sa_algo) { - RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength()); - - if (!rsa.verify(hashVerify.md5_, sizeof(hashVerify), signature_, - get_length())) - ssl.SetError(verify_error); - } - else { // DSA - byte decodedSig[DSS_SIG_SZ]; - TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, get_length()); - - DSS dss(cert.get_peerKey(), cert.get_peerKeyLength()); - if (!dss.verify(hashVerify.sha_, SHA_LEN, decodedSig, get_length())) - ssl.SetError(verify_error); - } -} - - -HandShakeType CertificateVerify::get_type() const -{ - return certificate_verify; -} - - -// output operator for ClientKeyExchange -output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck) -{ - output.write(ck.getKey(), ck.getKeyLength()); - return output; -} - - -// Client Key Exchange processing handler -void ClientKeyExchange::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - createKey(ssl); - if (ssl.GetError()) return; - client_key_->read(ssl, input); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - if (ssl.getCrypto().get_certManager().verifyPeer()) - build_certHashes(ssl, ssl.useHashes().use_certVerify()); - - ssl.useStates().useServer() = clientKeyExchangeComplete; -} - - -ClientKeyExchange::ClientKeyExchange(SSL& ssl) -{ - createKey(ssl); -} - - -ClientKeyExchange::ClientKeyExchange() - : client_key_(0) -{} - - -ClientKeyExchange::~ClientKeyExchange() -{ - ysDelete(client_key_); -} - - -void ClientKeyExchange::build(SSL& ssl) -{ - client_key_->build(ssl); - set_length(client_key_->get_length()); -} - -const opaque* ClientKeyExchange::getKey() const -{ - return client_key_->get_clientKey(); -} - - -int ClientKeyExchange::getKeyLength() const -{ - return client_key_->get_length(); -} - - -input_buffer& ClientKeyExchange::set(input_buffer& in) -{ - return in; -} - - -output_buffer& ClientKeyExchange::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType ClientKeyExchange::get_type() const -{ - return client_key_exchange; -} - - -// input operator for Finished -input_buffer& operator>>(input_buffer& input, Finished&) -{ - /* do in process */ - - return input; -} - -// output operator for Finished -output_buffer& operator<<(output_buffer& output, const Finished& fin) -{ - if (fin.get_length() == FINISHED_SZ) { - output.write(fin.hashes_.md5_, MD5_LEN); - output.write(fin.hashes_.sha_, SHA_LEN); - } - else // TLS_FINISHED_SZ - output.write(fin.hashes_.md5_, TLS_FINISHED_SZ); - - return output; -} - - -// Finished processing handler -void Finished::Process(input_buffer& input, SSL& ssl) -{ - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - // verify hashes - const Finished& verify = ssl.getHashes().get_verify(); - uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; - - input.read(hashes_.md5_, finishedSz); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - if (memcmp(&hashes_, &verify.hashes_, finishedSz)) { - ssl.SetError(verify_error); - return; - } - - // read verify mac - opaque verifyMAC[SHA_LEN]; - uint macSz = finishedSz + HANDSHAKE_HEADER; - - if (ssl.isTLS()) - TLS_hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - - macSz, macSz, handshake, true); - else - hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - macSz, - macSz, handshake, true); - - // read mac and fill - opaque mac[SHA_LEN]; // max size - int digestSz = ssl.getCrypto().get_digest().get_digestSize(); - input.read(mac, digestSz); - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - 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_ - ivExtra - - HANDSHAKE_HEADER - finishedSz - digestSz; - for (int i = 0; i < padSz; i++) - fill = input[AUTO]; - if (input.get_error()) { - ssl.SetError(bad_input); - return; - } - - // verify mac - if (memcmp(mac, verifyMAC, digestSz)) { - ssl.SetError(verify_error); - return; - } - - // update states - ssl.useStates().useHandShake() = handShakeReady; - if (ssl.getSecurity().get_parms().entity_ == client_end) - ssl.useStates().useClient() = serverFinishedComplete; - else - ssl.useStates().useServer() = clientFinishedComplete; -} - - -Finished::Finished() -{ - set_length(FINISHED_SZ); -} - - -uint8* Finished::set_md5() -{ - return hashes_.md5_; -} - - -uint8* Finished::set_sha() -{ - return hashes_.sha_; -} - - -input_buffer& Finished::set(input_buffer& in) -{ - return in >> *this; -} - - -output_buffer& Finished::get(output_buffer& out) const -{ - return out << *this; -} - - -HandShakeType Finished::get_type() const -{ - return finished; -} - - -void clean(volatile opaque* p, uint sz, RandomPool& ran) -{ - uint i(0); - - for (i = 0; i < sz; ++i) - p[i] = 0; - - ran.Fill(const_cast<opaque*>(p), sz); - - for (i = 0; i < sz; ++i) - p[i] = 0; -} - - - -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), - TLSv1_1_(v.major_ >= 3 && v.minor_ >= 2), compression_(false), - version_(v), random_(ran) -{ - memset(sessionID_, 0, sizeof(sessionID_)); -} - - -Connection::~Connection() -{ - CleanMaster(); CleanPreMaster(); ysArrayDelete(pre_master_secret_); -} - - -void Connection::AllocPreSecret(uint sz) -{ - pre_master_secret_ = NEW_YS opaque[pre_secret_len_ = sz]; -} - - -void Connection::TurnOffTLS() -{ - TLS_ = false; - version_.minor_ = 0; -} - - -void Connection::TurnOffTLS1_1() -{ - TLSv1_1_ = false; - version_.minor_ = 1; -} - - -// wipeout master secret -void Connection::CleanMaster() -{ - if (!master_clean_) { - volatile opaque* p = master_secret_; - clean(p, SECRET_LEN, random_); - master_clean_ = true; - } -} - - -// wipeout pre master secret -void Connection::CleanPreMaster() -{ - if (pre_master_secret_) { - volatile opaque* p = pre_master_secret_; - clean(p, pre_secret_len_, random_); - - ysArrayDelete(pre_master_secret_); - pre_master_secret_ = 0; - } -} - - -// Create functions for message factory -Message* CreateCipherSpec() { return NEW_YS ChangeCipherSpec; } -Message* CreateAlert() { return NEW_YS Alert; } -Message* CreateHandShake() { return NEW_YS HandShakeHeader; } -Message* CreateData() { return NEW_YS Data; } - -// Create functions for handshake factory -HandShakeBase* CreateHelloRequest() { return NEW_YS HelloRequest; } -HandShakeBase* CreateClientHello() { return NEW_YS ClientHello; } -HandShakeBase* CreateServerHello() { return NEW_YS ServerHello; } -HandShakeBase* CreateCertificate() { return NEW_YS Certificate; } -HandShakeBase* CreateServerKeyExchange() { return NEW_YS ServerKeyExchange;} -HandShakeBase* CreateCertificateRequest() { return NEW_YS - CertificateRequest; } -HandShakeBase* CreateServerHelloDone() { return NEW_YS ServerHelloDone; } -HandShakeBase* CreateCertificateVerify() { return NEW_YS CertificateVerify;} -HandShakeBase* CreateClientKeyExchange() { return NEW_YS ClientKeyExchange;} -HandShakeBase* CreateFinished() { return NEW_YS Finished; } - -// Create functions for server key exchange factory -ServerKeyBase* CreateRSAServerKEA() { return NEW_YS RSA_Server; } -ServerKeyBase* CreateDHServerKEA() { return NEW_YS DH_Server; } -ServerKeyBase* CreateFortezzaServerKEA() { return NEW_YS Fortezza_Server; } - -// Create functions for client key exchange factory -ClientKeyBase* CreateRSAClient() { return NEW_YS - EncryptedPreMasterSecret; } -ClientKeyBase* CreateDHClient() { return NEW_YS - ClientDiffieHellmanPublic; } -ClientKeyBase* CreateFortezzaClient() { return NEW_YS FortezzaKeys; } - - -// Constructor calls this to Register compile time callbacks -void InitMessageFactory(MessageFactory& mf) -{ - mf.Reserve(4); - mf.Register(alert, CreateAlert); - mf.Register(change_cipher_spec, CreateCipherSpec); - mf.Register(handshake, CreateHandShake); - mf.Register(application_data, CreateData); -} - - -// Constructor calls this to Register compile time callbacks -void InitHandShakeFactory(HandShakeFactory& hsf) -{ - hsf.Reserve(10); - hsf.Register(hello_request, CreateHelloRequest); - hsf.Register(client_hello, CreateClientHello); - hsf.Register(server_hello, CreateServerHello); - hsf.Register(certificate, CreateCertificate); - hsf.Register(server_key_exchange, CreateServerKeyExchange); - hsf.Register(certificate_request, CreateCertificateRequest); - hsf.Register(server_hello_done, CreateServerHelloDone); - hsf.Register(certificate_verify, CreateCertificateVerify); - hsf.Register(client_key_exchange, CreateClientKeyExchange); - hsf.Register(finished, CreateFinished); -} - - -// Constructor calls this to Register compile time callbacks -void InitServerKeyFactory(ServerKeyFactory& skf) -{ - skf.Reserve(3); - skf.Register(rsa_kea, CreateRSAServerKEA); - skf.Register(diffie_hellman_kea, CreateDHServerKEA); - skf.Register(fortezza_kea, CreateFortezzaServerKEA); -} - - -// Constructor calls this to Register compile time callbacks -void InitClientKeyFactory(ClientKeyFactory& ckf) -{ - ckf.Reserve(3); - ckf.Register(rsa_kea, CreateRSAClient); - ckf.Register(diffie_hellman_kea, CreateDHClient); - ckf.Register(fortezza_kea, CreateFortezzaClient); -} - - -} // namespace |