📄 handshake.cpp
字号:
/* handshake.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 *//* The handshake source implements functions for creating and reading * the various handshake messages. */#include "runtime.hpp"#include "handshake.hpp"#include "yassl_int.hpp"namespace yaSSL {using mySTL::min;// Build a client hello message from cipher suites and compression methodvoid buildClientHello(SSL& ssl, ClientHello& hello, CompressionMethod compression = no_compression){ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN); if (ssl.getSecurity().get_resuming()) { hello.id_len_ = ID_LEN; memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(), ID_LEN); } else hello.id_len_ = 0; hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_; memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_, hello.suite_len_); hello.comp_len_ = 1; hello.compression_methods_ = compression; hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + hello.id_len_ + sizeof(hello.id_len_) + hello.suite_len_ + sizeof(hello.suite_len_) + hello.comp_len_ + sizeof(hello.comp_len_));}// Build a server hello messagevoid buildServerHello(SSL& ssl, ServerHello& hello){ if (ssl.getSecurity().get_resuming()) { memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_, RAN_LEN); memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(), ID_LEN); } else { ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN); ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN); } hello.id_len_ = ID_LEN; ssl.set_sessionID(hello.session_id_); hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0]; hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1]; hello.compression_method_ = no_compression; hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN + sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);}// add handshake from buffer into md5 and sha hashes, use handshake headervoid hashHandShake(SSL& ssl, const input_buffer& input, uint sz){ const opaque* buffer = input.get_buffer() + input.get_current() - HANDSHAKE_HEADER; sz += HANDSHAKE_HEADER; ssl.useHashes().use_MD5().update(buffer, sz); ssl.useHashes().use_SHA().update(buffer, sz);}// localsnamespace {// Write a plaintext record to buffervoid buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr, const Message& msg){ buffer.allocate(RECORD_HEADER + rlHdr.length_); buffer << rlHdr << msg;}// Write a plaintext record to buffervoid buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr, const HandShakeHeader& hsHdr, const HandShakeBase& shake){ buffer.allocate(RECORD_HEADER + rlHdr.length_); buffer << rlHdr << hsHdr << shake;}// Build Record Layer header for Message without handshake headervoid buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg){ ProtocolVersion pv = ssl.getSecurity().get_connection().version_; rlHeader.type_ = msg.get_type(); rlHeader.version_.major_ = pv.major_; rlHeader.version_.minor_ = pv.minor_; rlHeader.length_ = msg.get_length();}// Build HandShake and RecordLayer Headers for handshake outputvoid buildHeaders(SSL& ssl, HandShakeHeader& hsHeader, RecordLayerHeader& rlHeader, const HandShakeBase& shake){ int sz = shake.get_length(); hsHeader.set_type(shake.get_type()); hsHeader.set_length(sz); ProtocolVersion pv = ssl.getSecurity().get_connection().version_; rlHeader.type_ = handshake; rlHeader.version_.major_ = pv.major_; rlHeader.version_.minor_ = pv.minor_; rlHeader.length_ = sz + HANDSHAKE_HEADER;}// add handshake from buffer into md5 and sha hashes, exclude record headervoid hashHandShake(SSL& ssl, const output_buffer& output){ uint sz = output.get_size() - RECORD_HEADER; const opaque* buffer = output.get_buffer() + RECORD_HEADER; ssl.useHashes().use_MD5().update(buffer, sz); ssl.useHashes().use_SHA().update(buffer, sz);}// calculate MD5 hash for finishedvoid buildMD5(SSL& ssl, Finished& fin, const opaque* sender){ opaque md5_result[MD5_LEN]; opaque md5_inner[SIZEOF_SENDER + 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, sender, SIZEOF_SENDER); memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN); memcpy(&md5_inner[SIZEOF_SENDER + 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(fin.set_md5(), md5_outer, sizeof(md5_outer));}// calculate SHA hash for finishedvoid buildSHA(SSL& ssl, Finished& fin, const opaque* sender){ opaque sha_result[SHA_LEN]; opaque sha_inner[SIZEOF_SENDER + 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, sender, SIZEOF_SENDER); memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN); memcpy(&sha_inner[SIZEOF_SENDER + 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(fin.set_sha(), sha_outer, sizeof(sha_outer));}// decrypt input message in place, store size in case needed latervoid decrypt_message(SSL& ssl, input_buffer& input, uint sz){ input_buffer plain(sz); opaque* cipher = input.get_buffer() + input.get_current(); ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz); memcpy(cipher, plain.get_buffer(), sz); ssl.useSecurity().use_parms().encrypt_size_ = sz;}// write headers, handshake hash, mac, pad, and encryptvoid cipherFinished(SSL& ssl, Finished& fin, output_buffer& output){ uint digestSz = ssl.getCrypto().get_digest().get_digestSize(); uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz; uint pad = 0; if (ssl.getSecurity().get_parms().cipher_type_ == block) { sz += 1; // pad byte uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); pad = (sz - RECORD_HEADER) % blockSz; pad = blockSz - pad; sz += pad; } RecordLayerHeader rlHeader; HandShakeHeader hsHeader; buildHeaders(ssl, hsHeader, rlHeader, fin); rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac // and pad, hanshake doesn't output.allocate(sz); output << rlHeader << hsHeader << fin; hashHandShake(ssl, output); opaque digest[SHA_LEN]; // max size if (ssl.isTLS()) TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, handshake); else hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, handshake); output.write(digest, digestSz); if (ssl.getSecurity().get_parms().cipher_type_ == block) for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets // pad value too input_buffer cipher(rlHeader.length_); ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(), output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER); output.set_current(RECORD_HEADER); output.write(cipher.get_buffer(), cipher.get_capacity());}// build an encrypted data or alert message for outputvoid buildMessage(SSL& ssl, output_buffer& output, const Message& msg){ uint digestSz = ssl.getCrypto().get_digest().get_digestSize(); uint sz = RECORD_HEADER + msg.get_length() + digestSz; uint pad = 0; if (ssl.getSecurity().get_parms().cipher_type_ == block) { sz += 1; // pad byte uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); pad = (sz - RECORD_HEADER) % blockSz; pad = blockSz - pad; sz += pad; } RecordLayerHeader rlHeader; buildHeader(ssl, rlHeader, msg); rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac // and pad, hanshake doesn't output.allocate(sz); output << rlHeader << msg; opaque digest[SHA_LEN]; // max size if (ssl.isTLS()) TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, msg.get_type()); else hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, msg.get_type()); output.write(digest, digestSz); if (ssl.getSecurity().get_parms().cipher_type_ == block) for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets // pad value too input_buffer cipher(rlHeader.length_); ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(), output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER); output.set_current(RECORD_HEADER); output.write(cipher.get_buffer(), cipher.get_capacity());}// build alert messagevoid buildAlert(SSL& ssl, output_buffer& output, const Alert& alert){ if (ssl.getSecurity().get_parms().pending_ == false) // encrypted buildMessage(ssl, output, alert); else { RecordLayerHeader rlHeader; buildHeader(ssl, rlHeader, alert); buildOutput(output, rlHeader, alert); }}// build TLS finished messagevoid buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender) { opaque handshake_hash[FINISHED_SZ]; ssl.useHashes().use_MD5().get_digest(handshake_hash); ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]); const opaque* side; if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) side = tls_client; else side = tls_server;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -