/src/nss/cpputil/tls_parser.h
Line | Count | Source (jump to first uncovered line) |
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 | 0 | inline std::ostream& operator<<(std::ostream& os, SSLProtocolVariant v) { |
90 | 0 | return os << ((v == ssl_variant_stream) ? "TLS" : "DTLS"); |
91 | 0 | } |
92 | | |
93 | 0 | inline std::ostream& operator<<(std::ostream& os, SSLContentType v) { |
94 | 0 | switch (v) { |
95 | 0 | case ssl_ct_change_cipher_spec: |
96 | 0 | return os << "CCS"; |
97 | 0 | case ssl_ct_alert: |
98 | 0 | return os << "alert"; |
99 | 0 | case ssl_ct_handshake: |
100 | 0 | return os << "handshake"; |
101 | 0 | case ssl_ct_application_data: |
102 | 0 | return os << "application data"; |
103 | 0 | case ssl_ct_ack: |
104 | 0 | return os << "ack"; |
105 | 0 | } |
106 | 0 | return os << "UNKNOWN content type " << static_cast<int>(v); |
107 | 0 | } |
108 | | |
109 | 0 | inline std::ostream& operator<<(std::ostream& os, SSLSecretDirection v) { |
110 | 0 | switch (v) { |
111 | 0 | case ssl_secret_read: |
112 | 0 | return os << "read"; |
113 | 0 | case ssl_secret_write: |
114 | 0 | return os << "write"; |
115 | 0 | } |
116 | 0 | return os << "UNKNOWN secret direction " << static_cast<int>(v); |
117 | 0 | } |
118 | | |
119 | 0 | inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; } |
120 | | |
121 | 0 | inline uint16_t NormalizeTlsVersion(uint16_t version) { |
122 | 0 | if (version == 0xfeff) { |
123 | 0 | return 0x0302; // special: DTLS 1.0 == TLS 1.1 |
124 | 0 | } |
125 | 0 | if (IsDtls(version)) { |
126 | 0 | return (version ^ 0xffff) + 0x0201; |
127 | 0 | } |
128 | 0 | return version; |
129 | 0 | } |
130 | | |
131 | 0 | inline uint16_t TlsVersionToDtlsVersion(uint16_t version) { |
132 | 0 | if (version == 0x0302) { |
133 | 0 | return 0xfeff; |
134 | 0 | } |
135 | 0 | if (version == 0x0304) { |
136 | 0 | return version; |
137 | 0 | } |
138 | 0 | return 0xffff - version + 0x0201; |
139 | 0 | } |
140 | | |
141 | | inline size_t WriteVariable(DataBuffer* target, size_t index, |
142 | 0 | const DataBuffer& buf, size_t len_size) { |
143 | 0 | index = target->Write(index, static_cast<uint32_t>(buf.len()), len_size); |
144 | 0 | return target->Write(index, buf.data(), buf.len()); |
145 | 0 | } |
146 | | |
147 | | class TlsParser { |
148 | | public: |
149 | 0 | TlsParser(const uint8_t* data, size_t len) : buffer_(data, len), offset_(0) {} |
150 | 0 | 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 | 0 | size_t consumed() const { return offset_; } |
166 | 0 | size_t remaining() const { return buffer_.len() - offset_; } |
167 | | |
168 | | private: |
169 | 0 | void consume(size_t len) { offset_ += len; } |
170 | 0 | 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 |