📄 handshake.cpp
字号:
else
side = tls_server;
PRF(fin.set_md5(), TLS_FINISHED_SZ,
ssl.getSecurity().get_connection().master_secret_, SECRET_LEN,
side, FINISHED_LABEL_SZ,
handshake_hash, FINISHED_SZ);
fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS
}
// compute p_hash for MD5 or SHA-1 for TLSv1 PRF
void p_hash(output_buffer& result, const output_buffer& secret,
const output_buffer& seed, MACAlgorithm hash)
{
uint len = hash == md5 ? MD5_LEN : SHA_LEN;
uint times = result.get_capacity() / len;
uint lastLen = result.get_capacity() % len;
opaque previous[SHA_LEN]; // max size
opaque current[SHA_LEN]; // max size
mySTL::auto_ptr<Digest> hmac(ysDelete);
if (lastLen) times += 1;
if (hash == md5)
hmac.reset(NEW_YS HMAC_MD5(secret.get_buffer(), secret.get_size()));
else
hmac.reset(NEW_YS HMAC_SHA(secret.get_buffer(), secret.get_size()));
// A0 = seed
hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1
uint lastTime = times - 1;
for (uint i = 0; i < times; i++) {
hmac->update(previous, len);
hmac->get_digest(current, seed.get_buffer(), seed.get_size());
if (lastLen && (i == lastTime))
result.write(current, lastLen);
else {
result.write(current, len);
//memcpy(previous, current, len);
hmac->get_digest(previous, previous, len);
}
}
}
// calculate XOR for TLSv1 PRF
void get_xor(byte *digest, uint digLen, output_buffer& md5,
output_buffer& sha)
{
for (uint i = 0; i < digLen; i++)
digest[i] = md5[AUTO] ^ sha[AUTO];
}
// build MD5 part of certificate verify
void buildMD5_CertVerify(SSL& ssl, byte* digest)
{
opaque md5_result[MD5_LEN];
opaque md5_inner[SECRET_LEN + PAD_MD5];
opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
const opaque* master_secret =
ssl.getSecurity().get_connection().master_secret_;
// make md5 inner
memcpy(md5_inner, master_secret, SECRET_LEN);
memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5);
ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
sizeof(md5_inner));
// make md5 outer
memcpy(md5_outer, master_secret, SECRET_LEN);
memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer));
}
// build SHA part of certificate verify
void buildSHA_CertVerify(SSL& ssl, byte* digest)
{
opaque sha_result[SHA_LEN];
opaque sha_inner[SECRET_LEN + PAD_SHA];
opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
const opaque* master_secret =
ssl.getSecurity().get_connection().master_secret_;
// make sha inner
memcpy(sha_inner, master_secret, SECRET_LEN);
memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA);
ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
sizeof(sha_inner));
// make sha outer
memcpy(sha_outer, master_secret, SECRET_LEN);
memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer));
}
} // namespace for locals
// some clients still send sslv2 client hello
void ProcessOldClientHello(input_buffer& input, SSL& ssl)
{
byte b0 = input[AUTO];
byte b1 = input[AUTO];
uint16 sz = ((b0 & 0x7f) << 8) | b1;
// hashHandShake manually
const opaque* buffer = input.get_buffer() + input.get_current();
ssl.useHashes().use_MD5().update(buffer, sz);
ssl.useHashes().use_SHA().update(buffer, sz);
b1 = input[AUTO]; // does this value mean client_hello?
ClientHello ch;
ch.client_version_.major_ = input[AUTO];
ch.client_version_.minor_ = input[AUTO];
byte len[2];
input.read(len, sizeof(len));
ato16(len, ch.suite_len_);
input.read(len, sizeof(len));
uint16 sessionLen;
ato16(len, sessionLen);
ch.id_len_ = sessionLen;
input.read(len, sizeof(len));
uint16 randomLen;
ato16(len, randomLen);
int j = 0;
for (uint16 i = 0; i < ch.suite_len_; i += 3) {
byte first = input[AUTO];
if (first) // sslv2 type
input.read(len, SUITE_LEN); // skip
else {
input.read(&ch.cipher_suites_[j], SUITE_LEN);
j += SUITE_LEN;
}
}
ch.suite_len_ = j;
if (ch.id_len_)
input.read(ch.session_id_, ch.id_len_);
if (randomLen < RAN_LEN)
memset(ch.random_, 0, RAN_LEN - randomLen);
input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
ch.Process(input, ssl);
}
// Build a finished message, see 7.6.9
void buildFinished(SSL& ssl, Finished& fin, const opaque* sender)
{
// store current states, building requires get_digest which resets state
MD5 md5(ssl.getHashes().get_MD5());
SHA sha(ssl.getHashes().get_SHA());
if (ssl.isTLS())
buildFinishedTLS(ssl, fin, sender);
else {
buildMD5(ssl, fin, sender);
buildSHA(ssl, fin, sender);
}
// restore
ssl.useHashes().use_MD5() = md5;
ssl.useHashes().use_SHA() = sha;
}
/* compute SSLv3 HMAC into digest see
* buffer is of sz size and includes HandShake Header but not a Record Header
* verify means to check peers hmac
*/
void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
ContentType content, bool verify)
{
Digest& mac = ssl.useCrypto().use_digest();
opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ];
opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN];
opaque result[SHA_LEN]; // max possible sizes
uint digestSz = mac.get_digestSize(); // actual sizes
uint padSz = mac.get_padSize();
uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ;
uint outerSz = digestSz + padSz + digestSz;
// data
const opaque* mac_secret = ssl.get_macSecret(verify);
opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
opaque length[LENGTH_SZ];
c16toa(sz, length);
c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
// make inner
memcpy(inner, mac_secret, digestSz);
memcpy(&inner[digestSz], PAD1, padSz);
memcpy(&inner[digestSz + padSz], seq, SEQ_SZ);
inner[digestSz + padSz + SEQ_SZ] = content;
memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ);
mac.update(inner, innerSz);
mac.get_digest(result, buffer, sz); // append content buffer
// make outer
memcpy(outer, mac_secret, digestSz);
memcpy(&outer[digestSz], PAD2, padSz);
memcpy(&outer[digestSz + padSz], result, digestSz);
mac.get_digest(digest, outer, outerSz);
}
// TLS type HAMC
void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
ContentType content, bool verify)
{
mySTL::auto_ptr<Digest> hmac(ysDelete);
opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
opaque length[LENGTH_SZ];
opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len
c16toa(sz, length);
c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
if (algo == sha)
hmac.reset(NEW_YS HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
else if (algo == rmd)
hmac.reset(NEW_YS HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN));
else
hmac.reset(NEW_YS HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
hmac->update(seq, SEQ_SZ); // seq_num
inner[0] = content; // type
inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_;
inner[SIZEOF_ENUM + SIZEOF_ENUM] =
ssl.getSecurity().get_connection().version_.minor_; // version
memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length
hmac->update(inner, sizeof(inner));
hmac->get_digest(digest, buffer, sz); // content
}
// compute TLSv1 PRF (pseudo random function using HMAC)
void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
const byte* label, uint labLen, const byte* seed, uint seedLen)
{
uint half = (secLen + 1) / 2;
output_buffer md5_half(half);
output_buffer sha_half(half);
output_buffer labelSeed(labLen + seedLen);
md5_half.write(secret, half);
sha_half.write(secret + half - secLen % 2, half);
labelSeed.write(label, labLen);
labelSeed.write(seed, seedLen);
output_buffer md5_result(digLen);
output_buffer sha_result(digLen);
p_hash(md5_result, md5_half, labelSeed, md5);
p_hash(sha_result, sha_half, labelSeed, sha);
md5_result.set_current(0);
sha_result.set_current(0);
get_xor(digest, digLen, md5_result, sha_result);
}
// build certificate hashes
void build_certHashes(SSL& ssl, Hashes& hashes)
{
// store current states, building requires get_digest which resets state
MD5 md5(ssl.getHashes().get_MD5());
SHA sha(ssl.getHashes().get_SHA());
if (ssl.isTLS()) {
ssl.useHashes().use_MD5().get_digest(hashes.md5_);
ssl.useHashes().use_SHA().get_digest(hashes.sha_);
}
else {
buildMD5_CertVerify(ssl, hashes.md5_);
buildSHA_CertVerify(ssl, hashes.sha_);
}
// restore
ssl.useHashes().use_MD5() = md5;
ssl.useHashes().use_SHA() = sha;
}
mySTL::auto_ptr<input_buffer> null_buffer(ysDelete);
// do process input requests
mySTL::auto_ptr<input_buffer>
DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
{
// wait for input if blocking
if (!ssl.getSocket().wait()) {
ssl.SetError(receive_error);
return buffered = null_buffer;
}
uint ready = ssl.getSocket().get_ready();
if (!ready) return buffered;
// add buffered data if its there
uint buffSz = buffered.get() ? buffered.get()->get_size() : 0;
input_buffer buffer(buffSz + ready);
if (buffSz) {
buffer.assign(buffered.get()->get_buffer(), buffSz);
buffered = null_buffer;
}
// add NEW_YS data
uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
buffer.add_size(read);
uint offset = 0;
const MessageFactory& mf = ssl.getFactory().getMessage();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -