// send finished void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) { if (ssl.GetError()) return; Finished fin; buildFinished(ssl, fin, side == client_end ? client : server); mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer); cipherFinished(ssl, fin, *out.get()); // hashes handshake if (ssl.getSecurity().get_resuming()) { if (side == server_end) buildFinished(ssl, ssl.useHashes().use_verify(), client); // client } else { if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) GetSessions().add(ssl); // store session if (side == client_end) buildFinished(ssl, ssl.useHashes().use_verify(), server); // server } ssl.useSecurity().use_connection().CleanMaster(); if (buffer == buffered) ssl.addBuffer(out.release()); else ssl.Send(out->get_buffer(), out->get_size()); }
// add handshake from buffer into md5 and sha hashes, use handshake header void 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); }
// 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; }
// 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; }
// some clients still send sslv2 client hello void ProcessOldClientHello(input_buffer& input, SSL& ssl) { if (input.get_error() || input.get_remaining() < 2) { ssl.SetError(bad_input); return; } byte b0 = input[AUTO]; byte b1 = input[AUTO]; uint16 sz = ((b0 & 0x7f) << 8) | b1; if (sz > input.get_remaining()) { ssl.SetError(bad_input); return; } // 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]; len[0] = input[AUTO]; len[1] = input[AUTO]; ato16(len, ch.suite_len_); len[0] = input[AUTO]; len[1] = input[AUTO]; uint16 sessionLen; ato16(len, sessionLen); ch.id_len_ = sessionLen; len[0] = input[AUTO]; len[1] = input[AUTO]; uint16 randomLen; ato16(len, randomLen); if (input.get_error() || ch.suite_len_ > MAX_SUITE_SZ || ch.suite_len_ > input.get_remaining() || sessionLen > ID_LEN || randomLen > RAN_LEN) { ssl.SetError(bad_input); return; } 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_); // id_len_ from sessionLen if (randomLen < RAN_LEN) memset(ch.random_, 0, RAN_LEN - randomLen); input.read(&ch.random_[RAN_LEN - randomLen], randomLen); ch.Process(input, ssl); }