tls_parser.h (5543B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef tls_parser_h_ 8 #define tls_parser_h_ 9 10 #include <cstdint> 11 #include <cstring> 12 #include <memory> 13 #if defined(WIN32) || defined(WIN64) 14 #include <winsock2.h> 15 #else 16 #include <arpa/inet.h> 17 #endif 18 #include "databuffer.h" 19 #include "sslt.h" 20 21 namespace nss_test { 22 23 const uint8_t kTlsHandshakeClientHello = 1; 24 const uint8_t kTlsHandshakeServerHello = 2; 25 const uint8_t kTlsHandshakeNewSessionTicket = 4; 26 const uint8_t kTlsHandshakeHelloRetryRequest = 6; 27 const uint8_t kTlsHandshakeEncryptedExtensions = 8; 28 const uint8_t kTlsHandshakeCertificate = 11; 29 const uint8_t kTlsHandshakeServerKeyExchange = 12; 30 const uint8_t kTlsHandshakeCertificateRequest = 13; 31 const uint8_t kTlsHandshakeCertificateVerify = 15; 32 const uint8_t kTlsHandshakeClientKeyExchange = 16; 33 const uint8_t kTlsHandshakeFinished = 20; 34 const uint8_t kTlsHandshakeKeyUpdate = 24; 35 const uint8_t kTlsHandshakeCertificateCompression = 25; 36 37 const uint8_t kTlsAlertWarning = 1; 38 const uint8_t kTlsAlertFatal = 2; 39 40 const uint8_t kTlsAlertCloseNotify = 0; 41 const uint8_t kTlsAlertUnexpectedMessage = 10; 42 const uint8_t kTlsAlertBadRecordMac = 20; 43 const uint8_t kTlsAlertRecordOverflow = 22; 44 const uint8_t kTlsAlertHandshakeFailure = 40; 45 const uint8_t kTlsAlertBadCertificate = 42; 46 const uint8_t kTlsAlertCertificateRevoked = 44; 47 const uint8_t kTlsAlertCertificateExpired = 45; 48 const uint8_t kTlsAlertIllegalParameter = 47; 49 const uint8_t kTlsAlertDecodeError = 50; 50 const uint8_t kTlsAlertDecryptError = 51; 51 const uint8_t kTlsAlertProtocolVersion = 70; 52 const uint8_t kTlsAlertInsufficientSecurity = 71; 53 const uint8_t kTlsAlertInternalError = 80; 54 const uint8_t kTlsAlertInappropriateFallback = 86; 55 const uint8_t kTlsAlertMissingExtension = 109; 56 const uint8_t kTlsAlertUnsupportedExtension = 110; 57 const uint8_t kTlsAlertUnrecognizedName = 112; 58 const uint8_t kTlsAlertCertificateRequired = 116; 59 const uint8_t kTlsAlertNoApplicationProtocol = 120; 60 const uint8_t kTlsAlertEchRequired = 121; 61 62 const uint8_t kTlsFakeChangeCipherSpec[] = { 63 ssl_ct_change_cipher_spec, // Type 64 0xfe, 65 0xff, // Version 66 0x00, 67 0x00, 68 0x00, 69 0x00, 70 0x00, 71 0x00, 72 0x00, 73 0x10, // Fictitious sequence # 74 0x00, 75 0x01, // Length 76 0x01 // Value 77 }; 78 79 const uint8_t kCtDtlsCiphertext = 0x20; 80 const uint8_t kCtDtlsCiphertextMask = 0xE0; 81 const uint8_t kCtDtlsCiphertext16bSeqno = 0x08; 82 const uint8_t kCtDtlsCiphertextLengthPresent = 0x04; 83 84 static const uint8_t kTls13PskKe = 0; 85 static const uint8_t kTls13PskDhKe = 1; 86 static const uint8_t kTls13PskAuth = 0; 87 static const uint8_t kTls13PskSignAuth = 1; 88 89 inline std::ostream& operator<<(std::ostream& os, SSLProtocolVariant v) { 90 return os << ((v == ssl_variant_stream) ? "TLS" : "DTLS"); 91 } 92 93 inline std::ostream& operator<<(std::ostream& os, SSLContentType v) { 94 switch (v) { 95 case ssl_ct_change_cipher_spec: 96 return os << "CCS"; 97 case ssl_ct_alert: 98 return os << "alert"; 99 case ssl_ct_handshake: 100 return os << "handshake"; 101 case ssl_ct_application_data: 102 return os << "application data"; 103 case ssl_ct_ack: 104 return os << "ack"; 105 } 106 return os << "UNKNOWN content type " << static_cast<int>(v); 107 } 108 109 inline std::ostream& operator<<(std::ostream& os, SSLSecretDirection v) { 110 switch (v) { 111 case ssl_secret_read: 112 return os << "read"; 113 case ssl_secret_write: 114 return os << "write"; 115 } 116 return os << "UNKNOWN secret direction " << static_cast<int>(v); 117 } 118 119 inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; } 120 121 inline uint16_t NormalizeTlsVersion(uint16_t version) { 122 if (version == 0xfeff) { 123 return 0x0302; // special: DTLS 1.0 == TLS 1.1 124 } 125 if (IsDtls(version)) { 126 return (version ^ 0xffff) + 0x0201; 127 } 128 return version; 129 } 130 131 inline uint16_t TlsVersionToDtlsVersion(uint16_t version) { 132 if (version == 0x0302) { 133 return 0xfeff; 134 } 135 if (version == 0x0304) { 136 return version; 137 } 138 return 0xffff - version + 0x0201; 139 } 140 141 inline size_t WriteVariable(DataBuffer* target, size_t index, 142 const DataBuffer& buf, size_t len_size) { 143 index = target->Write(index, static_cast<uint32_t>(buf.len()), len_size); 144 return target->Write(index, buf.data(), buf.len()); 145 } 146 147 class TlsParser { 148 public: 149 TlsParser(const uint8_t* data, size_t len) : buffer_(data, len), offset_(0) {} 150 explicit TlsParser(const DataBuffer& buf) : buffer_(buf), offset_(0) {} 151 152 bool Read(uint8_t* val); 153 // Read an integral type of specified width. 154 bool Read(uint32_t* val, size_t size); 155 // Reads len bytes into dest buffer, overwriting it. 156 bool Read(DataBuffer* dest, size_t len); 157 bool ReadFromMark(DataBuffer* val, size_t len, size_t mark); 158 // Reads bytes into dest buffer, overwriting it. The number of bytes is 159 // determined by reading from len_size bytes from the stream first. 160 bool ReadVariable(DataBuffer* dest, size_t len_size); 161 162 bool Skip(size_t len); 163 bool SkipVariable(size_t len_size); 164 165 size_t consumed() const { return offset_; } 166 size_t remaining() const { return buffer_.len() - offset_; } 167 168 private: 169 void consume(size_t len) { offset_ += len; } 170 const uint8_t* ptr() const { return buffer_.data() + offset_; } 171 172 DataBuffer buffer_; 173 size_t offset_; 174 }; 175 176 } // namespace nss_test 177 178 #endif