ladybird/Userland/Libraries/LibTLS/HandshakeCertificate.cpp
Ali Mohammad Pur e0465b8939 Revert "LibTLS+Everywhere: Switch to using WolfSSL"
This reverts commit 8bb610b97a.
Linking wolfSSL seems to cause more legal trouble than it's worth due to
it being GPLv2, so let's undo this for now.
2024-07-06 15:15:34 -06:00

110 lines
3.4 KiB
C++

/*
* Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Debug.h>
#include <AK/Endian.h>
#include <AK/Random.h>
#include <LibCore/Timer.h>
#include <LibCrypto/ASN1/DER.h>
#include <LibTLS/TLSv12.h>
namespace TLS {
ssize_t TLSv12::handle_certificate(ReadonlyBytes buffer)
{
ssize_t res = 0;
if (buffer.size() < 3) {
dbgln_if(TLS_DEBUG, "not enough certificate header data");
return (i8)Error::NeedMoreData;
}
u32 certificate_total_length = buffer[0] * 0x10000 + buffer[1] * 0x100 + buffer[2];
dbgln_if(TLS_DEBUG, "total length: {}", certificate_total_length);
if (certificate_total_length <= 4)
return 3 * certificate_total_length;
res += 3;
if (certificate_total_length > buffer.size() - res) {
dbgln_if(TLS_DEBUG, "not enough data for claimed total cert length");
return (i8)Error::NeedMoreData;
}
size_t size = certificate_total_length;
bool valid_certificate = false;
while (size > 0) {
if (buffer.size() - res < 3) {
dbgln_if(TLS_DEBUG, "not enough data for certificate length");
return (i8)Error::NeedMoreData;
}
size_t certificate_size = buffer[res] * 0x10000 + buffer[res + 1] * 0x100 + buffer[res + 2];
res += 3;
if (buffer.size() - res < certificate_size) {
dbgln_if(TLS_DEBUG, "not enough data for certificate body");
return (i8)Error::NeedMoreData;
}
auto res_cert = res;
auto remaining = certificate_size;
do {
if (remaining <= 3) {
dbgln("Ran out of data");
break;
}
if (buffer.size() < (size_t)res_cert + 3) {
dbgln("not enough data to read cert size ({} < {})", buffer.size(), res_cert + 3);
break;
}
size_t certificate_size_specific = buffer[res_cert] * 0x10000 + buffer[res_cert + 1] * 0x100 + buffer[res_cert + 2];
res_cert += 3;
remaining -= 3;
if (certificate_size_specific > remaining) {
dbgln("invalid certificate size (expected {} but got {})", remaining, certificate_size_specific);
break;
}
remaining -= certificate_size_specific;
auto certificate = Certificate::parse_certificate(buffer.slice(res_cert, certificate_size_specific), false);
if (!certificate.is_error()) {
m_context.certificates.empend(certificate.value());
valid_certificate = true;
} else {
dbgln("Failed to parse client cert: {}", certificate.error());
dbgln("{:hex-dump}", buffer.slice(res_cert, certificate_size_specific));
dbgln("");
}
res_cert += certificate_size_specific;
} while (remaining > 0);
if (remaining) {
dbgln("extraneous {} bytes left over after parsing certificates", remaining);
}
size -= certificate_size + 3;
res += certificate_size;
}
if (!valid_certificate)
return (i8)Error::UnsupportedCertificate;
if ((size_t)res != buffer.size())
dbgln("some data left unread: {} bytes out of {}", res, buffer.size());
return res;
}
ssize_t TLSv12::handle_certificate_verify(ReadonlyBytes)
{
dbgln("FIXME: parse_verify");
return 0;
}
}