|
Packit |
40b132 |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
Packit |
40b132 |
/* vim: set ts=2 et sw=2 tw=80: */
|
|
Packit |
40b132 |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
40b132 |
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
Packit |
40b132 |
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
#ifndef tls_parser_h_
|
|
Packit |
40b132 |
#define tls_parser_h_
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
#include <memory>
|
|
Packit |
40b132 |
#include <cstdint>
|
|
Packit |
40b132 |
#include <cstring>
|
|
Packit |
40b132 |
#include <arpa/inet.h>
|
|
Packit |
40b132 |
#include "databuffer.h"
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
namespace nss_test {
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
const uint8_t kTlsChangeCipherSpecType = 20;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertType = 21;
|
|
Packit |
40b132 |
const uint8_t kTlsHandshakeType = 22;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
const uint8_t kTlsHandshakeClientHello = 1;
|
|
Packit |
40b132 |
const uint8_t kTlsHandshakeServerHello = 2;
|
|
Packit |
40b132 |
const uint8_t kTlsHandshakeCertificate = 11;
|
|
Packit |
40b132 |
const uint8_t kTlsHandshakeServerKeyExchange = 12;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
const uint8_t kTlsAlertWarning = 1;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertFatal = 2;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
const uint8_t kTlsAlertUnexpectedMessage = 10;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertHandshakeFailure = 40;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertIllegalParameter = 47;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertDecodeError = 50;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertUnsupportedExtension = 110;
|
|
Packit |
40b132 |
const uint8_t kTlsAlertNoApplicationProtocol = 120;
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
const uint8_t kTlsFakeChangeCipherSpec[] = {
|
|
Packit |
40b132 |
kTlsChangeCipherSpecType, // Type
|
|
Packit |
40b132 |
0xfe, 0xff, // Version
|
|
Packit |
40b132 |
0x00, 0x00, 0x00, 0x00,
|
|
Packit |
40b132 |
0x00, 0x00, 0x00, 0x10, // Fictitious sequence #
|
|
Packit |
40b132 |
0x00, 0x01, // Length
|
|
Packit |
40b132 |
0x01 // Value
|
|
Packit |
40b132 |
};
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
inline bool IsDtls(uint16_t version) {
|
|
Packit |
40b132 |
return (version & 0x8000) == 0x8000;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
inline uint16_t NormalizeTlsVersion(uint16_t version) {
|
|
Packit |
40b132 |
if (version == 0xfeff) {
|
|
Packit |
40b132 |
return 0x0302; // special: DTLS 1.0 == TLS 1.1
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
if (IsDtls(version)) {
|
|
Packit |
40b132 |
return (version ^ 0xffff) + 0x0201;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
return version;
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
inline void WriteVariable(DataBuffer* target, size_t index,
|
|
Packit |
40b132 |
const DataBuffer& buf, size_t len_size) {
|
|
Packit |
40b132 |
target->Write(index, static_cast<uint32_t>(buf.len()), len_size);
|
|
Packit |
40b132 |
target->Write(index + len_size, buf.data(), buf.len());
|
|
Packit |
40b132 |
}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
class TlsParser {
|
|
Packit |
40b132 |
public:
|
|
Packit |
40b132 |
TlsParser(const uint8_t* data, size_t len)
|
|
Packit |
40b132 |
: buffer_(data, len), offset_(0) {}
|
|
Packit |
40b132 |
explicit TlsParser(const DataBuffer& buf)
|
|
Packit |
40b132 |
: buffer_(buf), offset_(0) {}
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
bool Read(uint8_t* val);
|
|
Packit |
40b132 |
// Read an integral type of specified width.
|
|
Packit |
40b132 |
bool Read(uint32_t* val, size_t size);
|
|
Packit |
40b132 |
// Reads len bytes into dest buffer, overwriting it.
|
|
Packit |
40b132 |
bool Read(DataBuffer* dest, size_t len);
|
|
Packit |
40b132 |
// Reads bytes into dest buffer, overwriting it. The number of bytes is
|
|
Packit |
40b132 |
// determined by reading from len_size bytes from the stream first.
|
|
Packit |
40b132 |
bool ReadVariable(DataBuffer* dest, size_t len_size);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
bool Skip(size_t len);
|
|
Packit |
40b132 |
bool SkipVariable(size_t len_size);
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
size_t consumed() const { return offset_; }
|
|
Packit |
40b132 |
size_t remaining() const { return buffer_.len() - offset_; }
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
private:
|
|
Packit |
40b132 |
void consume(size_t len) { offset_ += len; }
|
|
Packit |
40b132 |
const uint8_t* ptr() const { return buffer_.data() + offset_; }
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
DataBuffer buffer_;
|
|
Packit |
40b132 |
size_t offset_;
|
|
Packit |
40b132 |
};
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
} // namespace nss_test
|
|
Packit |
40b132 |
|
|
Packit |
40b132 |
#endif
|