Skip to content

Commit a5b429f

Browse files
committedAug 22, 2021
initial commit
0 parents  commit a5b429f

10 files changed

+624
-0
lines changed
 

‎.ccls

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
clang
2+
%h
3+
-I.

‎.clang-format

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
BasedOnStyle: LLVM
3+
IndentWidth: 4
4+
---
5+

‎.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.nvimlog
2+
.nvim
3+
a.out
4+
example
5+
test

‎LICENSE

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Boost Software License - Version 1.0 - August 17th, 2003
2+
3+
Permission is hereby granted, free of charge, to any person or organization
4+
obtaining a copy of the software and accompanying documentation covered by
5+
this license (the "Software") to use, reproduce, display, distribute,
6+
execute, and transmit the Software, and to prepare derivative works of the
7+
Software, and to permit third-parties to whom the Software is furnished to
8+
do so, all subject to the following:
9+
10+
The copyright notices in the Software and this entire statement, including
11+
the above license grant, this restriction and the following disclaimer,
12+
must be included in all copies of the Software, in whole or in part, and
13+
all derivative works of the Software, unless such copies or derivative
14+
works are solely in the form of machine-executable object code generated by
15+
a source language processor.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23+
DEALINGS IN THE SOFTWARE.

‎Makefile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CFLAGS ?= -O2 -Wall -Wextra -Wfloat-equal -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wmissing-declarations -Wredundant-decls -Wshadow
2+
3+
all: test example
4+
5+
test: tests.c cCHello.c
6+
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
7+
8+
example: example.c cCHello.c
9+
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
10+
11+
clean:
12+
rm -rf example
13+
rm -rf test

