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