Serenity Operating System
1/*
2 * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Debug.h>
8#include <AK/Endian.h>
9#include <AK/Random.h>
10
11#include <LibCore/Timer.h>
12#include <LibCrypto/ASN1/DER.h>
13#include <LibCrypto/PK/Code/EMSA_PSS.h>
14#include <LibTLS/TLSv12.h>
15
16namespace TLS {
17
18ssize_t TLSv12::handle_certificate(ReadonlyBytes buffer)
19{
20 ssize_t res = 0;
21
22 if (buffer.size() < 3) {
23 dbgln_if(TLS_DEBUG, "not enough certificate header data");
24 return (i8)Error::NeedMoreData;
25 }
26
27 u32 certificate_total_length = buffer[0] * 0x10000 + buffer[1] * 0x100 + buffer[2];
28
29 dbgln_if(TLS_DEBUG, "total length: {}", certificate_total_length);
30
31 if (certificate_total_length <= 4)
32 return 3 * certificate_total_length;
33
34 res += 3;
35
36 if (certificate_total_length > buffer.size() - res) {
37 dbgln_if(TLS_DEBUG, "not enough data for claimed total cert length");
38 return (i8)Error::NeedMoreData;
39 }
40 size_t size = certificate_total_length;
41
42 bool valid_certificate = false;
43
44 while (size > 0) {
45 if (buffer.size() - res < 3) {
46 dbgln_if(TLS_DEBUG, "not enough data for certificate length");
47 return (i8)Error::NeedMoreData;
48 }
49 size_t certificate_size = buffer[res] * 0x10000 + buffer[res + 1] * 0x100 + buffer[res + 2];
50 res += 3;
51
52 if (buffer.size() - res < certificate_size) {
53 dbgln_if(TLS_DEBUG, "not enough data for certificate body");
54 return (i8)Error::NeedMoreData;
55 }
56
57 auto res_cert = res;
58 auto remaining = certificate_size;
59
60 do {
61 if (remaining <= 3) {
62 dbgln("Ran out of data");
63 break;
64 }
65 if (buffer.size() < (size_t)res_cert + 3) {
66 dbgln("not enough data to read cert size ({} < {})", buffer.size(), res_cert + 3);
67 break;
68 }
69 size_t certificate_size_specific = buffer[res_cert] * 0x10000 + buffer[res_cert + 1] * 0x100 + buffer[res_cert + 2];
70 res_cert += 3;
71 remaining -= 3;
72
73 if (certificate_size_specific > remaining) {
74 dbgln("invalid certificate size (expected {} but got {})", remaining, certificate_size_specific);
75 break;
76 }
77 remaining -= certificate_size_specific;
78
79 auto certificate = Certificate::parse_asn1(buffer.slice(res_cert, certificate_size_specific), false);
80 if (certificate.has_value()) {
81 m_context.certificates.append(certificate.value());
82 valid_certificate = true;
83 }
84 res_cert += certificate_size_specific;
85 } while (remaining > 0);
86 if (remaining) {
87 dbgln("extraneous {} bytes left over after parsing certificates", remaining);
88 }
89 size -= certificate_size + 3;
90 res += certificate_size;
91 }
92 if (!valid_certificate)
93 return (i8)Error::UnsupportedCertificate;
94
95 if ((size_t)res != buffer.size())
96 dbgln("some data left unread: {} bytes out of {}", res, buffer.size());
97
98 return res;
99}
100
101ssize_t TLSv12::handle_certificate_verify(ReadonlyBytes)
102{
103 dbgln("FIXME: parse_verify");
104 return 0;
105}
106
107}