Tls deser ser
Deserializer for TLS records
include tls_record
object tls_deser = {}
object tls_ser = {}
object tls_ser_server = {}
<<< member
class `tls_deser`;
class `tls_ser`;
class `tls_ser_server`;
>>>
<<< impl
//https://tools.ietf.org/html/draft-thomson-coap-bit-grease-00
//https://tools.ietf.org/id/draft-huitema-coap-ts-03.html
//TODO
class `tls_deser` : public ivy_binary_deser_128 {
//class `tls_deser` : public ivy_binary_deser {
int field_bytes;
std::vector<unsigned> fence;
int in_encrypted_extensions;
bool is_session_ticket;
bool ticket_nonce_b;
bool ticket_b;
bool extensions_b;
bool early_data_b;
bool is_server_hello;
public:
tls_deser(const std::vector<char> &inp) : ivy_binary_deser_128(inp) {
//tls_deser(const std::vector<char> &inp) : ivy_binary_deser(inp) {
field_bytes = 2;
in_encrypted_extensions = 0;
is_session_ticket = false;
ticket_nonce_b = false;
ticket_b = false;
extensions_b = false;
early_data_b = false;
is_server_hello = false;
}
virtual bool more(unsigned bytes) {
if (fence.size() > 0 && pos + bytes > fence.back()) {
return false;
}
return ivy_binary_deser_128::more(bytes);
//return ivy_binary_deser::more(bytes);
}
virtual void open_field(const std::string &name) {
std::cerr << "deser-open_field: name : " << name << "\n";
if(name == "tls.server_hello")
is_server_hello = true;
if(name == "tls.client_hello")
is_server_hello = false;
if (name == "random_bytes") { //28 bytes tls1.2, 32bytes tls1.3
fence.push_back(pos+28);
field_bytes = 1;
}
else if (name == "versions") {
field_bytes = 4;
int128_t bytes = 0;
//long long bytes = 0;
if (in_encrypted_extensions) {
getn(bytes,1);
}
fence.push_back(pos+bytes);
}
else if (tls_field_length_bytes_map.find(name) != tls_field_length_bytes_map.end()) {
int length_field_bytes = tls_field_length_bytes_map[name];
int128_t bytes;
//long long bytes;
std::cerr << "deser-open_field: length_field_bytes : " << length_field_bytes << "\n";
getn(bytes,length_field_bytes);
/*if(is_session_ticket && name == "unknown_message_bytes") {
is_session_ticket = false;
}*/
/*if(name == "psk_identities")
bytes -= 2;*/
std::cerr << "deser-open_field: flength : " << bytes << "\n";
if(tls_field_bytes_map.find(name) != tls_field_bytes_map.end()) {
//tls_field_bytes_map[name] = bytes;
std::cerr << "deser-open_field: tls_field_bytes_map[" << name << "] : " << bytes << "\n";
} //else if (name == )
fence.push_back(pos+bytes);
// if (name == "ticket" && ! ticket_b) {
// std::cerr << "deser-open_field: name BITE : " << name << "\n";
// // int128_t val;
// // getn(val,bytes);
// //std::cerr << "deser-open_field: val BITE : " << val << "\n";
// //std::cerr << "deser-open_field: pos+bytes BITE : " << pos+bytes << "\n";
// const char * session_file = getenv("STFILE2");
// FILE *fp;
// if(session_file != NULL) {
// fp = fopen(session_file,"a");
// uint16_t val_trunc = bytes;
// fprintf(fp, "%02hhx%02hhx", val_trunc >> 8, val_trunc); //length field
// for(int j = 0; j < bytes; j++) {
// int128_t val;
// getn(val,1);
// //std::cerr << "deser-open_field: val BITE : " << val << "\n";
// val_trunc = val;
// fprintf(fp, "%02x", val_trunc);
// }
// fclose(fp);
// pos -= bytes;
// }
// ticket_b = true;
// }
// if (name == "ticket_nonce" && !ticket_nonce_b) {
// std::cerr << "deser-open_field: name BITE : " << name << "\n";
// // int128_t val;
// // getn(val,bytes);
// ////std::cerr << "deser-open_field: val BITE : " << val << "\n";
// //std::cerr << "deser-open_field: pos+bytes BITE : " << pos+bytes << "\n";
// const char * session_file = getenv("STFILE2");
// FILE *fp;
// if(session_file != NULL) {
// fp = fopen(session_file,"a");
// uint16_t val_trunc = bytes;
// fprintf(fp, "%02hhx", val_trunc);
// for(int j = 0; j < bytes && bytes > 0; j++) {
// int128_t val;
// getn(val,1);
// //std::cerr << "deser-open_field: val BITE : " << val << "\n";
// val_trunc = val;
// fprintf(fp, "%02x", val_trunc); //length field
// }
// fclose(fp);
// pos -= bytes;
// }
// ticket_nonce_b = true;
// }
// if (name == "extensions" && ticket_b && !extensions_b) {
// std::cerr << "deser-open_field: name BITE : " << name << "\n";
// // int128_t val;
// // getn(val,bytes);
// ////std::cerr << "deser-open_field: val BITE : " << val << "\n";
// //std::cerr << "deser-open_field: pos+bytes BITE : " << pos+bytes << "\n";
// const char * session_file = getenv("STFILE2");
// FILE *fp;
// if(session_file != NULL) {
// fp = fopen(session_file,"a");
// uint16_t val_trunc = bytes;
// fprintf(fp, "%02hhx%02hhx", val_trunc >> 8, val_trunc);
// fclose(fp);
// }
// extensions_b = true;
// }
// if (name == "tls.early_data" && !early_data_b) {
//std::cerr << "deser-open_field: name BITE : " << name << "\n";
// int128_t val;
// getn(val,bytes);
////std::cerr << "deser-open_field: val BITE : " << val << "\n";
//std::cerr << "deser-open_field: pos+bytes BITE : " << pos+bytes << "\n";
// const char * session_file = getenv("STFILE2");
// FILE *fp;
// if(session_file != NULL) {
// fp = fopen(session_file,"a");
// uint16_t val_trunc1 = 42;
// fprintf(fp, "%02hhx%02hhx", val_trunc1 >> 8, val_trunc1);
// uint16_t val_trunc = bytes;
// fprintf(fp, "%02hhx%02hhx", val_trunc >> 8, val_trunc);
// for(int j = 0; j < bytes; j++) {
// int128_t val;
// getn(val,1);
// //std::cerr << "deser-open_field: val BITE : " << val << "\n";
// val_trunc = val;
// fprintf(fp, "%02x", val_trunc); //length field
// }
// fclose(fp);
// pos -= bytes;
// }
//early_data_b = true;
//}
}
else if (fence.size() > 0) {
unsigned b = fence.back();
std::cerr << "4) pkt-pos = " << b << "\n";
fence.push_back(b);
}
if (tls_field_bytes_map.find(name) != tls_field_bytes_map.end()) {
field_bytes = tls_field_bytes_map[name];
// if (name == "ticket_lifetime" ||
// name == "ticket_age_add") {
//std::cerr << "deser-open_field: name BITE : " << name << "\n";
//int128_t val;
//getn(val,field_bytes);
//std::cerr << "deser-open_field: val BITE : " << val << "\n";
//std::cerr << "deser-open_field: pos+bytes BITE : " << pos+bytes << "\n";
// const char * session_file = getenv("STFILE2");
// FILE *fp;
// if(session_file != NULL) {
// if (name == "ticket_lifetime")
// fp = fopen(session_file,"w");
// else
// fp = fopen(session_file,"a");
// int32_t val_trunc = val;
// //fprintf(fp, "%04x", val_trunc);
// fprintf(fp, "%02hhx%02hhx%02hhx%02hhx", val_trunc >> 24, val_trunc >> 16, val_trunc >> 8, val_trunc);
// fclose(fp);
// }
//pos -= field_bytes;
//}
std::cerr << "deser-open_field: field_bytes : " << field_bytes << "\n";
}
if (name == "tls.encrypted_extensions") {
in_encrypted_extensions = fence.size();
}
}
virtual void close_field() {
if (fence.size() == in_encrypted_extensions)
in_encrypted_extensions = 0;
if (fence.size() > 0)
fence.pop_back();
}
virtual int open_tag(const std::vector<std::string> &tags) {
int bytes = 1;
if (tls_tag_bytes_map.find(tags[0]) != tls_tag_bytes_map.end()) {
bytes = tls_tag_bytes_map[tags[0]];
}
int128_t tag;
int128_t tag_new;
uint128_t tag_final; //uint128_t
//long long tag;
//long long tag_new;
//unsigned long long tag_final;
long long mask;
getn(tag,bytes);
std::cerr << "tag v1: " << tag << "\n";
std::cerr << "bytes v1: " << bytes << "\n";
u_int tag_int = (u_int) tag; //TODO change could be dangerous
int tag_size = (tag_int >> 6) & ((1 << 2) -1);
if(tag_size == 0) {
tag_size = 1;
mask = 0x3ff;
} else if(tag_size == 1) {
tag_size = 2;
mask = 0x3fff;
} else if(tag_size == 2) {
tag_size = 4;
mask = 0x3fffffff;
} else if(tag_size == 3) {
tag_size = 8;
mask = 0x3fffffffffffffff;
}
bool is_unknow = false;
if(tag > 0x0f && tag != 0x002a && tag != 0x0029)
is_unknow = true;
//if(tag == 0x00C0)
// is_unknow = false;
std::cerr << "is_unknow: " << is_unknow << "\n";
if(tag == 0x002a || tag == 0x0029)
tag_size = 2;
std::cerr << "Tag size: " << tag_size << "\n";
std::cerr << "tags[0]: " << tags[0] << "\n";
int128_t value_size = 0;
//long long value_size = 0;
if((tags[0] == "tls.client_hello" || tags[0] == "tls.server_hello") && tag == 4) {
// new session ticket
//tls_field_bytes_map["ticket"] = value_size;
is_session_ticket = true;
}
if((((tag_size != bytes || is_unknow || tag == 0x1010 || tag == 0x0f || tag == 0x00 || tag == 0x0d)
&& tags[0] != "tls.client_hello" && tags[0] != "tls.unknown_extension" //&& tags[0] != "tls.early_data" && tags[0] != "tls.unknown_extension"
&& tags[0] != "tls.server_hello"))
|| tag ==0x002a || tag == 0x0029) { //|| tag == 0x0d
tls_tag_bytes_map["unknown_transport_parameter"] = tag_size;
pos -= bytes;
bytes = tag_size;
getn(tag_new,bytes);
//unsigned long long tag_intt = (uint128_t) tag_new;
uint128_t tag_intt = (uint128_t) tag_new;
tag_final = (tag_intt & mask);
if(tag == 0x0029 || tag == 0x002a) {
getn(value_size,2);
pos -= 2;
} else {
getn(value_size,1);
pos -= 1;
}
std::cerr << "tag: " << tag << "\n";
std::cerr << "value_size: " << value_size << "\n";
if(tag == 0x0f || tag == 0x00) {
tls_field_bytes_map["scid"] = value_size;
}
else if(tag == 0x002a) {
tls_field_bytes_map["max_early_data_size"] = value_size;
}
/*else if(tag == 0x0029) {
tls_field_bytes_map["content_psk"] = value_size;
//tls_field_bytes_map["tls.pre_shared_key"] = value_size;
}*/
else if(tag == 0x0d) {
int128_t pcil = value_size - 4 - 2 -16 - 2 - 1 - 16;
std::cerr << "pcil: " << pcil << "\n";
std::cerr << "pref_add: " << (pcil+4+2+16+2+1+16) << "\n";
tls_field_bytes_map["pcid"] = pcil;
}
else if(tag == 0x10) { // else if(tag == 0x1010) {
tls_field_bytes_map["rcid"] = value_size;
}
else if (is_unknow) {
tls_field_bytes_map["unknown"] = value_size;
}
} else {
tag_final = tag;
}
unsigned long long casted_tag = (unsigned long long)(tag_final & 0xFFFFFFFFFFFFFFFF);
std::cerr << "value_size: " << value_size << "\n";
std::cerr << "tag v2: " << casted_tag << "\n";
if(casted_tag == 4278509082)
tag_final = -4611686014148878822; //TODO hack
for (int i = 0; i < tags.size(); i++) {
// std::cerr << "tags[i]: " << tags[i] << "\n";
// std::cerr << "tls_tags_map[tags[i]]: " << tls_tags_map[tags[i]] << "\n";
if (tag_final == tls_tags_map[tags[i]]) {
if(is_server_hello && tags[i] == "tls.pre_shared_key_client")
continue;
else {
open_field(tags[i]);
return i;
}
}
}
for (int i = 0; i < tags.size(); i++) {
if (-1 == tls_tags_map[tags[i]]) {
if(is_server_hello && tags[i] == "tls.pre_shared_key_client")
continue;
else {
pos -= bytes; // leave the unknown tag to parse again
open_field(tags[i]);
return i;
}
}
}
for (int i = 0; i < tags.size(); i++) {
if (-2 == tls_tags_map[tags[i]]) {
if(is_server_hello && tags[i] == "tls.pre_shared_key_client")
continue;
else {
open_field(tags[i]);
return i;
}
}
}
std::cerr << "error tls_desert 1\n";
throw deser_err();
}
virtual void close_tag() {
close_field();
}
virtual void get(int128_t &res) {
//virtual void get(long long &res) {
if (field_bytes == -1) get_var_int(res);
else getn(res,field_bytes);
}
void get_var_int(int128_t &res) {
//void get_var_int(long long &res) {
static int lens[4] = {0,1,3,7};
int128_t lobyte;
//long long lobyte;
ivy_binary_deser_128::getn(lobyte,1);
//ivy_binary_deser::getn(lobyte,1);
int bytes = lens[(lobyte & 0xc0) >> 6];
ivy_binary_deser_128::getn(res,bytes);
//ivy_binary_deser::getn(res,bytes);
res |= (lobyte & 0x3f) << (bytes << 3);
}
virtual bool open_list_elem() {
if (fence.size() == 0) { // tricky: see if input contains a full message
if (!more(4)) {
return false;
}
unsigned len = (inp[pos+1] << 16) + (inp[pos+2] << 8) + inp[pos];
return inp.size() >= pos + len + 4;
}
return more(1);
}
void close_list_elem() {}
void open_list() {}
void close_list() {}
~tls_deser(){}
};
struct `tls_ser` : public ivy_binary_ser_128 {
//struct `tls_ser` : public ivy_binary_ser {
int field_bytes;
std::vector<uint128_t> field_start;
std::vector<uint128_t> field_length_bytes;
//std::vector<unsigned long long> field_start;
//std::vector<unsigned long long> field_length_bytes;
int in_encrypted_extensions;
tls_ser() {
in_encrypted_extensions = 0;
if(const char* env_p3 = std::getenv("INITIAL_VERSION")) {
std::cerr << "INITIAL_VERSION " << env_p3 << "\n";
int iversion = atoi(env_p3);
std::cerr << "INITIAL_VERSION " << iversion << "\n";
if(iversion == 1) {
tls_tags_map["coap_transport_parameters"] = 0x39;
} else {
tls_tags_map["coap_transport_parameters"] = 0xffa5;
}
std::cerr << "tls_tags_map[coap_transport_parameters] " << tls_tags_map["coap_transport_parameters"] << "\n";
}
}
/**
* Allocate memory for each transport parameters
*/
virtual void open_field(const std::string &name) {
int flb = 0;
std::cerr << "ser-open_field: name 1: " << name << "\n";
// if(name == "tls.server_hello")
// is_server_hello = true;
if (name == "random_bytes") {
field_bytes = 1;
}
/*else if (name == "content_psk") {
field_bytes = 2;
}else if (name == "tls.new_session_ticket") {
field_bytes = 1;
}*/ else if (name == "versions") {
field_bytes = 4;
if (in_encrypted_extensions) {
flb = 1;
res.resize(res.size() + flb);
}
}
else if (name != "tls.early_data" && // && name != "tls.pre_shared_key_client" && name != "identity"
tls_field_length_bytes_map.find(name) != tls_field_length_bytes_map.end()) {
flb = tls_field_length_bytes_map[name];
std::cerr << "ser-open_field: flb : " << flb << "\n";
res.resize(res.size() + flb);
}
std::cerr << "ser-open_field: field_start.push_back(res.size()) : " << res.size() << "\n";
std::cerr << "ser-open_field: ffield_length_bytes.push_back(flb) : " << flb << "\n";
field_start.push_back(res.size());
field_length_bytes.push_back(flb);
if (tls_field_bytes_map.find(name) != tls_field_bytes_map.end()
) { //&& name != "psk_identities"
field_bytes = tls_field_bytes_map[name];
std::cerr << "ser-open_field: name_field_bytes 1: " << field_bytes << "\n";
} else
std::cerr << "ser-open_field: name_field_bytes 2: " << field_bytes << "\n";
if (name == "tls.encrypted_extensions") { // || name == "tls.new_session_ticket"
in_encrypted_extensions = field_start.size();
std::cerr << "ser-open_field: name == tls.encrypted_extensions 2: " << in_encrypted_extensions << "\n";
}
std::cerr << "ser-open_field: field_bytes: " << field_bytes << "\n";
std::cerr << "ser-open_field: res.size() : " << res.size() << "\n";
}
//TODO [xx]
virtual void close_field() {
if (field_start.size() == in_encrypted_extensions)
in_encrypted_extensions = 0;
// tricky -- go back and fill in the length bytes after the field is serialized
int start = field_start.back();
int end = res.size();
int flb = field_length_bytes.back();
std::vector<char> temp;
temp.swap(res);
int len = end-start;
std::cerr << "ser-close_field: start : " << start << "\n";
std::cerr << "ser-close_field: end : " << end << "\n";
std::cerr << "ser-close_field: len : " << len << "\n";
std::cerr << "ser-close_field: flb : " << flb << "\n";
std::cerr << "-------------------" << "\n";
setn(len,flb);
temp.swap(res); //[xx] remove
std::copy(temp.begin(),temp.end(),res.begin()+start-flb); // [xx] remove
field_start.pop_back();
field_length_bytes.pop_back();
}
virtual void open_tag(int ivy_tag, const std::string &name) {
int bytes = 1;
if (tls_tag_bytes_map.find(name) != tls_tag_bytes_map.end())
bytes = tls_tag_bytes_map[name];
int128_t tag = tls_tags_map[name];
std::cerr << "ser-open_tag: bytes : " << bytes << "\n";
std::cerr << "ser-open_tag: tag : " << tag << "\n";
//long long tag = tls_tags_map[name];
if (tag !=-1) {
std::cerr << "ser-open_tag: tag != -1: \n";
setn(tag,bytes); // var int ?
}
if(const char* env_p2 = std::getenv("TEST_TYPE")) {
// because it seralize directly so we dont know the scid/dcid length
// TODO maybe change and put the value directly in envvar
std::cerr << "TEST_TYPE " << env_p2 << "\n";
if(strcmp(env_p2, "client") == 0) {
if(const char* env_p3 = std::getenv("TEST_SCIL")) {
std::cerr << "TEST_SCIL " << env_p3 << "\n";
//tls_field_bytes_map["scid"] = atoi(env_p3);
}
if(const char* env_p3 = std::getenv("TEST_DCIL")) {
std::cerr << "TEST_DCIL " << env_p3 << "\n";
tls_field_bytes_map["dcid"] = atoi(env_p3);
}
if(const char* env_p3 = std::getenv("TEST_PCIL")) {
std::cerr << "TEST_PCIL " << env_p3 << "\n";
tls_field_bytes_map["pcid"] = atoi(env_p3);
}
}
}
open_field(name);
}
virtual void close_tag() {
close_field();
}
void set(int128_t inp) {
//void set(long long inp) {
if (field_bytes == -1) set_var_int(inp);
else setn(inp,field_bytes);
}
void set_var_int(int128_t res) {
int128_t val = res & 0x3fffffffffffffff;
//void set_var_int(long long res) {
// long long val = res & 0x3fffffffffffffff;
int bytecode = res <= 0x3f ? 0 : res <= 0x3fff ? 1 : res <= 0x3fffffff ? 2 : 3;
int bytes = 1 << bytecode;
val |= bytecode << ((bytes << 3) - 2);
setn(val,bytes);
}
void open_list(int len) {
}
};
struct `tls_ser_server` : public tls_ser {
// This version of the serializer uses the server format. The only difference is
// that the coap_extension structure has an extra field "versions".
tls_ser_server() {
in_encrypted_extensions = -1;
}
};
>>>
<<< init
tls_make_name_map(tls_field_length_bytes,tls_field_length_bytes_map);
tls_make_name_map(tls_field_bytes,tls_field_bytes_map);
tls_make_name_map(tls_tags,tls_tags_map);
tls_make_name_map(tls_tag_bytes,tls_tag_bytes_map);
>>>