blob: ef8f5906772a2114edb8455b22e76dab09a67327 [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
2 * MbedTLS SSL context deserializer from base64 code
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Piotr Nowicki9370f902020-03-13 14:43:22 +01005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Piotr Nowicki9370f902020-03-13 14:43:22 +010018 */
19
Mateusz Starzyk6c2e9b62021-05-19 17:54:54 +020020#define MBEDTLS_ALLOW_PRIVATE_ACCESS
21
Bence Szépkútic662b362021-05-27 11:25:03 +020022#include "mbedtls/build_info.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010023
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010024#include <stdio.h>
25#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020026
Gilles Peskinef4a6a052020-11-09 14:55:35 +010027#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
28 !defined(MBEDTLS_SSL_TLS_C)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020029int main(void)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020030{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010031 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
32 "MBEDTLS_SSL_TLS_C not defined.\n");
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020033 return 0;
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020034}
35#else
36
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020037# if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
38# define _CRT_SECURE_NO_DEPRECATE 1
39# endif
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020040
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020041# include <stdint.h>
42# include <stdarg.h>
43# include <string.h>
44# include <time.h>
45# include "mbedtls/ssl.h"
46# include "mbedtls/error.h"
47# include "mbedtls/base64.h"
48# include "mbedtls/md.h"
49# include "mbedtls/x509_crt.h"
50# include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010051
52/*
53 * This program version
54 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020055# define PROG_NAME "ssl_context_info"
56# define VER_MAJOR 0
57# define VER_MINOR 1
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010058
59/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020060 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010061 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020062# define SESSION_CONFIG_TIME_BIT (1 << 0)
63# define SESSION_CONFIG_CRT_BIT (1 << 1)
64# define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
65# define SESSION_CONFIG_MFL_BIT (1 << 3)
66# define SESSION_CONFIG_TRUNC_HMAC_BIT (1 << 4)
67# define SESSION_CONFIG_ETM_BIT (1 << 5)
68# define SESSION_CONFIG_TICKET_BIT (1 << 6)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010069
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020070# define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT (1 << 0)
71# define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT (1 << 1)
72# define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT (1 << 2)
73# define CONTEXT_CONFIG_ALPN_BIT (1 << 3)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010074
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020075# define TRANSFORM_RANDBYTE_LEN 64
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010076
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010077/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020078 * Minimum and maximum number of bytes for specific data: context, sessions,
79 * certificates, tickets and buffers in the program. The context and session
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020080 * size values have been calculated based on the
81 * 'print_deserialized_ssl_context()' and 'print_deserialized_ssl_session()'
82 * content.
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020083 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020084# define MIN_CONTEXT_LEN 84
85# define MIN_SESSION_LEN 88
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020086
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020087# define MAX_CONTEXT_LEN 875 /* without session data */
88# define MAX_SESSION_LEN 109 /* without certificate and ticket data */
89# define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
90# define MAX_TICKET_LEN ((1 << 24) - 1)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020091
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020092# define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
93# define MAX_SERIALIZED_DATA \
94 (MAX_CONTEXT_LEN + MAX_SESSION_LEN + MAX_CERTIFICATE_LEN + \
95 MAX_TICKET_LEN)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020096
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020097# define MIN_BASE64_LEN (MIN_SERIALIZED_DATA * 4 / 3)
98# define MAX_BASE64_LEN (MAX_SERIALIZED_DATA * 4 / 3 + 3)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020099
100/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100101 * A macro that prevents from reading out of the ssl buffer range.
102 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200103# define CHECK_SSL_END(LEN) \
104 do { \
105 if (end - ssl < (int)(LEN)) { \
106 printf_err("%s", buf_ln_err); \
107 return; \
108 } \
109 } while (0)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100110
111/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100112 * Global values
113 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200114FILE *b64_file = NULL; /* file with base64 codes to deserialize */
115char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from
116 mbedTLS configuration */
117char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration
118 */
119char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200120const char alloc_err[] = "Cannot allocate memory\n";
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200121const char buf_ln_err[] =
122 "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100123
124/*
125 * Basic printing functions
126 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200127void print_version()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100128{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200129 printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100130}
131
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200132void print_usage()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100133{
134 print_version();
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200135 printf(
136 "\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
137 "in the text file. The program can deserialize many codes from one file, but they must be\n"
138 "separated, e.g. by a newline.\n\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100139 printf(
140 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100141 "\t-f path - Path to the file with base64 code\n"
142 "\t-v - Show version\n"
143 "\t-h - Show this usage\n"
144 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200145 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100146 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
147 "\t flag. You can also use it if there are some problems with reading\n"
148 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200149 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100150 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200151 "\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100152}
153
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200154void printf_dbg(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100155{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200156 if (debug) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100157 va_list args;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200158 va_start(args, str);
159 printf("debug: ");
160 vprintf(str, args);
161 fflush(stdout);
162 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100163 }
164}
165
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200166void printf_err(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100167{
168 va_list args;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200169 va_start(args, str);
170 fflush(stdout);
171 fprintf(stderr, "ERROR: ");
172 vfprintf(stderr, str, args);
173 fflush(stderr);
174 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100175}
176
177/*
178 * Exit from the program in case of error
179 */
180void error_exit()
181{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200182 if (NULL != b64_file) {
183 fclose(b64_file);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100184 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200185 exit(-1);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100186}
187
188/*
189 * This function takes the input arguments of this program
190 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200191void parse_arguments(int argc, char *argv[])
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100192{
193 int i = 1;
194
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200195 if (argc < 2) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100196 print_usage();
197 error_exit();
198 }
199
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200200 while (i < argc) {
201 if (strcmp(argv[i], "-d") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100202 debug = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200203 } else if (strcmp(argv[i], "-h") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100204 print_usage();
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200205 } else if (strcmp(argv[i], "-v") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100206 print_version();
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200207 } else if (strcmp(argv[i], "-f") == 0) {
208 if (++i >= argc) {
209 printf_err("File path is empty\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100210 error_exit();
211 }
212
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200213 if ((b64_file = fopen(argv[i], "r")) == NULL) {
214 printf_err("Cannot find file \"%s\"\n", argv[i]);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100215 error_exit();
216 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200217 } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100218 conf_keep_peer_certificate = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200219 } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100220 conf_dtls_proto = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200221 } else {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100222 print_usage();
223 error_exit();
224 }
225
226 i++;
227 }
228}
229
Piotr Nowicki14d31052020-03-16 14:05:22 +0100230/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100231 * This function prints base64 code to the stdout
232 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233void print_b64(const uint8_t *b, size_t len)
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100234{
235 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100236 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100237 printf("\t");
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200238 while (b < end) {
239 if (++i > 75) {
240 printf("\n\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100241 i = 0;
242 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200243 printf("%c", *b++);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100244 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200245 printf("\n");
246 fflush(stdout);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100247}
248
249/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100250 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100251 *
252 * /p b buffer with data to print
253 * /p len number of bytes to print
254 * /p in_line number of bytes in one line
255 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100256 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200257void print_hex(const uint8_t *b,
258 size_t len,
259 const size_t in_line,
260 const char *prefix)
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100261{
262 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100263 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100264
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200265 if (prefix == NULL) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100266 prefix = "";
267 }
268
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200269 while (b < end) {
270 if (++i > in_line) {
271 printf("\n%s", prefix);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100272 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100273 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200274 printf("%02X ", (uint8_t)*b++);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100275 }
276 printf("\n");
277 fflush(stdout);
278}
279
280/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100281 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
282 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200283void print_time(const time_t *time)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100284{
285 char buf[20];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200286 struct tm *t = gmtime(time);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100287 static const char format[] = "%Y-%m-%d %H:%M:%S";
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200288 if (NULL != t) {
289 strftime(buf, sizeof(buf), format, t);
290 printf("%s\n", buf);
291 } else {
292 printf("unknown\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100293 }
294}
295
296/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100297 * Print the input string if the bit is set in the value
298 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200299void print_if_bit(const char *str, int bit, int val)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100300{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200301 if (bit & val) {
302 printf("\t%s\n", str);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100303 }
304}
305
306/*
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200307 * Return pointer to hardcoded "enabled" or "disabled" depending on the input
308 * value
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100309 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200310const char *get_enabled_str(int is_en)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100311{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200312 return (is_en) ? "enabled" : "disabled";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100313}
314
315/*
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200316 * Return pointer to hardcoded MFL string value depending on the MFL code at the
317 * input
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100318 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200319const char *get_mfl_str(int mfl_code)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100320{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200321 switch (mfl_code) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100322 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
323 return "none";
324 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
325 return "512";
326 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
327 return "1024";
328 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
329 return "2048";
330 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
331 return "4096";
332 default:
333 return "error";
334 }
335}
336
337/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100338 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
339 * previously. After each call to this function, the internal file position
340 * indicator of the global b64_file is advanced.
341 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200342 * Note - This function checks the size of the input buffer and if necessary,
343 * increases it to the maximum MAX_BASE64_LEN
344 *
345 * /p b64 pointer to the pointer of the buffer for input data
346 * /p max_len pointer to the current buffer capacity. It can be changed if
347 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100348 *
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200349 * \retval number of bytes written in to the b64 buffer or 0 in case no
350 * more
Piotr Nowicki14d31052020-03-16 14:05:22 +0100351 * data was found
352 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200353size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
Piotr Nowicki14d31052020-03-16 14:05:22 +0100354{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200355 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100356 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100357 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000358 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100359
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200360 while (EOF != c) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100361 char c_valid = 0;
362
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200363 c = fgetc(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100364
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200365 if (pad > 0) {
366 if (c == '=' && pad == 1) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100367 c_valid = 1;
368 pad = 2;
369 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200370 } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
371 (c >= '0' && c <= '9') || c == '+' || c == '/') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100372 c_valid = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200373 } else if (c == '=') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100374 c_valid = 1;
375 pad = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200376 } else if (c == '-') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100377 c = '+';
378 c_valid = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200379 } else if (c == '_') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100380 c = '/';
381 c_valid = 1;
382 }
383
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200384 if (c_valid) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200385 /* A string of characters that could be a base64 code. */
386 valid_balance++;
387
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200388 if (len < *max_len) {
389 (*b64)[len++] = c;
390 } else if (*max_len < MAX_BASE64_LEN) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200391 /* Current buffer is too small, but can be resized. */
392 void *ptr;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200393 size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
394 *max_len + 4096 :
395 MAX_BASE64_LEN;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200396
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200397 ptr = realloc(*b64, new_size);
398 if (NULL == ptr) {
399 printf_err(alloc_err);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200400 return 0;
401 }
402 *b64 = ptr;
403 *max_len = new_size;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200404 (*b64)[len++] = c;
405 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200406 /* Too much data so it will be treated as invalid */
407 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100408 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200409 } else if (len > 0) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200410 /* End of a string that could be a base64 code, but need to check
411 * that the length of the characters is correct. */
412
413 valid_balance--;
414
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200415 if (len < MIN_CONTEXT_LEN) {
416 printf_dbg(
417 "The code found is too small to be a SSL context.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200418 len = pad = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200419 } else if (len > *max_len) {
420 printf_err("The code found is too large by %u bytes.\n",
421 len - *max_len);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200422 len = pad = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200423 } else if (len % 4 != 0) {
424 printf_err(
425 "The length of the base64 code found should be a multiple of 4.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200426 len = pad = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200427 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200428 /* Base64 code with valid character length. */
429 return len;
430 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200431 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200432 valid_balance--;
433 }
434
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200435 /* Detection of potentially wrong file format like: binary, zip, ISO,
436 * etc. */
437 if (valid_balance < -100) {
438 printf_err("Too many bad symbols detected. File check aborted.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200439 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100440 }
441 }
442
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200443 printf_dbg("End of file\n");
Piotr Nowicki14d31052020-03-16 14:05:22 +0100444 return 0;
445}
446
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200447# if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100448/*
449 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100450 * about the certificates from provided data.
451 *
452 * /p ssl pointer to serialized certificate
453 * /p len number of bytes in the buffer
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200454 */
455void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100456{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200457 enum
458 {
459 STRLEN = 4096
460 };
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100461 mbedtls_x509_crt crt;
462 int ret;
463 char str[STRLEN];
464
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200465 printf("\nCertificate:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100466
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200467 mbedtls_x509_crt_init(&crt);
468 ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
469 if (0 != ret) {
470 mbedtls_strerror(ret, str, STRLEN);
471 printf_err("Invalid format of X.509 - %s\n", str);
472 printf("Cannot deserialize:\n\t");
473 print_hex(ssl, len, 25, "\t");
474 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100475 mbedtls_x509_crt *current = &crt;
476
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200477 while (current != NULL) {
478 ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
479 if (0 > ret) {
480 mbedtls_strerror(ret, str, STRLEN);
481 printf_err("Cannot write to the output - %s\n", str);
482 } else {
483 printf("%s", str);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100484 }
485
486 current = current->next;
487
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200488 if (current) {
489 printf("\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100490 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100491 }
492 }
493
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200494 mbedtls_x509_crt_free(&crt);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100495}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200496# endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100497
498/*
499 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100500 * about the session from provided data. This function was built based on
501 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
502 * due to dependencies on the mbedTLS configuration.
503 *
504 * The data structure in the buffer:
505 * uint64 start_time;
506 * uint8 ciphersuite[2]; // defined by the standard
507 * uint8 compression; // 0 or 1
508 * uint8 session_id_len; // at most 32
509 * opaque session_id[32];
510 * opaque master[48]; // fixed length in the standard
511 * uint32 verify_result;
512 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
513 * opaque ticket<0..2^24-1>; // length 0 means no ticket
514 * uint32 ticket_lifetime;
515 * uint8 mfl_code; // up to 255 according to standard
516 * uint8 trunc_hmac; // 0 or 1
517 * uint8 encrypt_then_mac; // 0 or 1
518 *
519 * /p ssl pointer to serialized session
520 * /p len number of bytes in the buffer
521 * /p session_cfg_flag session configuration flags
522 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200523void print_deserialized_ssl_session(const uint8_t *ssl,
524 uint32_t len,
525 int session_cfg_flag)
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100526{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200527 const struct mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100528 int ciphersuite_id;
529 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100530 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100531 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100532
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200533 printf("\nSession info:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100534
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200535 if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100536 uint64_t start;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200537 CHECK_SSL_END(8);
538 start = ((uint64_t)ssl[0] << 56) | ((uint64_t)ssl[1] << 48) |
539 ((uint64_t)ssl[2] << 40) | ((uint64_t)ssl[3] << 32) |
540 ((uint64_t)ssl[4] << 24) | ((uint64_t)ssl[5] << 16) |
541 ((uint64_t)ssl[6] << 8) | ((uint64_t)ssl[7]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100542 ssl += 8;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200543 printf("\tstart time : ");
544 print_time((time_t *)&start);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100545 }
546
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200547 CHECK_SSL_END(2);
548 ciphersuite_id = ((int)ssl[0] << 8) | (int)ssl[1];
549 printf_dbg("Ciphersuite ID: %d\n", ciphersuite_id);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100550 ssl += 2;
551
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200552 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
553 if (ciphersuite_info == NULL) {
554 printf_err("Cannot find ciphersuite info\n");
555 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100556 const mbedtls_cipher_info_t *cipher_info;
557 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100558
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200559 printf("\tciphersuite : %s\n", ciphersuite_info->name);
560 printf("\tcipher flags : 0x%02X\n", ciphersuite_info->flags);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100561
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200562 cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
563 if (cipher_info == NULL) {
564 printf_err("Cannot find cipher info\n");
565 } else {
566 printf("\tcipher : %s\n", cipher_info->name);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100567 }
568
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200569 md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
570 if (md_info == NULL) {
571 printf_err("Cannot find Message-Digest info\n");
572 } else {
573 printf("\tMessage-Digest : %s\n", mbedtls_md_get_name(md_info));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100574 }
575 }
576
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200577 CHECK_SSL_END(1);
578 printf("\tcompression : %s\n", get_enabled_str(*ssl++));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100579
580 /* Note - Here we can get session ID length from serialized data, but we
581 * use hardcoded 32-bytes length. This approach was taken from
582 * 'mbedtls_ssl_session_load()'. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200583 CHECK_SSL_END(1 + 32);
584 printf_dbg("Session id length: %u\n", (uint32_t)*ssl++);
585 printf("\tsession ID : ");
586 print_hex(ssl, 32, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100587 ssl += 32;
588
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200589 printf("\tmaster secret : ");
590 CHECK_SSL_END(48);
591 print_hex(ssl, 48, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100592 ssl += 48;
593
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200594 CHECK_SSL_END(4);
595 verify_result = ((uint32_t)ssl[0] << 24) | ((uint32_t)ssl[1] << 16) |
596 ((uint32_t)ssl[2] << 8) | ((uint32_t)ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100597 ssl += 4;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200598 printf("\tverify result : 0x%08X\n", verify_result);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100599
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200600 if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
601 if (conf_keep_peer_certificate) {
602 CHECK_SSL_END(3);
603 cert_len = ((uint32_t)ssl[0] << 16) | ((uint32_t)ssl[1] << 8) |
604 ((uint32_t)ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100605 ssl += 3;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200606 printf_dbg("Certificate length: %u\n", cert_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200608 if (cert_len > 0) {
609 CHECK_SSL_END(cert_len);
610# if !defined(MBEDTLS_X509_REMOVE_INFO)
611 print_deserialized_ssl_cert(ssl, cert_len);
612# endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100613 ssl += cert_len;
614 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200615 } else {
616 printf("\tPeer digest : ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100617
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200618 CHECK_SSL_END(1);
619 switch ((mbedtls_md_type_t)*ssl++) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100620 case MBEDTLS_MD_NONE:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200621 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100622 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100623 case MBEDTLS_MD_MD5:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200624 printf("MD5\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100625 break;
626 case MBEDTLS_MD_SHA1:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200627 printf("SHA1\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100628 break;
629 case MBEDTLS_MD_SHA224:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200630 printf("SHA224\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100631 break;
632 case MBEDTLS_MD_SHA256:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200633 printf("SHA256\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100634 break;
635 case MBEDTLS_MD_SHA384:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200636 printf("SHA384\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100637 break;
638 case MBEDTLS_MD_SHA512:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200639 printf("SHA512\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100640 break;
641 case MBEDTLS_MD_RIPEMD160:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200642 printf("RIPEMD160\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100643 break;
644 default:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200645 printf("undefined or erroneous\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100646 break;
647 }
648
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200649 CHECK_SSL_END(1);
650 cert_len = (uint32_t)*ssl++;
651 printf_dbg("Message-Digest length: %u\n", cert_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100652
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200653 if (cert_len > 0) {
654 printf("\tPeer digest cert : ");
655 CHECK_SSL_END(cert_len);
656 print_hex(ssl, cert_len, 16, "\t ");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100657 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100658 }
659 }
660 }
661
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200662 if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
663 printf("\nTicket:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100664
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200665 CHECK_SSL_END(3);
666 ticket_len = ((uint32_t)ssl[0] << 16) | ((uint32_t)ssl[1] << 8) |
667 ((uint32_t)ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100668 ssl += 3;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200669 printf_dbg("Ticket length: %u\n", ticket_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100670
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200671 if (ticket_len > 0) {
672 printf("\t");
673 CHECK_SSL_END(ticket_len);
674 print_hex(ssl, ticket_len, 22, "\t");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100675 ssl += ticket_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200676 printf("\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100677 }
678
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200679 CHECK_SSL_END(4);
680 ticket_lifetime = ((uint32_t)ssl[0] << 24) | ((uint32_t)ssl[1] << 16) |
681 ((uint32_t)ssl[2] << 8) | ((uint32_t)ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100682 ssl += 4;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200683 printf("\tlifetime : %u sec.\n", ticket_lifetime);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100684 }
685
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200686 if (ssl < end) {
687 printf("\nSession others:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100688 }
689
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200690 if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
691 CHECK_SSL_END(1);
692 printf("\tMFL : %s\n", get_mfl_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100693 }
694
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200695 if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
696 CHECK_SSL_END(1);
697 printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100698 }
699
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200700 if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
701 CHECK_SSL_END(1);
702 printf("\tEncrypt-then-MAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100703 }
704
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200705 if (0 != (end - ssl)) {
706 printf_err("%i bytes left to analyze from session\n",
707 (int32_t)(end - ssl));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100708 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100709}
710
711/*
712 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100713 * about the context from provided data. This function was built based on
714 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
715 * due to dependencies on the mbedTLS configuration and the configuration of
716 * the context when serialization was created.
717 *
718 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200719 * // header
720 * uint8 version[3];
721 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100722 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200723 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100724 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
725 * // transform sub-structure
726 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200727 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100728 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200729 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100730 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
731 * // fields from ssl_context
732 * uint32 badmac_seen; // DTLS: number of records with failing MAC
733 * uint64 in_window_top; // DTLS: last validated record seq_num
734 * uint64 in_window; // DTLS: bitmask for replay protection
735 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
736 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
737 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200738 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100739 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
740 *
741 * /p ssl pointer to serialized session
742 * /p len number of bytes in the buffer
743 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200744void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100745{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100746 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100747 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100748 int session_cfg_flag;
749 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100750
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200751 printf("\nMbed TLS version:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100752
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200753 CHECK_SSL_END(3 + 2 + 3);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100754
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200755 printf("\tmajor %u\n", (uint32_t)*ssl++);
756 printf("\tminor %u\n", (uint32_t)*ssl++);
757 printf("\tpath %u\n", (uint32_t)*ssl++);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100758
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200759 printf("\nEnabled session and context configuration:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100760
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200761 session_cfg_flag = ((int)ssl[0] << 8) | ((int)ssl[1]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100762 ssl += 2;
763
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200764 context_cfg_flag = ((int)ssl[0] << 16) | ((int)ssl[1] << 8) | ((int)ssl[2]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100765 ssl += 3;
766
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200767 printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
768 printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100769
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200770 print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT,
771 session_cfg_flag);
772 print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT,
773 session_cfg_flag);
774 print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT,
775 session_cfg_flag);
776 print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT,
777 session_cfg_flag);
778 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT,
779 session_cfg_flag);
780 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
781 SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100782
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200783 print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
784 CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag);
785 print_if_bit("MBEDTLS_SSL_DTLS_ANTI_REPLAY",
786 CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag);
787 print_if_bit("MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100788
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200789 CHECK_SSL_END(4);
790 session_len = ((uint32_t)ssl[0] << 24) | ((uint32_t)ssl[1] << 16) |
791 ((uint32_t)ssl[2] << 8) | ((uint32_t)ssl[3]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100792 ssl += 4;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200793 printf_dbg("Session length %u\n", session_len);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100794
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200795 CHECK_SSL_END(session_len);
796 print_deserialized_ssl_session(ssl, session_len, session_cfg_flag);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100797 ssl += session_len;
798
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200799 printf("\nRandom bytes:\n\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100800
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200801 CHECK_SSL_END(TRANSFORM_RANDBYTE_LEN);
802 print_hex(ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100803 ssl += TRANSFORM_RANDBYTE_LEN;
804
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200805 printf("\nContext others:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100806
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200807 if (CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag) {
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100808 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100809
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200810 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100811 cid_len = *ssl++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200812 printf_dbg("In CID length %u\n", (uint32_t)cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100813
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200814 printf("\tin CID : ");
815 if (cid_len > 0) {
816 CHECK_SSL_END(cid_len);
817 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100818 ssl += cid_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200819 } else {
820 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100821 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100822
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200823 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100824 cid_len = *ssl++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200825 printf_dbg("Out CID length %u\n", (uint32_t)cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100826
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200827 printf("\tout CID : ");
828 if (cid_len > 0) {
829 CHECK_SSL_END(cid_len);
830 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100831 ssl += cid_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200832 } else {
833 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100834 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100835 }
836
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200837 if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100838 uint32_t badmac_seen;
839
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200840 CHECK_SSL_END(4);
841 badmac_seen = ((uint32_t)ssl[0] << 24) | ((uint32_t)ssl[1] << 16) |
842 ((uint32_t)ssl[2] << 8) | ((uint32_t)ssl[3]);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100843 ssl += 4;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200844 printf("\tbad MAC seen number : %u\n", badmac_seen);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100845
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100846 /* value 'in_window_top' from mbedtls_ssl_context */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200847 printf("\tlast validated record sequence no. : ");
848 CHECK_SSL_END(8);
849 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100850 ssl += 8;
851
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100852 /* value 'in_window' from mbedtls_ssl_context */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200853 printf("\tbitmask for replay detection : ");
854 CHECK_SSL_END(8);
855 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100856 ssl += 8;
857 }
858
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200859 if (conf_dtls_proto) {
860 CHECK_SSL_END(1);
861 printf("\tDTLS datagram packing : %s\n",
862 get_enabled_str(!(*ssl++)));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100863 }
864
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100865 /* value 'cur_out_ctr' from mbedtls_ssl_context */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200866 printf("\toutgoing record sequence no. : ");
867 CHECK_SSL_END(8);
868 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100869 ssl += 8;
870
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200871 if (conf_dtls_proto) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100872 uint16_t mtu;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200873 CHECK_SSL_END(2);
874 mtu = (ssl[0] << 8) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100875 ssl += 2;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200876 printf("\tMTU : %u\n", mtu);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100877 }
878
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200879 if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100880 uint8_t alpn_len;
881
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200882 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100883 alpn_len = *ssl++;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200884 printf_dbg("ALPN length %u\n", (uint32_t)alpn_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100885
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200886 printf("\tALPN negotiation : ");
887 CHECK_SSL_END(alpn_len);
888 if (alpn_len > 0) {
889 if (strlen((const char *)ssl) == alpn_len) {
890 printf("%s\n", ssl);
891 } else {
892 printf("\n");
893 printf_err("\tALPN negotiation is incorrect\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100894 }
895 ssl += alpn_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200896 } else {
897 printf("not selected\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898 }
899 }
900
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200901 if (0 != (end - ssl)) {
902 printf_err("%i bytes left to analyze from context\n",
903 (int32_t)(end - ssl));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100904 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200905 printf("\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100906}
907
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200908int main(int argc, char *argv[])
Piotr Nowicki9370f902020-03-13 14:43:22 +0100909{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200910 enum
911 {
912 SSL_INIT_LEN = 4096
913 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100914
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100915 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200916 uint8_t *b64_buf = NULL;
917 uint8_t *ssl_buf = NULL;
918 size_t b64_max_len = SSL_INIT_LEN;
919 size_t ssl_max_len = SSL_INIT_LEN;
920 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100921
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200922 /* The 'b64_file' is opened when parsing arguments to check that the
923 * file name is correct */
924 parse_arguments(argc, argv);
Piotr Nowicki9370f902020-03-13 14:43:22 +0100925
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200926 if (NULL != b64_file) {
927 b64_buf = malloc(SSL_INIT_LEN);
928 ssl_buf = malloc(SSL_INIT_LEN);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200929
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200930 if (NULL == b64_buf || NULL == ssl_buf) {
931 printf_err(alloc_err);
932 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200933 b64_file = NULL;
934 }
935 }
936
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200937 while (NULL != b64_file) {
938 size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
939 if (b64_len > 0) {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100940 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200941 size_t ssl_required_len = b64_len * 3 / 4 + 1;
942
943 /* Allocate more memory if necessary. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200944 if (ssl_required_len > ssl_max_len) {
945 void *ptr = realloc(ssl_buf, ssl_required_len);
946 if (NULL == ptr) {
947 printf_err(alloc_err);
948 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200949 b64_file = NULL;
950 break;
951 }
952 ssl_buf = ptr;
953 ssl_max_len = ssl_required_len;
954 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100955
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200956 printf("\nDeserializing number %u:\n", ++b64_counter);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100957
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200958 printf("\nBase64 code:\n");
959 print_b64(b64_buf, b64_len);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100960
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200961 ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf,
962 b64_len);
963 if (ret != 0) {
964 mbedtls_strerror(ret, (char *)b64_buf, b64_max_len);
965 printf_err("base64 code cannot be decoded - %s\n", b64_buf);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100966 continue;
967 }
968
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200969 if (debug) {
970 printf("\nDecoded data in hex:\n\t");
971 print_hex(ssl_buf, ssl_len, 25, "\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100972 }
Piotr Nowicki14d31052020-03-16 14:05:22 +0100973
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200974 print_deserialized_ssl_context(ssl_buf, ssl_len);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100975
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200976 } else {
977 fclose(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100978 b64_file = NULL;
979 }
980 }
981
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200982 free(b64_buf);
983 free(ssl_buf);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200984
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200985 if (b64_counter > 0) {
986 printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
987 } else {
988 printf("Finished. No valid base64 code found\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200989 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100990
Piotr Nowicki9370f902020-03-13 14:43:22 +0100991 return 0;
992}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200993
994#endif /* MBEDTLS_X509_CRT_PARSE_C */