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/MemoryStream.h>
10#include <LibCore/EventLoop.h>
11#include <LibCore/Timer.h>
12#include <LibCrypto/PK/Code/EMSA_PSS.h>
13#include <LibTLS/TLSv12.h>
14
15namespace TLS {
16
17ByteBuffer TLSv12::build_alert(bool critical, u8 code)
18{
19 PacketBuilder builder(MessageType::Alert, (u16)m_context.options.version);
20 builder.append((u8)(critical ? AlertLevel::Critical : AlertLevel::Warning));
21 builder.append(code);
22
23 if (critical)
24 m_context.critical_error = code;
25
26 auto packet = builder.build();
27 update_packet(packet);
28
29 return packet;
30}
31
32void TLSv12::alert(AlertLevel level, AlertDescription code)
33{
34 auto the_alert = build_alert(level == AlertLevel::Critical, (u8)code);
35 write_packet(the_alert);
36 MUST(flush());
37}
38
39void TLSv12::write_packet(ByteBuffer& packet)
40{
41 auto schedule_or_perform_flush = [&](bool immediate) {
42 if (m_context.connection_status > ConnectionStatus::Disconnected) {
43 if (!m_has_scheduled_write_flush && !immediate) {
44 dbgln_if(TLS_DEBUG, "Scheduling write of {}", m_context.tls_buffer.size());
45 Core::deferred_invoke([this] { write_into_socket(); });
46 m_has_scheduled_write_flush = true;
47 } else {
48 // multiple packet are available, let's flush some out
49 dbgln_if(TLS_DEBUG, "Flushing scheduled write of {}", m_context.tls_buffer.size());
50 write_into_socket();
51 // the deferred invoke is still in place
52 m_has_scheduled_write_flush = true;
53 }
54 }
55 };
56 // Record size limit is 18432 bytes, leave some headroom and flush at 16K.
57 if (m_context.tls_buffer.size() + packet.size() > 16 * KiB)
58 schedule_or_perform_flush(true);
59
60 if (m_context.tls_buffer.try_append(packet.data(), packet.size()).is_error()) {
61 // Toooooo bad, drop the record on the ground.
62 return;
63 }
64 schedule_or_perform_flush(false);
65}
66
67void TLSv12::update_packet(ByteBuffer& packet)
68{
69 u32 header_size = 5;
70 ByteReader::store(packet.offset_pointer(3), AK::convert_between_host_and_network_endian((u16)(packet.size() - header_size)));
71
72 if (packet[0] != (u8)MessageType::ChangeCipher) {
73 if (packet[0] == (u8)MessageType::Handshake && packet.size() > header_size) {
74 u8 handshake_type = packet[header_size];
75 if (handshake_type != HandshakeType::HelloRequest && handshake_type != HandshakeType::HelloVerifyRequest) {
76 update_hash(packet.bytes(), header_size);
77 }
78 }
79 if (m_context.cipher_spec_set && m_context.crypto.created) {
80 size_t length = packet.size() - header_size;
81 size_t block_size = 0;
82 size_t padding = 0;
83 size_t mac_size = 0;
84
85 m_cipher_local.visit(
86 [&](Empty&) { VERIFY_NOT_REACHED(); },
87 [&](Crypto::Cipher::AESCipher::GCMMode& gcm) {
88 VERIFY(is_aead());
89 block_size = gcm.cipher().block_size();
90 padding = 0;
91 mac_size = 0; // AEAD provides its own authentication scheme.
92 },
93 [&](Crypto::Cipher::AESCipher::CBCMode& cbc) {
94 VERIFY(!is_aead());
95 block_size = cbc.cipher().block_size();
96 // If the length is already a multiple a block_size,
97 // an entire block of padding is added.
98 // In short, we _never_ have no padding.
99 mac_size = mac_length();
100 length += mac_size;
101 padding = block_size - length % block_size;
102 length += padding;
103 });
104
105 if (m_context.crypto.created == 1) {
106 // `buffer' will continue to be encrypted
107 auto buffer_result = ByteBuffer::create_uninitialized(length);
108 if (buffer_result.is_error()) {
109 dbgln("LibTLS: Failed to allocate enough memory");
110 VERIFY_NOT_REACHED();
111 }
112 auto buffer = buffer_result.release_value();
113 size_t buffer_position = 0;
114 auto iv_size = iv_length();
115
116 // copy the packet, sans the header
117 buffer.overwrite(buffer_position, packet.offset_pointer(header_size), packet.size() - header_size);
118 buffer_position += packet.size() - header_size;
119
120 ByteBuffer ct;
121
122 m_cipher_local.visit(
123 [&](Empty&) { VERIFY_NOT_REACHED(); },
124 [&](Crypto::Cipher::AESCipher::GCMMode& gcm) {
125 VERIFY(is_aead());
126 // We need enough space for a header, the data, a tag, and the IV
127 auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size + 16);
128 if (ct_buffer_result.is_error()) {
129 dbgln("LibTLS: Failed to allocate enough memory for the ciphertext");
130 VERIFY_NOT_REACHED();
131 }
132 ct = ct_buffer_result.release_value();
133
134 // copy the header over
135 ct.overwrite(0, packet.data(), header_size - 2);
136
137 // AEAD AAD (13)
138 // Seq. no (8)
139 // content type (1)
140 // version (2)
141 // length (2)
142 u8 aad[13];
143 Bytes aad_bytes { aad, 13 };
144 FixedMemoryStream aad_stream { aad_bytes };
145
146 u64 seq_no = AK::convert_between_host_and_network_endian(m_context.local_sequence_number);
147 u16 len = AK::convert_between_host_and_network_endian((u16)(packet.size() - header_size));
148
149 MUST(aad_stream.write_value(seq_no)); // sequence number
150 MUST(aad_stream.write_until_depleted(packet.bytes().slice(0, 3))); // content-type + version
151 MUST(aad_stream.write_value(len)); // length
152 VERIFY(MUST(aad_stream.tell()) == MUST(aad_stream.size()));
153
154 // AEAD IV (12)
155 // IV (4)
156 // (Nonce) (8)
157 // -- Our GCM impl takes 16 bytes
158 // zero (4)
159 u8 iv[16];
160 Bytes iv_bytes { iv, 16 };
161 Bytes { m_context.crypto.local_aead_iv, 4 }.copy_to(iv_bytes);
162 fill_with_random(iv_bytes.offset(4), 8);
163 memset(iv_bytes.offset(12), 0, 4);
164
165 // write the random part of the iv out
166 iv_bytes.slice(4, 8).copy_to(ct.bytes().slice(header_size));
167
168 // Write the encrypted data and the tag
169 gcm.encrypt(
170 packet.bytes().slice(header_size, length),
171 ct.bytes().slice(header_size + 8, length),
172 iv_bytes,
173 aad_bytes,
174 ct.bytes().slice(header_size + 8 + length, 16));
175
176 VERIFY(header_size + 8 + length + 16 == ct.size());
177 },
178 [&](Crypto::Cipher::AESCipher::CBCMode& cbc) {
179 VERIFY(!is_aead());
180 // We need enough space for a header, iv_length bytes of IV and whatever the packet contains
181 auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size);
182 if (ct_buffer_result.is_error()) {
183 dbgln("LibTLS: Failed to allocate enough memory for the ciphertext");
184 VERIFY_NOT_REACHED();
185 }
186 ct = ct_buffer_result.release_value();
187
188 // copy the header over
189 ct.overwrite(0, packet.data(), header_size - 2);
190
191 // get the appropriate HMAC value for the entire packet
192 auto mac = hmac_message(packet, {}, mac_size, true);
193
194 // write the MAC
195 buffer.overwrite(buffer_position, mac.data(), mac.size());
196 buffer_position += mac.size();
197
198 // Apply the padding (a packet MUST always be padded)
199 memset(buffer.offset_pointer(buffer_position), padding - 1, padding);
200 buffer_position += padding;
201
202 VERIFY(buffer_position == buffer.size());
203
204 auto iv_buffer_result = ByteBuffer::create_uninitialized(iv_size);
205 if (iv_buffer_result.is_error()) {
206 dbgln("LibTLS: Failed to allocate memory for IV");
207 VERIFY_NOT_REACHED();
208 }
209 auto iv = iv_buffer_result.release_value();
210 fill_with_random(iv.data(), iv.size());
211
212 // write it into the ciphertext portion of the message
213 ct.overwrite(header_size, iv.data(), iv.size());
214
215 VERIFY(header_size + iv_size + length == ct.size());
216 VERIFY(length % block_size == 0);
217
218 // get a block to encrypt into
219 auto view = ct.bytes().slice(header_size + iv_size, length);
220 cbc.encrypt(buffer, view, iv);
221 });
222
223 // store the correct ciphertext length into the packet
224 u16 ct_length = (u16)ct.size() - header_size;
225
226 ByteReader::store(ct.offset_pointer(header_size - 2), AK::convert_between_host_and_network_endian(ct_length));
227
228 // replace the packet with the ciphertext
229 packet = ct;
230 }
231 }
232 }
233 ++m_context.local_sequence_number;
234}
235
236void TLSv12::update_hash(ReadonlyBytes message, size_t header_size)
237{
238 dbgln_if(TLS_DEBUG, "Update hash with message of size {}", message.size());
239 m_context.handshake_hash.update(message.slice(header_size));
240}
241
242void TLSv12::ensure_hmac(size_t digest_size, bool local)
243{
244 if (local && m_hmac_local)
245 return;
246
247 if (!local && m_hmac_remote)
248 return;
249
250 auto hash_kind = Crypto::Hash::HashKind::None;
251
252 switch (digest_size) {
253 case Crypto::Hash::SHA1::DigestSize:
254 hash_kind = Crypto::Hash::HashKind::SHA1;
255 break;
256 case Crypto::Hash::SHA256::DigestSize:
257 hash_kind = Crypto::Hash::HashKind::SHA256;
258 break;
259 case Crypto::Hash::SHA384::DigestSize:
260 hash_kind = Crypto::Hash::HashKind::SHA384;
261 break;
262 case Crypto::Hash::SHA512::DigestSize:
263 hash_kind = Crypto::Hash::HashKind::SHA512;
264 break;
265 default:
266 dbgln("Failed to find a suitable hash for size {}", digest_size);
267 break;
268 }
269
270 auto hmac = make<Crypto::Authentication::HMAC<Crypto::Hash::Manager>>(ReadonlyBytes { local ? m_context.crypto.local_mac : m_context.crypto.remote_mac, digest_size }, hash_kind);
271 if (local)
272 m_hmac_local = move(hmac);
273 else
274 m_hmac_remote = move(hmac);
275}
276
277ByteBuffer TLSv12::hmac_message(ReadonlyBytes buf, Optional<ReadonlyBytes> const buf2, size_t mac_length, bool local)
278{
279 u64 sequence_number = AK::convert_between_host_and_network_endian(local ? m_context.local_sequence_number : m_context.remote_sequence_number);
280 ensure_hmac(mac_length, local);
281 auto& hmac = local ? *m_hmac_local : *m_hmac_remote;
282 if constexpr (TLS_DEBUG) {
283 dbgln("========================= PACKET DATA ==========================");
284 print_buffer((u8 const*)&sequence_number, sizeof(u64));
285 print_buffer(buf.data(), buf.size());
286 if (buf2.has_value())
287 print_buffer(buf2.value().data(), buf2.value().size());
288 dbgln("========================= PACKET DATA ==========================");
289 }
290 hmac.update((u8 const*)&sequence_number, sizeof(u64));
291 hmac.update(buf);
292 if (buf2.has_value() && buf2.value().size()) {
293 hmac.update(buf2.value());
294 }
295 auto digest = hmac.digest();
296 auto mac_result = ByteBuffer::copy(digest.immutable_data(), digest.data_length());
297 if (mac_result.is_error()) {
298 dbgln("Failed to calculate message HMAC: Not enough memory");
299 return {};
300 }
301
302 if constexpr (TLS_DEBUG) {
303 dbgln("HMAC of the block for sequence number {}", sequence_number);
304 print_buffer(mac_result.value());
305 }
306
307 return mac_result.release_value();
308}
309
310ssize_t TLSv12::handle_message(ReadonlyBytes buffer)
311{
312 auto res { 5ll };
313 size_t header_size = res;
314 ssize_t payload_res = 0;
315
316 dbgln_if(TLS_DEBUG, "buffer size: {}", buffer.size());
317
318 if (buffer.size() < 5) {
319 return (i8)Error::NeedMoreData;
320 }
321
322 auto type = (MessageType)buffer[0];
323 size_t buffer_position { 1 };
324
325 // FIXME: Read the version and verify it
326
327 if constexpr (TLS_DEBUG) {
328 auto version = ByteReader::load16(buffer.offset_pointer(buffer_position));
329 dbgln("type={}, version={}", (u8)type, (u16)version);
330 }
331
332 buffer_position += 2;
333
334 auto length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(buffer_position)));
335
336 dbgln_if(TLS_DEBUG, "record length: {} at offset: {}", length, buffer_position);
337 buffer_position += 2;
338
339 if (buffer_position + length > buffer.size()) {
340 dbgln_if(TLS_DEBUG, "record length more than what we have: {}", buffer.size());
341 return (i8)Error::NeedMoreData;
342 }
343
344 dbgln_if(TLS_DEBUG, "message type: {}, length: {}", (u8)type, length);
345 auto plain = buffer.slice(buffer_position, buffer.size() - buffer_position);
346
347 ByteBuffer decrypted;
348
349 if (m_context.cipher_spec_set && type != MessageType::ChangeCipher) {
350 if constexpr (TLS_DEBUG) {
351 dbgln("Encrypted: ");
352 print_buffer(buffer.slice(header_size, length));
353 }
354
355 Error return_value = Error::NoError;
356 m_cipher_remote.visit(
357 [&](Empty&) { VERIFY_NOT_REACHED(); },
358 [&](Crypto::Cipher::AESCipher::GCMMode& gcm) {
359 VERIFY(is_aead());
360 if (length < 24) {
361 dbgln("Invalid packet length");
362 auto packet = build_alert(true, (u8)AlertDescription::DecryptError);
363 write_packet(packet);
364 return_value = Error::BrokenPacket;
365 return;
366 }
367
368 auto packet_length = length - iv_length() - 16;
369 auto payload = plain;
370 auto decrypted_result = ByteBuffer::create_uninitialized(packet_length);
371 if (decrypted_result.is_error()) {
372 dbgln("Failed to allocate memory for the packet");
373 return_value = Error::DecryptionFailed;
374 return;
375 }
376 decrypted = decrypted_result.release_value();
377
378 // AEAD AAD (13)
379 // Seq. no (8)
380 // content type (1)
381 // version (2)
382 // length (2)
383 u8 aad[13];
384 Bytes aad_bytes { aad, 13 };
385 FixedMemoryStream aad_stream { aad_bytes };
386
387 u64 seq_no = AK::convert_between_host_and_network_endian(m_context.remote_sequence_number);
388 u16 len = AK::convert_between_host_and_network_endian((u16)packet_length);
389
390 MUST(aad_stream.write_value(seq_no)); // sequence number
391 MUST(aad_stream.write_until_depleted(buffer.slice(0, header_size - 2))); // content-type + version
392 MUST(aad_stream.write_value(len)); // length
393 VERIFY(MUST(aad_stream.tell()) == MUST(aad_stream.size()));
394
395 auto nonce = payload.slice(0, iv_length());
396 payload = payload.slice(iv_length());
397
398 // AEAD IV (12)
399 // IV (4)
400 // (Nonce) (8)
401 // -- Our GCM impl takes 16 bytes
402 // zero (4)
403 u8 iv[16];
404 Bytes iv_bytes { iv, 16 };
405 Bytes { m_context.crypto.remote_aead_iv, 4 }.copy_to(iv_bytes);
406 nonce.copy_to(iv_bytes.slice(4));
407 memset(iv_bytes.offset(12), 0, 4);
408
409 auto ciphertext = payload.slice(0, payload.size() - 16);
410 auto tag = payload.slice(ciphertext.size());
411
412 auto consistency = gcm.decrypt(
413 ciphertext,
414 decrypted,
415 iv_bytes,
416 aad_bytes,
417 tag);
418
419 if (consistency != Crypto::VerificationConsistency::Consistent) {
420 dbgln("integrity check failed (tag length {})", tag.size());
421 auto packet = build_alert(true, (u8)AlertDescription::BadRecordMAC);
422 write_packet(packet);
423
424 return_value = Error::IntegrityCheckFailed;
425 return;
426 }
427
428 plain = decrypted;
429 },
430 [&](Crypto::Cipher::AESCipher::CBCMode& cbc) {
431 VERIFY(!is_aead());
432 auto iv_size = iv_length();
433
434 auto decrypted_result = cbc.create_aligned_buffer(length - iv_size);
435 if (decrypted_result.is_error()) {
436 dbgln("Failed to allocate memory for the packet");
437 return_value = Error::DecryptionFailed;
438 return;
439 }
440 decrypted = decrypted_result.release_value();
441 auto iv = buffer.slice(header_size, iv_size);
442
443 Bytes decrypted_span = decrypted;
444 cbc.decrypt(buffer.slice(header_size + iv_size, length - iv_size), decrypted_span, iv);
445
446 length = decrypted_span.size();
447
448 if constexpr (TLS_DEBUG) {
449 dbgln("Decrypted: ");
450 print_buffer(decrypted);
451 }
452
453 auto mac_size = mac_length();
454 if (length < mac_size) {
455 dbgln("broken packet");
456 auto packet = build_alert(true, (u8)AlertDescription::DecryptError);
457 write_packet(packet);
458 return_value = Error::BrokenPacket;
459 return;
460 }
461
462 length -= mac_size;
463
464 const u8* message_hmac = decrypted_span.offset(length);
465 u8 temp_buf[5];
466 memcpy(temp_buf, buffer.offset_pointer(0), 3);
467 *(u16*)(temp_buf + 3) = AK::convert_between_host_and_network_endian(length);
468 auto hmac = hmac_message({ temp_buf, 5 }, decrypted_span.slice(0, length), mac_size);
469 auto message_mac = ReadonlyBytes { message_hmac, mac_size };
470 if (hmac != message_mac) {
471 dbgln("integrity check failed (mac length {})", mac_size);
472 dbgln("mac received:");
473 print_buffer(message_mac);
474 dbgln("mac computed:");
475 print_buffer(hmac);
476 auto packet = build_alert(true, (u8)AlertDescription::BadRecordMAC);
477 write_packet(packet);
478
479 return_value = Error::IntegrityCheckFailed;
480 return;
481 }
482 plain = decrypted.bytes().slice(0, length);
483 });
484
485 if (return_value != Error::NoError) {
486 return (i8)return_value;
487 }
488 }
489 m_context.remote_sequence_number++;
490
491 switch (type) {
492 case MessageType::ApplicationData:
493 if (m_context.connection_status != ConnectionStatus::Established) {
494 dbgln("unexpected application data");
495 payload_res = (i8)Error::UnexpectedMessage;
496 auto packet = build_alert(true, (u8)AlertDescription::UnexpectedMessage);
497 write_packet(packet);
498 } else {
499 dbgln_if(TLS_DEBUG, "application data message of size {}", plain.size());
500
501 if (m_context.application_buffer.try_append(plain.data(), plain.size()).is_error()) {
502 payload_res = (i8)Error::DecryptionFailed;
503 auto packet = build_alert(true, (u8)AlertDescription::DecryptionFailed);
504 write_packet(packet);
505 }
506 }
507 break;
508 case MessageType::Handshake:
509 dbgln_if(TLS_DEBUG, "tls handshake message");
510 payload_res = handle_handshake_payload(plain);
511 break;
512 case MessageType::ChangeCipher:
513 if (m_context.connection_status != ConnectionStatus::KeyExchange) {
514 dbgln("unexpected change cipher message");
515 auto packet = build_alert(true, (u8)AlertDescription::UnexpectedMessage);
516 write_packet(packet);
517 payload_res = (i8)Error::UnexpectedMessage;
518 } else {
519 dbgln_if(TLS_DEBUG, "change cipher spec message");
520 m_context.cipher_spec_set = true;
521 m_context.remote_sequence_number = 0;
522 }
523 break;
524 case MessageType::Alert:
525 dbgln_if(TLS_DEBUG, "alert message of length {}", length);
526 if (length >= 2) {
527 if constexpr (TLS_DEBUG)
528 print_buffer(plain);
529
530 auto level = plain[0];
531 auto code = plain[1];
532 dbgln_if(TLS_DEBUG, "Alert received with level {}, code {}", level, code);
533
534 if (level == (u8)AlertLevel::Critical) {
535 dbgln("We were alerted of a critical error: {} ({})", code, alert_name((AlertDescription)code));
536 m_context.critical_error = code;
537 try_disambiguate_error();
538 res = (i8)Error::UnknownError;
539 }
540
541 if (code == (u8)AlertDescription::CloseNotify) {
542 res += 2;
543 alert(AlertLevel::Critical, AlertDescription::CloseNotify);
544 if (!m_context.cipher_spec_set) {
545 // AWS CloudFront hits this.
546 dbgln("Server sent a close notify and we haven't agreed on a cipher suite. Treating it as a handshake failure.");
547 m_context.critical_error = (u8)AlertDescription::HandshakeFailure;
548 try_disambiguate_error();
549 }
550 m_context.close_notify = true;
551 }
552 m_context.error_code = (Error)code;
553 check_connection_state(false);
554 notify_client_for_app_data(); // Give the user one more chance to observe the EOF
555 }
556 break;
557 default:
558 dbgln("message not understood");
559 return (i8)Error::NotUnderstood;
560 }
561
562 if (payload_res < 0)
563 return payload_res;
564
565 if (res > 0)
566 return header_size + length;
567
568 return res;
569}
570
571}