diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-04-25 05:07:24 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-02 12:24:10 +0200 |
commit | bb46e5f608cee772896ae4ac8ae69318e9edab1a (patch) | |
tree | facb54846664faff33507b5f834fdeeb48974e22 /Libraries | |
parent | 43a49f5fff72b519bdc3a87f0df610bcd9f405bf (diff) | |
download | serenity-bb46e5f608cee772896ae4ac8ae69318e9edab1a.zip |
LibTLS: Switch to Hash::Manager for hashing and add SHA1
Now we can talk to google.com
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibCrypto/Hash/HashManager.h | 84 | ||||
-rw-r--r-- | Libraries/LibCrypto/Hash/SHA1.h | 2 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpsJob.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibTLS/TLSv12.cpp | 47 | ||||
-rw-r--r-- | Libraries/LibTLS/TLSv12.h | 45 |
5 files changed, 102 insertions, 78 deletions
diff --git a/Libraries/LibCrypto/Hash/HashManager.h b/Libraries/LibCrypto/Hash/HashManager.h index fb01db77b9..94e3b7f375 100644 --- a/Libraries/LibCrypto/Hash/HashManager.h +++ b/Libraries/LibCrypto/Hash/HashManager.h @@ -27,6 +27,7 @@ #pragma once #include <AK/Optional.h> +#include <AK/OwnPtr.h> #include <LibCrypto/Hash/HashFunction.h> #include <LibCrypto/Hash/MD5.h> #include <LibCrypto/Hash/SHA1.h> @@ -124,7 +125,7 @@ public: Manager(const Manager& other) // NOT a copy constructor! { m_pre_init_buffer = ByteBuffer::create_zeroed(0); // will not be used - initialise(other.m_kind); + initialize(other.m_kind); } Manager(HashKind kind) @@ -135,6 +136,10 @@ public: ~Manager() { + m_sha1 = nullptr; + m_sha256 = nullptr; + m_sha512 = nullptr; + m_md5 = nullptr; } virtual void update(const ByteBuffer& buffer) override { update(buffer.data(), buffer.size()); }; @@ -143,13 +148,13 @@ public: { switch (m_kind) { case HashKind::MD5: - return md5.value().digest_size(); + return m_md5->digest_size(); case HashKind::SHA1: - return sha1.value().digest_size(); + return m_sha1->digest_size(); case HashKind::SHA256: - return sha256.value().digest_size(); + return m_sha256->digest_size(); case HashKind::SHA512: - return sha512.value().digest_size(); + return m_sha512->digest_size(); default: case HashKind::None: return 0; @@ -180,16 +185,16 @@ public: m_kind = kind; switch (kind) { case HashKind::MD5: - md5 = MD5 {}; + m_md5 = make<MD5>(); break; case HashKind::SHA1: - sha1 = SHA1 {}; + m_sha1 = make<SHA1>(); break; case HashKind::SHA256: - sha256 = SHA256 {}; + m_sha256 = make<SHA256>(); break; case HashKind::SHA512: - sha512 = SHA512 {}; + m_sha512 = make<SHA512>(); break; default: case HashKind::None: @@ -199,46 +204,48 @@ public: virtual void update(const u8* data, size_t length) override { + auto size = m_pre_init_buffer.size(); switch (m_kind) { case HashKind::MD5: - if (m_pre_init_buffer.size()) - md5.value().update(m_pre_init_buffer); - md5.value().update(data, length); + if (size) + m_md5->update(m_pre_init_buffer); + m_md5->update(data, length); break; case HashKind::SHA1: - if (m_pre_init_buffer.size()) - sha1.value().update(m_pre_init_buffer); - sha1.value().update(data, length); + if (size) + m_sha1->update(m_pre_init_buffer); + m_sha1->update(data, length); break; case HashKind::SHA256: - if (m_pre_init_buffer.size()) - sha256.value().update(m_pre_init_buffer); - sha256.value().update(data, length); + if (size) + m_sha256->update(m_pre_init_buffer); + m_sha256->update(data, length); break; case HashKind::SHA512: - if (m_pre_init_buffer.size()) - sha512.value().update(m_pre_init_buffer); - sha512.value().update(data, length); + if (size) + m_sha512->update(m_pre_init_buffer); + m_sha512->update(data, length); break; default: case HashKind::None: m_pre_init_buffer.append(data, length); return; } - m_pre_init_buffer.clear(); + if (size) + m_pre_init_buffer.clear(); } virtual DigestType peek() override { switch (m_kind) { case HashKind::MD5: - return { md5.value().peek() }; + return { m_md5->peek() }; case HashKind::SHA1: - return { sha1.value().peek() }; + return { m_sha1->peek() }; case HashKind::SHA256: - return { sha256.value().peek() }; + return { m_sha256->peek() }; case HashKind::SHA512: - return { sha512.value().peek() }; + return { m_sha512->peek() }; default: case HashKind::None: ASSERT_NOT_REACHED(); @@ -255,18 +262,19 @@ public: virtual void reset() override { + m_pre_init_buffer.clear(); switch (m_kind) { case HashKind::MD5: - md5.value().reset(); + m_md5->reset(); break; case HashKind::SHA1: - sha1.value().reset(); + m_sha1->reset(); break; case HashKind::SHA256: - sha256.value().reset(); + m_sha256->reset(); break; case HashKind::SHA512: - sha512.value().reset(); + m_sha512->reset(); break; default: case HashKind::None: @@ -278,13 +286,13 @@ public: { switch (m_kind) { case HashKind::MD5: - return md5.value().class_name(); + return m_md5->class_name(); case HashKind::SHA1: - return sha1.value().class_name(); + return m_sha1->class_name(); case HashKind::SHA256: - return sha256.value().class_name(); + return m_sha256->class_name(); case HashKind::SHA512: - return sha512.value().class_name(); + return m_sha512->class_name(); default: case HashKind::None: return "UninitializedHashManager"; @@ -297,10 +305,10 @@ public: } private: - Optional<SHA1> sha1; - Optional<SHA256> sha256; - Optional<SHA512> sha512; - Optional<MD5> md5; + OwnPtr<SHA1> m_sha1; + OwnPtr<SHA256> m_sha256; + OwnPtr<SHA512> m_sha512; + OwnPtr<MD5> m_md5; HashKind m_kind { HashKind::None }; ByteBuffer m_pre_init_buffer; }; diff --git a/Libraries/LibCrypto/Hash/SHA1.h b/Libraries/LibCrypto/Hash/SHA1.h index bb37296612..594172f3e7 100644 --- a/Libraries/LibCrypto/Hash/SHA1.h +++ b/Libraries/LibCrypto/Hash/SHA1.h @@ -85,6 +85,8 @@ public: }; inline virtual void reset() override { + m_data_length = 0; + m_bit_length = 0; for (auto i = 0; i < 5; ++i) m_state[i] = SHA1Constants::InitializationHashes[i]; } diff --git a/Libraries/LibHTTP/HttpsJob.cpp b/Libraries/LibHTTP/HttpsJob.cpp index ec23fbdaae..412be193ce 100644 --- a/Libraries/LibHTTP/HttpsJob.cpp +++ b/Libraries/LibHTTP/HttpsJob.cpp @@ -162,13 +162,11 @@ void HttpsJob::on_socket_connected() return finish_up(); return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); } - dbg() << "Read payload, " << payload.size() << " bytes"; m_received_buffers.append(payload); m_received_size += payload.size(); auto content_length_header = m_headers.get("Content-Length"); if (content_length_header.has_value()) { - dbg() << "content length is " << content_length_header.value() << ", we have " << m_received_size; bool ok; if (m_received_size >= content_length_header.value().to_uint(ok) && ok) finish_up(); diff --git a/Libraries/LibTLS/TLSv12.cpp b/Libraries/LibTLS/TLSv12.cpp index f05a9865e7..0aceeb21ee 100644 --- a/Libraries/LibTLS/TLSv12.cpp +++ b/Libraries/LibTLS/TLSv12.cpp @@ -389,9 +389,11 @@ ByteBuffer TLSv12::build_hello() } // Ciphers - builder.append((u16)(2 * sizeof(u16))); + builder.append((u16)(4 * sizeof(u16))); builder.append((u16)CipherSuite::RSA_WITH_AES_128_CBC_SHA256); builder.append((u16)CipherSuite::RSA_WITH_AES_256_CBC_SHA256); + builder.append((u16)CipherSuite::RSA_WITH_AES_128_CBC_SHA); + builder.append((u16)CipherSuite::RSA_WITH_AES_256_CBC_SHA); // we don't like compression builder.append((u8)1); @@ -460,8 +462,8 @@ ByteBuffer TLSv12::build_finished() auto outbuffer = ByteBuffer::wrap(out, out_size); auto dummy = ByteBuffer::create_zeroed(0); - auto digest = m_context.handshake_hash.hash.peek(); - auto hashbuf = ByteBuffer::wrap(digest.data, m_context.handshake_hash.hash.DigestSize); + auto digest = m_context.handshake_hash.digest(); + auto hashbuf = ByteBuffer::wrap(digest.immutable_data(), m_context.handshake_hash.digest_size()); pseudorandom_function(outbuffer, m_context.master_key, (const u8*)"client finished", 15, hashbuf, dummy); builder.append(outbuffer); @@ -554,9 +556,9 @@ bool TLSv12::expand_key() dbg() << "server iv"; print_buffer(server_iv, iv_size); dbg() << "client mac key"; - print_buffer(m_context.crypto.local_mac, 32); + print_buffer(m_context.crypto.local_mac, mac_size); dbg() << "server mac key"; - print_buffer(m_context.crypto.remote_mac, 32); + print_buffer(m_context.crypto.remote_mac, mac_size); #endif memcpy(m_context.crypto.local_iv, client_iv, iv_size); @@ -577,6 +579,11 @@ void TLSv12::pseudorandom_function(ByteBuffer& output, const ByteBuffer& secret, return; } + // RFC 5246: "In this section, we define one PRF, based on HMAC. This PRF with the + // SHA-256 hash function is used for all cipher suites defined in this + // document and in TLS documents published prior to this document when + // TLS 1.2 is negotiated." + // Apparently this PRF _always_ uses SHA256 Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac(secret); auto l_seed_size = label_length + seed.size() + seed_b.size(); @@ -586,11 +593,13 @@ void TLSv12::pseudorandom_function(ByteBuffer& output, const ByteBuffer& secret, label_seed_buffer.overwrite(label_length, seed.data(), seed.size()); label_seed_buffer.overwrite(label_length + seed.size(), seed_b.data(), seed_b.size()); - u8 digest[hmac.DigestSize]; + auto digest_size = hmac.digest_size(); - auto digest_0 = ByteBuffer::wrap(digest, hmac.DigestSize); + u8 digest[digest_size]; - digest_0.overwrite(0, hmac.process(label_seed_buffer).data, hmac.DigestSize); + auto digest_0 = ByteBuffer::wrap(digest, digest_size); + + digest_0.overwrite(0, hmac.process(label_seed_buffer).immutable_data(), digest_size); size_t index = 0; while (index < output.size()) { @@ -598,12 +607,12 @@ void TLSv12::pseudorandom_function(ByteBuffer& output, const ByteBuffer& secret, hmac.update(label_seed_buffer); auto digest_1 = hmac.digest(); - auto copy_size = min(hmac.DigestSize, output.size() - index); + auto copy_size = min(digest_size, output.size() - index); - output.overwrite(index, digest_1.data, copy_size); + output.overwrite(index, digest_1.immutable_data(), copy_size); index += copy_size; - digest_0.overwrite(0, hmac.process(digest_0).data, hmac.DigestSize); + digest_0.overwrite(0, hmac.process(digest_0).immutable_data(), digest_size); } } @@ -888,6 +897,9 @@ ssize_t TLSv12::handle_hello(const ByteBuffer& buffer, size_t& write_packets) m_context.cipher = cipher; dbg() << "Cipher: " << (u16)cipher; + // The handshake hash function is _always_ SHA256 + m_context.handshake_hash.initialize(Crypto::Hash::HashKind::SHA256); + if (buffer.size() - res < 1) { dbg() << "not enough data for compression spec"; return (i8)Error::NeedMoreData; @@ -1115,7 +1127,7 @@ ssize_t TLSv12::handle_verify(const ByteBuffer&) void TLSv12::update_hash(const ByteBuffer& message) { - m_context.handshake_hash.hash.update(message); + m_context.handshake_hash.update(message); } bool TLSv12::connect(const String& hostname, int port) @@ -1476,7 +1488,8 @@ ByteBuffer TLSv12::hmac_message(const ByteBuffer& buf, const Optional<ByteBuffer if (buf2.has_value() && buf2.value().size()) { hmac.update(buf2.value()); } - auto mac = ByteBuffer::copy(hmac.digest().data, hmac.DigestSize); + auto digest = hmac.digest(); + auto mac = ByteBuffer::copy(digest.immutable_data(), digest.data_length()); #ifdef TLS_DEBUG dbg() << "HMAC of the block for sequence number " << m_context.local_sequence_number; print_buffer(mac); @@ -1484,12 +1497,16 @@ ByteBuffer TLSv12::hmac_message(const ByteBuffer& buf, const Optional<ByteBuffer return mac; }; switch (mac_length) { + case Crypto::Hash::SHA1::DigestSize: { + Crypto::Authentication::HMAC<Crypto::Hash::SHA1> hmac(ByteBuffer::wrap(local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, mac_length)); + return digest(hmac); + } case Crypto::Hash::SHA256::DigestSize: { - Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac(ByteBuffer::wrap(local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, 32)); + Crypto::Authentication::HMAC<Crypto::Hash::SHA256> hmac(ByteBuffer::wrap(local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, mac_length)); return digest(hmac); } case Crypto::Hash::SHA512::DigestSize: { - Crypto::Authentication::HMAC<Crypto::Hash::SHA512> hmac(ByteBuffer::wrap(local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, 32)); + Crypto::Authentication::HMAC<Crypto::Hash::SHA512> hmac(ByteBuffer::wrap(local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, mac_length)); return digest(hmac); } default: diff --git a/Libraries/LibTLS/TLSv12.h b/Libraries/LibTLS/TLSv12.h index 315fb7babb..83ca59aaf4 100644 --- a/Libraries/LibTLS/TLSv12.h +++ b/Libraries/LibTLS/TLSv12.h @@ -34,7 +34,7 @@ #include <LibCrypto/Authentication/HMAC.h> #include <LibCrypto/BigInt/UnsignedBigInteger.h> #include <LibCrypto/Cipher/AES.h> -#include <LibCrypto/Hash/SHA2.h> +#include <LibCrypto/Hash/HashManager.h> #include <LibCrypto/PK/RSA.h> #include <LibTLS/TLSPacketBuilder.h> @@ -42,8 +42,6 @@ namespace TLS { class Socket; -using HashFunction = Crypto::Hash::SHA256; - enum class KeyExchangeAlgorithms { DHE_DSS, DHE_RSA, @@ -66,16 +64,6 @@ enum class ClientCertificateType { ECDSA_FixedECDH = 66 }; -enum class HashAlgorithm { - None = 0, - MD5 = 1, - SHA1 = 2, - SHA224 = 3, - SHA256 = 4, - SHA384 = 5, - SHA512 = 6 -}; - enum class SignatureAlgorithm { Anonymous = 0, RSA = 1, @@ -90,10 +78,9 @@ enum class CipherSuite { AES_128_CCM_SHA256 = 0x1304, AES_128_CCM_8_SHA256 = 0x1305, + // We support these RSA_WITH_AES_128_CBC_SHA = 0x002F, RSA_WITH_AES_256_CBC_SHA = 0x0035, - - // We support these RSA_WITH_AES_128_CBC_SHA256 = 0x003C, RSA_WITH_AES_256_CBC_SHA256 = 0x003D, // TODO @@ -187,10 +174,6 @@ struct Certificate { ByteBuffer data; }; -struct Hash { - Crypto::Hash::SHA256 hash; -}; - struct Context { String to_string() const; bool verify() const; @@ -220,7 +203,7 @@ struct Context { u8 remote_iv[16]; } crypto; - Hash handshake_hash; + Crypto::Hash::Manager handshake_hash; ByteBuffer message_buffer; u64 remote_sequence_number { 0 }; @@ -299,7 +282,7 @@ public: bool cipher_supported(CipherSuite suite) const { - return suite == CipherSuite::RSA_WITH_AES_128_CBC_SHA256 || suite == CipherSuite::RSA_WITH_AES_256_CBC_SHA256; + return suite == CipherSuite::RSA_WITH_AES_128_CBC_SHA256 || suite == CipherSuite::RSA_WITH_AES_256_CBC_SHA256 || suite == CipherSuite::RSA_WITH_AES_128_CBC_SHA || suite == CipherSuite::RSA_WITH_AES_256_CBC_SHA; } bool version_supported(Version v) const @@ -384,8 +367,24 @@ private: } size_t mac_length() const { - return Crypto::Authentication::HMAC<Crypto::Hash::SHA256>::DigestSize; - } // FIXME: generalize + switch (m_context.cipher) { + case CipherSuite::RSA_WITH_AES_128_CBC_SHA: + case CipherSuite::RSA_WITH_AES_256_CBC_SHA: + return Crypto::Hash::SHA1::digest_size(); + case CipherSuite::AES_256_GCM_SHA384: + case CipherSuite::RSA_WITH_AES_256_GCM_SHA384: + return Crypto::Hash::SHA512::digest_size(); + case CipherSuite::AES_128_CCM_8_SHA256: + case CipherSuite::AES_128_CCM_SHA256: + case CipherSuite::AES_128_GCM_SHA256: + case CipherSuite::Invalid: + case CipherSuite::RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite::RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite::RSA_WITH_AES_256_CBC_SHA256: + default: + return Crypto::Hash::SHA256::digest_size(); + } + } size_t iv_length() const { switch (m_context.cipher) { |