summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-04-25 05:07:24 +0430
committerAndreas Kling <kling@serenityos.org>2020-05-02 12:24:10 +0200
commitbb46e5f608cee772896ae4ac8ae69318e9edab1a (patch)
treefacb54846664faff33507b5f834fdeeb48974e22 /Libraries
parent43a49f5fff72b519bdc3a87f0df610bcd9f405bf (diff)
downloadserenity-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.h84
-rw-r--r--Libraries/LibCrypto/Hash/SHA1.h2
-rw-r--r--Libraries/LibHTTP/HttpsJob.cpp2
-rw-r--r--Libraries/LibTLS/TLSv12.cpp47
-rw-r--r--Libraries/LibTLS/TLSv12.h45
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) {