📄 yassl_imp.cpp
字号:
/* yassl_imp.cpp * * Copyright (C) 2003 Sawtooth Consulting Ltd. * * This file is part of yaSSL. * * yaSSL 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; either version 2 of the License, or * (at your option) any later version. * * yaSSL 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 { // localsbool 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 parmsvoid 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 parmsvoid 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 sidevoid 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_; 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 sidevoid 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()); c16toa(keyLength, Yc_); memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength); ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);}// build server exhange, server sidevoid 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(ysDelete); const CertManager& cert = ssl.getCrypto().get_certManager(); if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) auth.reset(new (ys) RSA(cert.get_privateKey(), cert.get_privateKeyLength(), false)); else { auth.reset(new (ys) DSS(cert.get_privateKey(), cert.get_privateKeyLength(), false)); sigSz += DSS_ENCODED_EXTRA; } sigSz += auth->get_signatureLength(); 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()); 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 sidevoid EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input){ 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]; input.read(len, sizeof(len)); ato16(len, cipherLen); } alloc(cipherLen); input.read(secret_, length_); opaque preMasterSecret[SECRET_LEN]; rsa.decrypt(preMasterSecret, secret_, length_, ssl.getCrypto().get_random()); 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 sidevoid ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input){ DiffieHellman& dh = ssl.useCrypto().use_dh(); uint16 keyLength; byte tmp[2]; tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; ato16(tmp, keyLength); alloc(keyLength); input.read(Yc_, length_); dh.makeAgreement(Yc_); ssl.set_preMaster(dh.get_agreedKey(), keyLength); 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 sidevoid DH_Server::read(SSL& ssl, input_buffer& input){ 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); // g tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; ato16(tmp, length); messageTotal += length; input.read(parms_.alloc_g(length), length); // pub tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; ato16(tmp, length); messageTotal += length; input.read(parms_.alloc_pub(length), length); // 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); // signature tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; ato16(tmp, length); signature_ = new (ys) byte[length]; input.read(signature_, length); // 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 suitesParameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, ProtocolVersion pv) : entity_(ce){ pending_ = true; // suite not set yet if (ciphers.setSuites_) { // use user set list suites_size_ = ciphers.suiteSz_; memcpy(suites_, ciphers.suites_, ciphers.suiteSz_); SetCipherNames(); } else SetSuites(pv); // defaults}void Parameters::SetSuites(ProtocolVersion pv){ int i = 0; // available suites, best first // when adding more, make sure cipher_names is updated and // MAX_CIPHER_LIST is big enough if (isTLS(pv)) { suites_[i++] = 0x00; suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_DHE_DSS_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; 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; 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; } 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; suites_[i++] = 0x00; suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA; 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 int len = strlen(cipher_names[index]); memcpy(&cipher_list_[pos], cipher_names[index], len); pos += len; cipher_list_[pos++] = ':'; } if (suites) cipher_list_[--pos] = 0;}// input operator for RecordLayerHeader, adjust streaminput_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -