Coverage Report

Created: 2024-02-25 06:31

/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