‎README.md

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# cCHello
2+
3+
A minimal TLS client hello parser.
4+
5+
# Features
6+
- compatible with C99
7+
- no dependencies
8+
- ~100 LOC
9+
- simple API
10+
- extensive overflow checks
11+
12+
# API
13+
```c
14+
client_hello_t *cchello_client_hello_init(void);
15+
int cchello_parse(client_hello_t *ch, uint8_t *data, size_t data_len);
16+
void cchello_client_hello_free(client_hello_t *ch);
17+
```
18+
19+
# Usage
20+
21+
```c
22+
#include "cCHello.h"
23+
...
24+
client_hello_t *ch == cchello_client_hello_init();
25+
if (ch == NULL)
26+
// handle alloc failure.
27+
28+
int ret = cchello_parse(ch, data, data_len);
29+
if (ret < 0)
30+
// handle cchello error.
31+
else
32+
// you may want to check if cchello read all of the data
33+
assert(data_len == ret);
34+
35+
// remember to free!
36+
cchello_client_hello_free(ch);
37+
```
38+
39+
# Example
40+
41+
After running the example binary, visit the URL [https://localhost:1337](https://localhost:1337) in your browser.
42+
43+
```sh
44+
$ make example
45+
cc -O2 -Wall -Wextra -Wfloat-equal -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wmissing-declarations -Wredundant-decls -Wshadow -o test tests.c cCHello.c
46+
$ ./example
47+
[...]
48+
```
49+
50+
# Tests
51+
```sh
52+
$ make test
53+
cc -O2 -Wall -Wextra -Wfloat-equal -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wmissing-declarations -Wredundant-decls -Wshadow -o test tests.c cCHello.c
54+
$ ./test
55+
[...]
56+
ALL TESTS PASSED.
57+
```
58+
59+
# Thanks
60+
[Michael Driscoll](https://github.com/syncsynchalt) for the [illustrated TLS connection](https://github.com/syncsynchalt/illustrated-tls)
61+
62+
# License
63+
[BSL-1.0 License](https://github.com/BlazeWasHere/cCHello/blob/master/LICENSE)

‎cCHello.c

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright Blaze 2021.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE or copy at
4+
// https://www.boost.org/LICENSE_1_0.txt)
5+
6+
#include <string.h>
7+
8+
#include "cCHello.h"
9+
10+
#define OVERFLOW_CHECK(num) \
11+
if (num > data_len) \
12+
return CCHELLO_OVERFLOW;
13+
14+
static inline uint32_t concat_bytes(uint8_t x, uint8_t y, uint8_t z) {
15+
return (x << 16) | (y << 8) | z;
16+
}
17+
18+
enum tls_version cchello_parse_version(uint8_t major, uint8_t minor) {
19+
uint32_t ret = concat_bytes(0, major, minor);
20+
21+
if (ret == TLS_1_0 || ret == TLS_1_1 || ret == TLS_1_2 || ret == TLS_1_3)
22+
return ret;
23+
24+
return UNKNOWN;
25+
}
26+
27+
client_hello_t *cchello_client_hello_init(void) {
28+
return (client_hello_t *)calloc(1, sizeof(client_hello_t));
29+
}
30+
31+
int cchello_parse(client_hello_t *ch, uint8_t *data, size_t data_len) {
32+
uint32_t handshake_len, ch_data_len;
33+
size_t read = 0;
34+
35+
if (data_len == 0)
36+
return read;
37+
38+
for (read = 0; read < data_len; read++) {
39+
switch (read) {
40+
case 0:
41+
// 0x16 = handshake record
42+
if (data[read] != 0x16)
43+
return CCHELLO_WRONG_PACKET;
44+
break;
45+
case 2:
46+
ch->version = cchello_parse_version(data[read - 1], data[read]);
47+
break;
48+
case 4:
49+
handshake_len = concat_bytes(0, data[read - 1], data[read]);
50+
OVERFLOW_CHECK(handshake_len + read)
51+
break;
52+
case 5:
53+
// handshake message type 0x1 = client hello
54+
if (data[read] != 0x1)
55+
return CCHELLO_WRONG_PACKET;
56+
break;
57+
case 8:
58+
ch_data_len =
59+
concat_bytes(data[read - 2], data[read - 1], data[read]);
60+
OVERFLOW_CHECK(ch_data_len + read)
61+
break;
62+
case 11:
63+
// TODO: what to do with this, is it even needed?
64+
// cchello_parse_version(data[read - 1], data[read]);
65+
break;
66+
case 42:
67+
memcpy(ch->random, data + 11, 32);
68+
break;
69+
case 43:
70+
// session id
71+
ch->session_id_len = data[read];
72+
OVERFLOW_CHECK(ch->session_id_len + read);
73+
74+
ch->session_id = calloc(sizeof(uint8_t), ch->session_id_len);
75+
if (ch->session_id == NULL)
76+
return CCHELLO_NOMEM;
77+
78+
memcpy(ch->session_id, data + read + 1, ch->session_id_len);
79+
// +1 byte; for the session_id_len byte
80+
read += ch->session_id_len + 1;
81+
82+
// cipher suites
83+
OVERFLOW_CHECK(read + 1);
84+
ch->cipher_suites_len = concat_bytes(0, data[read], data[read + 1]);
85+
OVERFLOW_CHECK(ch->cipher_suites_len + read);
86+
87+
ch->cipher_suites = calloc(sizeof(uint8_t), ch->cipher_suites_len);
88+
if (ch->cipher_suites == NULL)
89+
return CCHELLO_NOMEM;
90+
91+
// cipher_suites_len takes 2 bytes
92+
read += 2;
93+
memcpy(ch->cipher_suites, data + read, ch->cipher_suites_len);
94+
read += ch->cipher_suites_len;
95+
96+
// compression methods
97+
ch->compression_methods_len = data[read];
98+
OVERFLOW_CHECK(ch->compression_methods_len + read);
99+
100+
ch->compression_methods =
101+
calloc(sizeof(uint8_t), ch->cipher_suites_len);
102+
memcpy(ch->compression_methods, data + read + 1,
103+
ch->compression_methods_len);
104+
read += ch->compression_methods_len + 1;
105+
106+
// extensions
107+
OVERFLOW_CHECK(read + 1);
108+
ch->extensions_len = concat_bytes(0, data[read], data[read + 1]);
109+
OVERFLOW_CHECK(ch->extensions_len + read);
110+
111+
ch->extensions = calloc(sizeof(uint8_t), ch->extensions_len);
112+
if (ch->extensions == NULL)
113+
return CCHELLO_NOMEM;
114+
115+
read += 2;
116+
memcpy(ch->extensions, data + read, ch->extensions_len);
117+
read += ch->extensions_len;
118+
119+
return read;
120+
}
121+
}
122+
123+
return read;
124+
}
125+
126+
void cchello_client_hello_free(client_hello_t *ch) {
127+
free(ch->extensions);
128+
free(ch->compression_methods);
129+
free(ch->cipher_suites);
130+
free(ch->session_id);
131+
free(ch);
132+
133+
// prevent segfault from freeing twice
134+
ch = NULL;
135+
}

‎cCHello.h

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright Blaze 2021.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE or copy at
4+
// https://www.boost.org/LICENSE_1_0.txt)
5+
6+
#ifndef _CCHELLO_H
7+
#define _CCHELLO_H
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
#include <stddef.h>
13+
#include <stdint.h>
14+
#include <stdlib.h>
15+
16+
#define TLS_VERSION_NUMBER(id) \
17+
((((id##_VERSION_MAJOR) & 0xFF) << 8) | ((id##_VERSION_MINOR) & 0xFF))
18+
19+
#define TLS_1_0_VERSION_MAJOR 0x3
20+
#define TLS_1_0_VERSION_MINOR 0x1
21+
22+
#define TLS_1_1_VERSION_MAJOR 0x3
23+
#define TLS_1_1_VERSION_MINOR 0x2
24+
25+
#define TLS_1_2_VERSION_MAJOR 0x3
26+
#define TLS_1_2_VERSION_MINOR 0x3
27+
28+
#define TLS_1_3_VERSION_MAJOR 0x3
29+
#define TLS_1_3_VERSION_MINOR 0x4
30+
31+
enum tls_version {
32+
UNKNOWN = -1,
33+
TLS_1_0 = TLS_VERSION_NUMBER(TLS_1_0),
34+
TLS_1_1 = TLS_VERSION_NUMBER(TLS_1_1),
35+
TLS_1_2 = TLS_VERSION_NUMBER(TLS_1_2),
36+
TLS_1_3 = TLS_VERSION_NUMBER(TLS_1_3),
37+
};
38+
39+
enum cchello_err {
40+
/* The packet given is not a handshake record or a client hello. */
41+
CCHELLO_WRONG_PACKET = -1,
42+
/* An overflow/overstep would have occured. */
43+
CCHELLO_OVERFLOW = -2,
44+
/* Not enough memory. */
45+
CCHELLO_NOMEM = -3,
46+
};
47+
48+
typedef struct {
49+
/* The client's TLS version */
50+
enum tls_version version;
51+
/* The client provides 32 bytes of random data. This data will be used
52+
* later in the session. In this example we've made the random data a
53+
* predictable string. */
54+
uint8_t random[32];
55+
/* The client can provide the ID of a previous TLS session against this
56+
* server which it is able to resume. */
57+
uint8_t *session_id;
58+
uint8_t session_id_len;
59+
/* The client provides an ordered list of which cryptographic methods it
60+
* will support for key exchange, encryption with that exchanged key, and
61+
* message authentication. The list is in the order preferred by the client,
62+
* with highest preference first. */
63+
uint8_t *cipher_suites;
64+
uint32_t cipher_suites_len;
65+
/* The client provides an ordered list of which compression methods it will
66+
* support. This compression would be applied before encryption (as
67+
* encrypted data is usually incompressible). */
68+
uint8_t *compression_methods;
69+
uint8_t compression_methods_len;
70+
/* The client has provided a list of optional extensions which the server
71+
* can use to take action or enable new features. */
72+
uint8_t *extensions;
73+
uint32_t extensions_len;
74+
} client_hello_t;
75+
76+
enum tls_version cchello_parse_version(uint8_t major, uint8_t minor);
77+
78+
/* if <0, error; else returns bytes read from `data` */
79+
int cchello_parse(client_hello_t *ch, uint8_t *data, size_t data_len);
80+
81+
client_hello_t *cchello_client_hello_init(void);
82+
83+
void cchello_client_hello_free(client_hello_t *ch);
84+
85+
#ifdef __cplusplus
86+
}
87+
#endif
88+
89+
#endif // _CCHELLO_H

‎example.c

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright Blaze 2021.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE or copy at
4+
// https://www.boost.org/LICENSE_1_0.txt)
5+
6+
#include <err.h>
7+
#include <netinet/in.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <sys/socket.h>
11+
12+
#include "cCHello.h"
13+
14+
#define RECV_MAX 1024
15+
#define BACKLOG 256
16+
#define PORT 1337
17+
18+
static int setup_socket(int port) {
19+
struct sockaddr_in address;
20+
int ret;
21+
22+
int sock = socket(AF_INET, SOCK_STREAM, 0);
23+
if (sock == -1)
24+
err(EXIT_FAILURE, "Failed to create a socket");
25+
26+
int optval = 1;
27+
28+
ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
29+
if (ret == -1)
30+
err(EXIT_FAILURE, "Failed to set socket opt");
31+
32+
address.sin_family = AF_INET;
33+
address.sin_port = htons(port);
34+
address.sin_addr.s_addr = htonl(INADDR_ANY);
35+
36+
ret = bind(sock, (struct sockaddr *)&address, sizeof(address));
37+
if (ret == -1)
38+
err(EXIT_FAILURE, "Failed to bind the socket");
39+
40+
ret = listen(sock, BACKLOG);
41+
if (ret == -1)
42+
err(EXIT_FAILURE, "Failed to listen with the socket");
43+
44+
return sock;
45+
}
46+
47+
static void print_hex(uint8_t *data, uint32_t data_len) {
48+
printf("{");
49+
50+
for (size_t i = 0; i < data_len; i++)
51+
if (i != (data_len - 1))
52+
printf("0x%x, ", data[i]);
53+
else
54+
printf("0x%x", data[i]);
55+
56+
printf("}\n");
57+
}
58+
59+
int main(void) {
60+
struct sockaddr_in client_addr;
61+
uint8_t buffer[RECV_MAX];
62+
ssize_t buf_len;
63+
int ret;
64+
65+
socklen_t addr_size = sizeof(client_addr);
66+
int socket = setup_socket(PORT);
67+
68+
socket = accept(socket, (struct sockaddr *)&client_addr, &addr_size);
69+
if (socket == -1)
70+
err(EXIT_FAILURE, "Failed to accept with the socket");
71+
72+
buf_len = recv(socket, buffer, RECV_MAX, 0);
73+
if (buf_len == -1)
74+
err(EXIT_FAILURE, "Failed to read data from the socket");
75+
76+
client_hello_t *ch = calloc(1, sizeof(client_hello_t));
77+
if (ch == NULL)
78+
errx(EXIT_FAILURE, "out of memory");
79+
80+
ret = cchello_parse(ch, buffer, buf_len);
81+
printf("function ret: %d, data size: %ld\n", ret, buf_len);
82+
83+
printf("tls version: %d\n", ch->version);
84+
printf("session id: ");
85+
print_hex(ch->session_id, ch->session_id_len);
86+
printf("random: ");
87+
print_hex(ch->random, sizeof(ch->random));
88+
printf("compression methods: ");
89+
print_hex(ch->compression_methods, ch->compression_methods_len);
90+
printf("cipher suites: ");
91+
print_hex(ch->cipher_suites, ch->cipher_suites_len);
92+
printf("extensions: ");
93+
print_hex(ch->extensions, ch->extensions_len);
94+
95+
return 0;
96+
}

‎tests.c

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// Copyright Blaze 2021.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE or copy at
4+
// https://www.boost.org/LICENSE_1_0.txt)
5+
6+
#include <assert.h>
7+
#include <stdbool.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
12+
#include "cCHello.h"
13+
14+
static uint8_t ch_1_3[] = {
15+
0x16, 0x03, 0x01, 0x00, 0xca, 0x01, 0x00, 0x00, 0xc6, 0x03, 0x03, 0x00,
16+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
17+
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
18+
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0xe0, 0xe1, 0xe2, 0xe3,
19+
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
20+
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
21+
0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x06, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03,
22+
0x01, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x18, 0x00, 0x16, 0x00, 0x00,
23+
0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66,
24+
0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x0a, 0x00, 0x08,
25+
0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x0d, 0x00, 0x14,
26+
0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05,
27+
0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x33, 0x00, 0x26,
28+
0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x35, 0x80, 0x72, 0xd6, 0x36, 0x58,
29+
0x80, 0xd1, 0xae, 0xea, 0x32, 0x9a, 0xdf, 0x91, 0x21, 0x38, 0x38, 0x51,
30+
0xed, 0x21, 0xa2, 0x8e, 0x3b, 0x75, 0xe9, 0x65, 0xd0, 0xd2, 0xcd, 0x16,
31+
0x62, 0x54, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x2b, 0x00, 0x03,
32+
0x02, 0x03, 0x04};
33+
34+
static uint8_t ch_1_2[] = {
35+
0x16, 0x03, 0x01, 0x00, 0xa5, 0x01, 0x00, 0x00, 0xa1, 0x03, 0x03, 0x00,
36+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
37+
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
38+
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x20, 0xcc, 0xa8,
39+
0xcc, 0xa9, 0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x13,
40+
0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f,
41+
0x00, 0x35, 0xc0, 0x12, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00,
42+
0x00, 0x18, 0x00, 0x16, 0x00, 0x00, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70,
43+
0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e,
44+
0x65, 0x74, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
45+
0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00,
46+
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00,
47+
0x10, 0x04, 0x01, 0x04, 0x03, 0x05, 0x01, 0x05, 0x03, 0x06, 0x01, 0x06,
48+
0x03, 0x02, 0x01, 0x02, 0x03, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x12,
49+
0x00, 0x00};
50+
51+
static void assert_array(uint8_t *x, uint8_t *y, size_t len) {
52+
assert(memcmp(x, y, sizeof(uint8_t) * len) == 0);
53+
}
54+
55+
static void print_hex(uint8_t *data, uint32_t data_len) {
56+
printf("{");
57+
58+
for (size_t i = 0; i < data_len; i++)
59+
if (i != (data_len - 1))
60+
printf("0x%x, ", data[i]);
61+
else
62+
printf("0x%x", data[i]);
63+
64+
printf("}\n");
65+
}
66+
67+
static client_hello_t *ch_init() {
68+
client_hello_t *ch = cchello_client_hello_init();
69+
if (ch == NULL) {
70+
fprintf(stderr, "out of memory\n");
71+
exit(EXIT_FAILURE);
72+
}
73+
74+
return ch;
75+
}
76+
77+
static void test_ch_1_3() {
78+
client_hello_t *ch = ch_init();
79+
80+
uint8_t c_session_id[] = {0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
81+
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
82+
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
83+
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
84+
uint8_t c_random[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
85+
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
86+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
87+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
88+
uint8_t c_ciphers[] = {0x13, 0x1, 0x13, 0x2, 0x13, 0x3};
89+
uint8_t c_extensions[] = {
90+
0x0, 0x0, 0x0, 0x18, 0x0, 0x16, 0x0, 0x0, 0x13, 0x65, 0x78, 0x61,
91+
0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d,
92+
0x2e, 0x6e, 0x65, 0x74, 0x0, 0xa, 0x0, 0x8, 0x0, 0x6, 0x0, 0x1d,
93+
0x0, 0x17, 0x0, 0x18, 0x0, 0xd, 0x0, 0x14, 0x0, 0x12, 0x4, 0x3,
94+
0x8, 0x4, 0x4, 0x1, 0x5, 0x3, 0x8, 0x5, 0x5, 0x1, 0x8, 0x6,
95+
0x6, 0x1, 0x2, 0x1, 0x0, 0x33, 0x0, 0x26, 0x0, 0x24, 0x0, 0x1d,
96+
0x0, 0x20, 0x35, 0x80, 0x72, 0xd6, 0x36, 0x58, 0x80, 0xd1, 0xae, 0xea,
97+
0x32, 0x9a, 0xdf, 0x91, 0x21, 0x38, 0x38, 0x51, 0xed, 0x21, 0xa2, 0x8e,
98+
0x3b, 0x75, 0xe9, 0x65, 0xd0, 0xd2, 0xcd, 0x16, 0x62, 0x54, 0x0, 0x2d,
99+
0x0, 0x2, 0x1, 0x1, 0x0, 0x2b, 0x0, 0x3, 0x2, 0x3, 0x4};
100+
101+
printf("TEST: parsing tls1.3 client hello: START.\n");
102+
int ret = cchello_parse(ch, ch_1_3, sizeof(ch_1_3));
103+
assert(ret == sizeof(ch_1_3));
104+
105+
printf("tls version: %d\n", ch->version);
106+
assert(ch->version == TLS_1_0);
107+
108+
printf("session id: ");
109+
print_hex(ch->session_id, ch->session_id_len);
110+
assert_array(ch->session_id, c_session_id, sizeof(c_session_id));
111+
112+
printf("random: ");
113+
print_hex(ch->random, sizeof(ch->random));
114+
assert_array(ch->random, c_random, sizeof(c_random));
115+
116+
printf("compression methods: ");
117+
print_hex(ch->compression_methods, ch->compression_methods_len);
118+
assert(ch->compression_methods[0] == 0x0);
119+
120+
printf("cipher suites: ");
121+
print_hex(ch->cipher_suites, ch->cipher_suites_len);
122+
assert_array(ch->cipher_suites, c_ciphers, sizeof(c_ciphers));
123+
124+
printf("extensions: ");
125+
print_hex(ch->extensions, ch->extensions_len);
126+
assert_array(ch->extensions, c_extensions, sizeof(c_extensions));
127+
128+
printf("TEST: parsing tls1.3 client hello: PASSED.\n\n");
129+
cchello_client_hello_free(ch);
130+
}
131+
132+
static void test_ch_1_2() {
133+
client_hello_t *ch = ch_init();
134+
135+
uint8_t c_session_id[] = {};
136+
uint8_t c_random[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
137+
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
138+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
139+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
140+
uint8_t c_ciphers[] = {0xcc, 0xa8, 0xcc, 0xa9, 0xc0, 0x2f, 0xc0, 0x30,
141+
0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x13, 0xc0, 0x9,
142+
0xc0, 0x14, 0xc0, 0xa, 0x0, 0x9c, 0x0, 0x9d,
143+
0x0, 0x2f, 0x0, 0x35, 0xc0, 0x12, 0x0, 0xa};
144+
uint8_t c_extensions[] = {
145+
0x0, 0x0, 0x0, 0x18, 0x0, 0x16, 0x0, 0x0, 0x13, 0x65, 0x78,
146+
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65,
147+
0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x0, 0x5, 0x0, 0x5, 0x1,
148+
0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0xa, 0x0, 0x8, 0x0,
149+
0x1d, 0x0, 0x17, 0x0, 0x18, 0x0, 0x19, 0x0, 0xb, 0x0, 0x2,
150+
0x1, 0x0, 0x0, 0xd, 0x0, 0x12, 0x0, 0x10, 0x4, 0x1, 0x4,
151+
0x3, 0x5, 0x1, 0x5, 0x3, 0x6, 0x1, 0x6, 0x3, 0x2, 0x1,
152+
0x2, 0x3, 0xff, 0x1, 0x0, 0x1, 0x0, 0x0, 0x12, 0x0, 0x0};
153+
154+
printf("TEST: parsing tls1.2 client hello: START.\n");
155+
int ret = cchello_parse(ch, ch_1_2, sizeof(ch_1_2));
156+
assert(ret == sizeof(ch_1_2));
157+
158+
printf("tls version: %d\n", ch->version);
159+
assert(ch->version == TLS_1_0);
160+
161+
printf("session id: ");
162+
print_hex(ch->session_id, ch->session_id_len);
163+
assert_array(ch->session_id, c_session_id, sizeof(c_session_id));
164+
165+
printf("random: ");
166+
print_hex(ch->random, sizeof(ch->random));
167+
assert_array(ch->random, c_random, sizeof(c_random));
168+
169+
printf("compression methods: ");
170+
print_hex(ch->compression_methods, ch->compression_methods_len);
171+
assert(ch->compression_methods[0] == 0x0);
172+
173+
printf("cipher suites: ");
174+
print_hex(ch->cipher_suites, ch->cipher_suites_len);
175+
assert_array(ch->cipher_suites, c_ciphers, sizeof(c_ciphers));
176+
177+
printf("extensions: ");
178+
print_hex(ch->extensions, ch->extensions_len);
179+
assert_array(ch->extensions, c_extensions, sizeof(c_extensions));
180+
181+
printf("TEST: parsing tls1.2 client hello: PASSED.\n\n");
182+
cchello_client_hello_free(ch);
183+
}
184+
185+
int main(void) {
186+
test_ch_1_2();
187+
test_ch_1_3();
188+
189+
printf("ALL TESTS PASSED.\n");
190+
191+
return 0;
192+
}

0 commit comments

Comments
 (0)
Please sign in to comment.