📄 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 { // 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().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 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(), keyLength);
c16toa(keyLength, Yc_);
memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
// because of encoding first byte might be zero, don't use it for preMaster
if (*dhClient.get_agreedKey() == 0)
ssl.set_preMaster(dhClient.get_agreedKey() + 1, keyLength - 1);
else
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(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 side
void 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 side
void 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_, keyLength);
dh.makeAgreement(Yc_, keyLength);
// because of encoding, first byte might be 0, don't use for preMaster
if (*dh.get_agreedKey() == 0)
ssl.set_preMaster(dh.get_agreedKey() + 1, dh.get_agreedKeyLength() - 1);
else
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)
{
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 suites
Parameters::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_CIPHERS 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]) + 1;
strncpy(cipher_list_[pos++], cipher_names[index], len);
}
cipher_list_[pos][0] = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -