blob: a8b2b470e0b94d55232e637fbc1938679e26fe34 [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
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020020#if !defined(MBEDTLS_CONFIG_FILE)
21#include "mbedtls/config.h"
22#else
23#include MBEDTLS_CONFIG_FILE
Piotr Nowickif86192f2020-03-26 11:45:42 +010024#endif
Paul Elliott8f20bab2021-12-09 14:48:47 +000025#include "mbedtls/debug.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010026
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010027#include <stdio.h>
28#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020029
Gilles Peskinef4a6a052020-11-09 14:55:35 +010030#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
31 !defined(MBEDTLS_SSL_TLS_C)
David Horstmannceeaeb92023-01-05 15:44:23 +000032int main(void)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020033{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010034 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
35 "MBEDTLS_SSL_TLS_C not defined.\n");
David Horstmannceeaeb92023-01-05 15:44:23 +000036 return 0;
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020037}
38#else
39
40#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
41#define _CRT_SECURE_NO_DEPRECATE 1
42#endif
43
Piotr Nowicki14d31052020-03-16 14:05:22 +010044#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010045#include <stdarg.h>
46#include <string.h>
Raoul Strackx2db000f2020-06-22 14:08:57 +020047#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010048#include <time.h>
Raoul Strackx2db000f2020-06-22 14:08:57 +020049#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010050#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010051#include "mbedtls/error.h"
52#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010053#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010054#include "mbedtls/md_internal.h"
55#include "mbedtls/x509_crt.h"
56#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010057
58/*
59 * This program version
60 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010061#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010062#define VER_MAJOR 0
63#define VER_MINOR 1
64
65/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020066 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010067 */
David Horstmannceeaeb92023-01-05 15:44:23 +000068#define SESSION_CONFIG_TIME_BIT (1 << 0)
69#define SESSION_CONFIG_CRT_BIT (1 << 1)
70#define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
71#define SESSION_CONFIG_MFL_BIT (1 << 3)
72#define SESSION_CONFIG_TRUNC_HMAC_BIT (1 << 4)
73#define SESSION_CONFIG_ETM_BIT (1 << 5)
74#define SESSION_CONFIG_TICKET_BIT (1 << 6)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010075
David Horstmannceeaeb92023-01-05 15:44:23 +000076#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT (1 << 0)
77#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT (1 << 1)
78#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT (1 << 2)
79#define CONTEXT_CONFIG_ALPN_BIT (1 << 3)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010080
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010081#define TRANSFORM_RANDBYTE_LEN 64
82
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010083/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020084 * Minimum and maximum number of bytes for specific data: context, sessions,
85 * certificates, tickets and buffers in the program. The context and session
86 * size values have been calculated based on the 'print_deserialized_ssl_context()'
87 * and 'print_deserialized_ssl_session()' content.
88 */
89#define MIN_CONTEXT_LEN 84
90#define MIN_SESSION_LEN 88
91
92#define MAX_CONTEXT_LEN 875 /* without session data */
93#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
David Horstmannceeaeb92023-01-05 15:44:23 +000094#define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
95#define MAX_TICKET_LEN ((1 << 24) - 1)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020096
David Horstmannceeaeb92023-01-05 15:44:23 +000097#define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
98#define MAX_SERIALIZED_DATA (MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
99 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200100
David Horstmannceeaeb92023-01-05 15:44:23 +0000101#define MIN_BASE64_LEN (MIN_SERIALIZED_DATA * 4 / 3)
102#define MAX_BASE64_LEN (MAX_SERIALIZED_DATA * 4 / 3 + 3)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200103
104/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100105 * A macro that prevents from reading out of the ssl buffer range.
106 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000107#define CHECK_SSL_END(LEN) \
108 do \
109 { \
110 if (end - ssl < (int) (LEN)) \
111 { \
112 printf_err("%s", buf_ln_err); \
113 return; \
114 } \
115 } while (0)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100116
117/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100118 * Global values
119 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100120FILE *b64_file = NULL; /* file with base64 codes to deserialize */
121char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
122char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
123char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200124const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100125const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100126
127/*
128 * Basic printing functions
129 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000130void print_version()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100131{
David Horstmannceeaeb92023-01-05 15:44:23 +0000132 printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100133}
134
David Horstmannceeaeb92023-01-05 15:44:23 +0000135void print_usage()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100136{
137 print_version();
David Horstmannceeaeb92023-01-05 15:44:23 +0000138 printf("\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
139 "in the text file. The program can deserialize many codes from one file, but they must be\n"
140 "separated, e.g. by a newline.\n\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100141 printf(
142 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100143 "\t-f path - Path to the file with base64 code\n"
144 "\t-v - Show version\n"
145 "\t-h - Show this usage\n"
146 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200147 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100148 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
149 "\t flag. You can also use it if there are some problems with reading\n"
150 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200151 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100152 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100153 "\n"
David Horstmannceeaeb92023-01-05 15:44:23 +0000154 );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100155}
156
David Horstmannceeaeb92023-01-05 15:44:23 +0000157void printf_dbg(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100158{
David Horstmannceeaeb92023-01-05 15:44:23 +0000159 if (debug) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100160 va_list args;
David Horstmannceeaeb92023-01-05 15:44:23 +0000161 va_start(args, str);
162 printf("debug: ");
163 vprintf(str, args);
164 fflush(stdout);
165 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100166 }
167}
168
David Horstmannceeaeb92023-01-05 15:44:23 +0000169MBEDTLS_PRINTF_ATTRIBUTE(1, 2)
170void printf_err(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100171{
172 va_list args;
David Horstmannceeaeb92023-01-05 15:44:23 +0000173 va_start(args, str);
174 fflush(stdout);
175 fprintf(stderr, "ERROR: ");
176 vfprintf(stderr, str, args);
177 fflush(stderr);
178 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100179}
180
181/*
182 * Exit from the program in case of error
183 */
184void error_exit()
185{
David Horstmannceeaeb92023-01-05 15:44:23 +0000186 if (NULL != b64_file) {
187 fclose(b64_file);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100188 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000189 exit(-1);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100190}
191
192/*
193 * This function takes the input arguments of this program
194 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000195void parse_arguments(int argc, char *argv[])
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100196{
197 int i = 1;
198
David Horstmannceeaeb92023-01-05 15:44:23 +0000199 if (argc < 2) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100200 print_usage();
201 error_exit();
202 }
203
David Horstmannceeaeb92023-01-05 15:44:23 +0000204 while (i < argc) {
205 if (strcmp(argv[i], "-d") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100206 debug = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000207 } else if (strcmp(argv[i], "-h") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100208 print_usage();
David Horstmannceeaeb92023-01-05 15:44:23 +0000209 } else if (strcmp(argv[i], "-v") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100210 print_version();
David Horstmannceeaeb92023-01-05 15:44:23 +0000211 } else if (strcmp(argv[i], "-f") == 0) {
212 if (++i >= argc) {
213 printf_err("File path is empty\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100214 error_exit();
215 }
216
David Horstmannceeaeb92023-01-05 15:44:23 +0000217 if (NULL != b64_file) {
218 printf_err("Cannot specify more than one file with -f\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100219 error_exit();
220 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000221
222 if ((b64_file = fopen(argv[i], "r")) == NULL) {
223 printf_err("Cannot find file \"%s\"\n", argv[i]);
224 error_exit();
225 }
226 } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100227 conf_keep_peer_certificate = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000228 } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100229 conf_dtls_proto = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000230 } else {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100231 print_usage();
232 error_exit();
233 }
234
235 i++;
236 }
237}
238
Piotr Nowicki14d31052020-03-16 14:05:22 +0100239/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100240 * This function prints base64 code to the stdout
241 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000242void print_b64(const uint8_t *b, size_t len)
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100243{
244 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100245 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100246 printf("\t");
David Horstmannceeaeb92023-01-05 15:44:23 +0000247 while (b < end) {
248 if (++i > 75) {
249 printf("\n\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100250 i = 0;
251 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000252 printf("%c", *b++);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100253 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000254 printf("\n");
255 fflush(stdout);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100256}
257
258/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100259 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100260 *
261 * /p b buffer with data to print
262 * /p len number of bytes to print
263 * /p in_line number of bytes in one line
264 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100265 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000266void print_hex(const uint8_t *b, size_t len,
267 const size_t in_line, const char *prefix)
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100268{
269 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100270 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100271
David Horstmannceeaeb92023-01-05 15:44:23 +0000272 if (prefix == NULL) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100273 prefix = "";
274 }
275
David Horstmannceeaeb92023-01-05 15:44:23 +0000276 while (b < end) {
277 if (++i > in_line) {
278 printf("\n%s", prefix);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100279 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100280 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000281 printf("%02X ", (uint8_t) *b++);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100282 }
283 printf("\n");
284 fflush(stdout);
285}
286
287/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100288 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
289 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000290void print_time(const uint64_t *time)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100291{
Andrzej Kurek478181d2022-02-28 05:51:57 -0500292#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100293 char buf[20];
David Horstmannceeaeb92023-01-05 15:44:23 +0000294 struct tm *t = gmtime((time_t *) time);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100295 static const char format[] = "%Y-%m-%d %H:%M:%S";
David Horstmannceeaeb92023-01-05 15:44:23 +0000296 if (NULL != t) {
297 strftime(buf, sizeof(buf), format, t);
298 printf("%s\n", buf);
299 } else {
300 printf("unknown\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100301 }
Andrzej Kurek478181d2022-02-28 05:51:57 -0500302#else
303 (void) time;
David Horstmannceeaeb92023-01-05 15:44:23 +0000304 printf("not supported\n");
Raoul Strackx2db000f2020-06-22 14:08:57 +0200305#endif
Andrzej Kurek478181d2022-02-28 05:51:57 -0500306}
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100307
308/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100309 * Print the input string if the bit is set in the value
310 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000311void print_if_bit(const char *str, int bit, int val)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100312{
David Horstmannceeaeb92023-01-05 15:44:23 +0000313 if (bit & val) {
314 printf("\t%s\n", str);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100315 }
316}
317
318/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100319 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
320 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000321const char *get_enabled_str(int is_en)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100322{
David Horstmannceeaeb92023-01-05 15:44:23 +0000323 return (is_en) ? "enabled" : "disabled";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100324}
325
326/*
327 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
328 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000329const char *get_mfl_str(int mfl_code)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100330{
David Horstmannceeaeb92023-01-05 15:44:23 +0000331 switch (mfl_code) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100332 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
333 return "none";
334 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
335 return "512";
336 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
337 return "1024";
338 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
339 return "2048";
340 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
341 return "4096";
342 default:
343 return "error";
344 }
345}
346
347/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100348 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
349 * previously. After each call to this function, the internal file position
350 * indicator of the global b64_file is advanced.
351 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200352 * Note - This function checks the size of the input buffer and if necessary,
353 * increases it to the maximum MAX_BASE64_LEN
354 *
355 * /p b64 pointer to the pointer of the buffer for input data
356 * /p max_len pointer to the current buffer capacity. It can be changed if
357 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100358 *
359 * \retval number of bytes written in to the b64 buffer or 0 in case no more
360 * data was found
361 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000362size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
Piotr Nowicki14d31052020-03-16 14:05:22 +0100363{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200364 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100365 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100366 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000367 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100368
David Horstmannceeaeb92023-01-05 15:44:23 +0000369 while (EOF != c) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100370 char c_valid = 0;
371
David Horstmannceeaeb92023-01-05 15:44:23 +0000372 c = fgetc(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100373
David Horstmannceeaeb92023-01-05 15:44:23 +0000374 if (pad > 0) {
375 if (c == '=' && pad == 1) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100376 c_valid = 1;
377 pad = 2;
378 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000379 } else if ((c >= 'A' && c <= 'Z') ||
380 (c >= 'a' && c <= 'z') ||
381 (c >= '0' && c <= '9') ||
382 c == '+' || c == '/') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100383 c_valid = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000384 } else if (c == '=') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100385 c_valid = 1;
386 pad = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000387 } else if (c == '-') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100388 c = '+';
389 c_valid = 1;
David Horstmannceeaeb92023-01-05 15:44:23 +0000390 } else if (c == '_') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100391 c = '/';
392 c_valid = 1;
393 }
394
David Horstmannceeaeb92023-01-05 15:44:23 +0000395 if (c_valid) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200396 /* A string of characters that could be a base64 code. */
397 valid_balance++;
398
David Horstmannceeaeb92023-01-05 15:44:23 +0000399 if (len < *max_len) {
400 (*b64)[len++] = c;
401 } else if (*max_len < MAX_BASE64_LEN) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200402 /* Current buffer is too small, but can be resized. */
403 void *ptr;
David Horstmannceeaeb92023-01-05 15:44:23 +0000404 size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200405 *max_len + 4096 : MAX_BASE64_LEN;
406
David Horstmannceeaeb92023-01-05 15:44:23 +0000407 ptr = realloc(*b64, new_size);
408 if (NULL == ptr) {
409 printf_err(alloc_err);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200410 return 0;
411 }
412 *b64 = ptr;
413 *max_len = new_size;
David Horstmannceeaeb92023-01-05 15:44:23 +0000414 (*b64)[len++] = c;
415 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200416 /* Too much data so it will be treated as invalid */
417 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100418 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000419 } else if (len > 0) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200420 /* End of a string that could be a base64 code, but need to check
421 * that the length of the characters is correct. */
422
423 valid_balance--;
424
David Horstmannceeaeb92023-01-05 15:44:23 +0000425 if (len < MIN_CONTEXT_LEN) {
426 printf_dbg("The code found is too small to be a SSL context.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200427 len = pad = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000428 } else if (len > *max_len) {
429 printf_err("The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
430 len - *max_len);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200431 len = pad = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000432 } else if (len % 4 != 0) {
433 printf_err("The length of the base64 code found should be a multiple of 4.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200434 len = pad = 0;
David Horstmannceeaeb92023-01-05 15:44:23 +0000435 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200436 /* Base64 code with valid character length. */
437 return len;
438 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000439 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200440 valid_balance--;
441 }
442
443 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000444 if (valid_balance < -100) {
445 printf_err("Too many bad symbols detected. File check aborted.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200446 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100447 }
448 }
449
David Horstmannceeaeb92023-01-05 15:44:23 +0000450 printf_dbg("End of file\n");
Piotr Nowicki14d31052020-03-16 14:05:22 +0100451 return 0;
452}
453
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100454/*
455 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100456 * about the certificates from provided data.
457 *
458 * /p ssl pointer to serialized certificate
459 * /p len number of bytes in the buffer
David Horstmannceeaeb92023-01-05 15:44:23 +0000460 */
461void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100462{
463 enum { STRLEN = 4096 };
464 mbedtls_x509_crt crt;
465 int ret;
466 char str[STRLEN];
467
David Horstmannceeaeb92023-01-05 15:44:23 +0000468 printf("\nCertificate:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100469
David Horstmannceeaeb92023-01-05 15:44:23 +0000470 mbedtls_x509_crt_init(&crt);
471 ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
472 if (0 != ret) {
473 mbedtls_strerror(ret, str, STRLEN);
474 printf_err("Invalid format of X.509 - %s\n", str);
475 printf("Cannot deserialize:\n\t");
476 print_hex(ssl, len, 25, "\t");
477 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100478 mbedtls_x509_crt *current = &crt;
479
David Horstmannceeaeb92023-01-05 15:44:23 +0000480 while (current != NULL) {
481 ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
482 if (0 > ret) {
483 mbedtls_strerror(ret, str, STRLEN);
484 printf_err("Cannot write to the output - %s\n", str);
485 } else {
486 printf("%s", str);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100487 }
488
489 current = current->next;
490
David Horstmannceeaeb92023-01-05 15:44:23 +0000491 if (current) {
492 printf("\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100493 }
494
495 }
496 }
497
David Horstmannceeaeb92023-01-05 15:44:23 +0000498 mbedtls_x509_crt_free(&crt);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100499}
500
501/*
502 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100503 * about the session from provided data. This function was built based on
504 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
505 * due to dependencies on the mbedTLS configuration.
506 *
507 * The data structure in the buffer:
508 * uint64 start_time;
509 * uint8 ciphersuite[2]; // defined by the standard
510 * uint8 compression; // 0 or 1
511 * uint8 session_id_len; // at most 32
512 * opaque session_id[32];
513 * opaque master[48]; // fixed length in the standard
514 * uint32 verify_result;
515 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
516 * opaque ticket<0..2^24-1>; // length 0 means no ticket
517 * uint32 ticket_lifetime;
518 * uint8 mfl_code; // up to 255 according to standard
519 * uint8 trunc_hmac; // 0 or 1
520 * uint8 encrypt_then_mac; // 0 or 1
521 *
522 * /p ssl pointer to serialized session
523 * /p len number of bytes in the buffer
524 * /p session_cfg_flag session configuration flags
525 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000526void print_deserialized_ssl_session(const uint8_t *ssl, uint32_t len,
527 int session_cfg_flag)
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100528{
David Horstmannceeaeb92023-01-05 15:44:23 +0000529 const struct mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100530 int ciphersuite_id;
531 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100532 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100533 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100534
David Horstmannceeaeb92023-01-05 15:44:23 +0000535 printf("\nSession info:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100536
David Horstmannceeaeb92023-01-05 15:44:23 +0000537 if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100538 uint64_t start;
David Horstmannceeaeb92023-01-05 15:44:23 +0000539 CHECK_SSL_END(8);
540 start = ((uint64_t) ssl[0] << 56) |
541 ((uint64_t) ssl[1] << 48) |
542 ((uint64_t) ssl[2] << 40) |
543 ((uint64_t) ssl[3] << 32) |
544 ((uint64_t) ssl[4] << 24) |
545 ((uint64_t) ssl[5] << 16) |
546 ((uint64_t) ssl[6] << 8) |
547 ((uint64_t) ssl[7]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100548 ssl += 8;
David Horstmannceeaeb92023-01-05 15:44:23 +0000549 printf("\tstart time : ");
550 print_time(&start);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100551 }
552
David Horstmannceeaeb92023-01-05 15:44:23 +0000553 CHECK_SSL_END(2);
554 ciphersuite_id = ((int) ssl[0] << 8) | (int) ssl[1];
555 printf_dbg("Ciphersuite ID: %d\n", ciphersuite_id);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100556 ssl += 2;
557
David Horstmannceeaeb92023-01-05 15:44:23 +0000558 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
559 if (ciphersuite_info == NULL) {
560 printf_err("Cannot find ciphersuite info\n");
561 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100562 const mbedtls_cipher_info_t *cipher_info;
563 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100564
David Horstmannceeaeb92023-01-05 15:44:23 +0000565 printf("\tciphersuite : %s\n", ciphersuite_info->name);
566 printf("\tcipher flags : 0x%02X\n", ciphersuite_info->flags);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100567
David Horstmannceeaeb92023-01-05 15:44:23 +0000568 cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
569 if (cipher_info == NULL) {
570 printf_err("Cannot find cipher info\n");
571 } else {
572 printf("\tcipher : %s\n", cipher_info->name);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100573 }
574
David Horstmannceeaeb92023-01-05 15:44:23 +0000575 md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
576 if (md_info == NULL) {
577 printf_err("Cannot find Message-Digest info\n");
578 } else {
579 printf("\tMessage-Digest : %s\n", md_info->name);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100580 }
581 }
582
David Horstmannceeaeb92023-01-05 15:44:23 +0000583 CHECK_SSL_END(1);
584 printf("\tcompression : %s\n", get_enabled_str(*ssl++));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100585
586 /* Note - Here we can get session ID length from serialized data, but we
587 * use hardcoded 32-bytes length. This approach was taken from
588 * 'mbedtls_ssl_session_load()'. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000589 CHECK_SSL_END(1 + 32);
590 printf_dbg("Session id length: %u\n", (uint32_t) *ssl++);
591 printf("\tsession ID : ");
592 print_hex(ssl, 32, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100593 ssl += 32;
594
David Horstmannceeaeb92023-01-05 15:44:23 +0000595 printf("\tmaster secret : ");
596 CHECK_SSL_END(48);
597 print_hex(ssl, 48, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100598 ssl += 48;
599
David Horstmannceeaeb92023-01-05 15:44:23 +0000600 CHECK_SSL_END(4);
601 verify_result = ((uint32_t) ssl[0] << 24) |
602 ((uint32_t) ssl[1] << 16) |
603 ((uint32_t) ssl[2] << 8) |
604 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100605 ssl += 4;
David Horstmannceeaeb92023-01-05 15:44:23 +0000606 printf("\tverify result : 0x%08X\n", verify_result);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607
David Horstmannceeaeb92023-01-05 15:44:23 +0000608 if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
609 if (conf_keep_peer_certificate) {
610 CHECK_SSL_END(3);
611 cert_len = ((uint32_t) ssl[0] << 16) |
612 ((uint32_t) ssl[1] << 8) |
613 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100614 ssl += 3;
David Horstmannceeaeb92023-01-05 15:44:23 +0000615 printf_dbg("Certificate length: %u\n", cert_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100616
David Horstmannceeaeb92023-01-05 15:44:23 +0000617 if (cert_len > 0) {
618 CHECK_SSL_END(cert_len);
619 print_deserialized_ssl_cert(ssl, cert_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100620 ssl += cert_len;
621 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000622 } else {
623 printf("\tPeer digest : ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100624
David Horstmannceeaeb92023-01-05 15:44:23 +0000625 CHECK_SSL_END(1);
626 switch ((mbedtls_md_type_t) *ssl++) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100627 case MBEDTLS_MD_NONE:
David Horstmannceeaeb92023-01-05 15:44:23 +0000628 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100629 break;
630 case MBEDTLS_MD_MD2:
David Horstmannceeaeb92023-01-05 15:44:23 +0000631 printf("MD2\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100632 break;
633 case MBEDTLS_MD_MD4:
David Horstmannceeaeb92023-01-05 15:44:23 +0000634 printf("MD4\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100635 break;
636 case MBEDTLS_MD_MD5:
David Horstmannceeaeb92023-01-05 15:44:23 +0000637 printf("MD5\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100638 break;
639 case MBEDTLS_MD_SHA1:
David Horstmannceeaeb92023-01-05 15:44:23 +0000640 printf("SHA1\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100641 break;
642 case MBEDTLS_MD_SHA224:
David Horstmannceeaeb92023-01-05 15:44:23 +0000643 printf("SHA224\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100644 break;
645 case MBEDTLS_MD_SHA256:
David Horstmannceeaeb92023-01-05 15:44:23 +0000646 printf("SHA256\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100647 break;
648 case MBEDTLS_MD_SHA384:
David Horstmannceeaeb92023-01-05 15:44:23 +0000649 printf("SHA384\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100650 break;
651 case MBEDTLS_MD_SHA512:
David Horstmannceeaeb92023-01-05 15:44:23 +0000652 printf("SHA512\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100653 break;
654 case MBEDTLS_MD_RIPEMD160:
David Horstmannceeaeb92023-01-05 15:44:23 +0000655 printf("RIPEMD160\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100656 break;
657 default:
David Horstmannceeaeb92023-01-05 15:44:23 +0000658 printf("undefined or erroneous\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100659 break;
660 }
661
David Horstmannceeaeb92023-01-05 15:44:23 +0000662 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100663 cert_len = (uint32_t) *ssl++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000664 printf_dbg("Message-Digest length: %u\n", cert_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100665
David Horstmannceeaeb92023-01-05 15:44:23 +0000666 if (cert_len > 0) {
667 printf("\tPeer digest cert : ");
668 CHECK_SSL_END(cert_len);
669 print_hex(ssl, cert_len, 16, "\t ");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100670 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100671 }
672 }
673 }
674
David Horstmannceeaeb92023-01-05 15:44:23 +0000675 if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
676 printf("\nTicket:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100677
David Horstmannceeaeb92023-01-05 15:44:23 +0000678 CHECK_SSL_END(3);
679 ticket_len = ((uint32_t) ssl[0] << 16) |
680 ((uint32_t) ssl[1] << 8) |
681 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100682 ssl += 3;
David Horstmannceeaeb92023-01-05 15:44:23 +0000683 printf_dbg("Ticket length: %u\n", ticket_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100684
David Horstmannceeaeb92023-01-05 15:44:23 +0000685 if (ticket_len > 0) {
686 printf("\t");
687 CHECK_SSL_END(ticket_len);
688 print_hex(ssl, ticket_len, 22, "\t");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100689 ssl += ticket_len;
David Horstmannceeaeb92023-01-05 15:44:23 +0000690 printf("\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100691 }
692
David Horstmannceeaeb92023-01-05 15:44:23 +0000693 CHECK_SSL_END(4);
694 ticket_lifetime = ((uint32_t) ssl[0] << 24) |
695 ((uint32_t) ssl[1] << 16) |
696 ((uint32_t) ssl[2] << 8) |
697 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100698 ssl += 4;
David Horstmannceeaeb92023-01-05 15:44:23 +0000699 printf("\tlifetime : %u sec.\n", ticket_lifetime);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100700 }
701
David Horstmannceeaeb92023-01-05 15:44:23 +0000702 if (ssl < end) {
703 printf("\nSession others:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100704 }
705
David Horstmannceeaeb92023-01-05 15:44:23 +0000706 if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
707 CHECK_SSL_END(1);
708 printf("\tMFL : %s\n", get_mfl_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100709 }
710
David Horstmannceeaeb92023-01-05 15:44:23 +0000711 if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
712 CHECK_SSL_END(1);
713 printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100714 }
715
David Horstmannceeaeb92023-01-05 15:44:23 +0000716 if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
717 CHECK_SSL_END(1);
718 printf("\tEncrypt-then-MAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100719 }
720
David Horstmannceeaeb92023-01-05 15:44:23 +0000721 if (0 != (end - ssl)) {
722 printf_err("%i bytes left to analyze from session\n", (int32_t) (end - ssl));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100723 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100724}
725
726/*
727 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100728 * about the context from provided data. This function was built based on
729 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
730 * due to dependencies on the mbedTLS configuration and the configuration of
731 * the context when serialization was created.
732 *
733 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200734 * // header
735 * uint8 version[3];
736 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100737 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200738 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100739 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
740 * // transform sub-structure
741 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200742 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100743 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200744 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100745 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
746 * // fields from ssl_context
747 * uint32 badmac_seen; // DTLS: number of records with failing MAC
748 * uint64 in_window_top; // DTLS: last validated record seq_num
749 * uint64 in_window; // DTLS: bitmask for replay protection
750 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
751 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
752 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200753 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100754 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
755 *
756 * /p ssl pointer to serialized session
757 * /p len number of bytes in the buffer
758 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000759void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100760{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100761 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100762 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100763 int session_cfg_flag;
764 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100765
David Horstmannceeaeb92023-01-05 15:44:23 +0000766 printf("\nMbed TLS version:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100767
David Horstmannceeaeb92023-01-05 15:44:23 +0000768 CHECK_SSL_END(3 + 2 + 3);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100769
David Horstmannceeaeb92023-01-05 15:44:23 +0000770 printf("\tmajor %u\n", (uint32_t) *ssl++);
771 printf("\tminor %u\n", (uint32_t) *ssl++);
772 printf("\tpath %u\n", (uint32_t) *ssl++);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100773
David Horstmannceeaeb92023-01-05 15:44:23 +0000774 printf("\nEnabled session and context configuration:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100775
David Horstmannceeaeb92023-01-05 15:44:23 +0000776 session_cfg_flag = ((int) ssl[0] << 8) | ((int) ssl[1]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100777 ssl += 2;
778
David Horstmannceeaeb92023-01-05 15:44:23 +0000779 context_cfg_flag = ((int) ssl[0] << 16) |
780 ((int) ssl[1] << 8) |
781 ((int) ssl[2]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100782 ssl += 3;
783
David Horstmannceeaeb92023-01-05 15:44:23 +0000784 printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
785 printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100786
David Horstmannceeaeb92023-01-05 15:44:23 +0000787 print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag);
788 print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag);
789 print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag);
790 print_if_bit("MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag);
791 print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag);
792 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag);
793 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
794 SESSION_CONFIG_CLIENT_TICKET_BIT,
795 session_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100796
David Horstmannceeaeb92023-01-05 15:44:23 +0000797 print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
798 CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT,
799 context_cfg_flag);
800 print_if_bit("MBEDTLS_SSL_DTLS_BADMAC_LIMIT",
801 CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT,
802 context_cfg_flag);
803 print_if_bit("MBEDTLS_SSL_DTLS_ANTI_REPLAY",
804 CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT,
805 context_cfg_flag);
806 print_if_bit("MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100807
David Horstmannceeaeb92023-01-05 15:44:23 +0000808 CHECK_SSL_END(4);
809 session_len = ((uint32_t) ssl[0] << 24) |
810 ((uint32_t) ssl[1] << 16) |
811 ((uint32_t) ssl[2] << 8) |
812 ((uint32_t) ssl[3]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100813 ssl += 4;
David Horstmannceeaeb92023-01-05 15:44:23 +0000814 printf_dbg("Session length %u\n", session_len);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100815
David Horstmannceeaeb92023-01-05 15:44:23 +0000816 CHECK_SSL_END(session_len);
817 print_deserialized_ssl_session(ssl, session_len, session_cfg_flag);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100818 ssl += session_len;
819
David Horstmannceeaeb92023-01-05 15:44:23 +0000820 printf("\nRandom bytes:\n\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100821
David Horstmannceeaeb92023-01-05 15:44:23 +0000822 CHECK_SSL_END(TRANSFORM_RANDBYTE_LEN);
823 print_hex(ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100824 ssl += TRANSFORM_RANDBYTE_LEN;
825
David Horstmannceeaeb92023-01-05 15:44:23 +0000826 printf("\nContext others:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100827
David Horstmannceeaeb92023-01-05 15:44:23 +0000828 if (CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag) {
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100829 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100830
David Horstmannceeaeb92023-01-05 15:44:23 +0000831 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100832 cid_len = *ssl++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000833 printf_dbg("In CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100834
David Horstmannceeaeb92023-01-05 15:44:23 +0000835 printf("\tin CID : ");
836 if (cid_len > 0) {
837 CHECK_SSL_END(cid_len);
838 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100839 ssl += cid_len;
David Horstmannceeaeb92023-01-05 15:44:23 +0000840 } else {
841 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100842 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100843
David Horstmannceeaeb92023-01-05 15:44:23 +0000844 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100845 cid_len = *ssl++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000846 printf_dbg("Out CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100847
David Horstmannceeaeb92023-01-05 15:44:23 +0000848 printf("\tout CID : ");
849 if (cid_len > 0) {
850 CHECK_SSL_END(cid_len);
851 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100852 ssl += cid_len;
David Horstmannceeaeb92023-01-05 15:44:23 +0000853 } else {
854 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100855 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100856 }
857
David Horstmannceeaeb92023-01-05 15:44:23 +0000858 if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100859 uint32_t badmac_seen;
860
David Horstmannceeaeb92023-01-05 15:44:23 +0000861 CHECK_SSL_END(4);
862 badmac_seen = ((uint32_t) ssl[0] << 24) |
863 ((uint32_t) ssl[1] << 16) |
864 ((uint32_t) ssl[2] << 8) |
865 ((uint32_t) ssl[3]);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100866 ssl += 4;
David Horstmannceeaeb92023-01-05 15:44:23 +0000867 printf("\tbad MAC seen number : %u\n", badmac_seen);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100868
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100869 /* value 'in_window_top' from mbedtls_ssl_context */
David Horstmannceeaeb92023-01-05 15:44:23 +0000870 printf("\tlast validated record sequence no. : ");
871 CHECK_SSL_END(8);
872 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100873 ssl += 8;
874
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100875 /* value 'in_window' from mbedtls_ssl_context */
David Horstmannceeaeb92023-01-05 15:44:23 +0000876 printf("\tbitmask for replay detection : ");
877 CHECK_SSL_END(8);
878 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100879 ssl += 8;
880 }
881
David Horstmannceeaeb92023-01-05 15:44:23 +0000882 if (conf_dtls_proto) {
883 CHECK_SSL_END(1);
884 printf("\tDTLS datagram packing : %s\n",
885 get_enabled_str(!(*ssl++)));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100886 }
887
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100888 /* value 'cur_out_ctr' from mbedtls_ssl_context */
David Horstmannceeaeb92023-01-05 15:44:23 +0000889 printf("\toutgoing record sequence no. : ");
890 CHECK_SSL_END(8);
891 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100892 ssl += 8;
893
David Horstmannceeaeb92023-01-05 15:44:23 +0000894 if (conf_dtls_proto) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100895 uint16_t mtu;
David Horstmannceeaeb92023-01-05 15:44:23 +0000896 CHECK_SSL_END(2);
897 mtu = (ssl[0] << 8) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898 ssl += 2;
David Horstmannceeaeb92023-01-05 15:44:23 +0000899 printf("\tMTU : %u\n", mtu);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100900 }
901
902
David Horstmannceeaeb92023-01-05 15:44:23 +0000903 if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100904 uint8_t alpn_len;
905
David Horstmannceeaeb92023-01-05 15:44:23 +0000906 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100907 alpn_len = *ssl++;
David Horstmannceeaeb92023-01-05 15:44:23 +0000908 printf_dbg("ALPN length %u\n", (uint32_t) alpn_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100909
David Horstmannceeaeb92023-01-05 15:44:23 +0000910 printf("\tALPN negotiation : ");
911 CHECK_SSL_END(alpn_len);
912 if (alpn_len > 0) {
913 if (strlen((const char *) ssl) == alpn_len) {
914 printf("%s\n", ssl);
915 } else {
916 printf("\n");
917 printf_err("\tALPN negotiation is incorrect\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100918 }
919 ssl += alpn_len;
David Horstmannceeaeb92023-01-05 15:44:23 +0000920 } else {
921 printf("not selected\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100922 }
923 }
924
David Horstmannceeaeb92023-01-05 15:44:23 +0000925 if (0 != (end - ssl)) {
926 printf_err("%i bytes left to analyze from context\n", (int32_t) (end - ssl));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100927 }
David Horstmannceeaeb92023-01-05 15:44:23 +0000928 printf("\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100929}
930
David Horstmannceeaeb92023-01-05 15:44:23 +0000931int main(int argc, char *argv[])
Piotr Nowicki9370f902020-03-13 14:43:22 +0100932{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200933 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100934
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100935 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200936 uint8_t *b64_buf = NULL;
937 uint8_t *ssl_buf = NULL;
938 size_t b64_max_len = SSL_INIT_LEN;
939 size_t ssl_max_len = SSL_INIT_LEN;
940 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100941
David Horstmannceeaeb92023-01-05 15:44:23 +0000942 /* The 'b64_file' is opened when parsing arguments to check that the
943 * file name is correct */
944 parse_arguments(argc, argv);
Piotr Nowicki9370f902020-03-13 14:43:22 +0100945
David Horstmannceeaeb92023-01-05 15:44:23 +0000946 if (NULL != b64_file) {
947 b64_buf = malloc(SSL_INIT_LEN);
948 ssl_buf = malloc(SSL_INIT_LEN);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200949
David Horstmannceeaeb92023-01-05 15:44:23 +0000950 if (NULL == b64_buf || NULL == ssl_buf) {
951 printf_err(alloc_err);
952 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200953 b64_file = NULL;
954 }
955 }
956
David Horstmannceeaeb92023-01-05 15:44:23 +0000957 while (NULL != b64_file) {
958 size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
959 if (b64_len > 0) {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100960 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200961 size_t ssl_required_len = b64_len * 3 / 4 + 1;
962
963 /* Allocate more memory if necessary. */
David Horstmannceeaeb92023-01-05 15:44:23 +0000964 if (ssl_required_len > ssl_max_len) {
965 void *ptr = realloc(ssl_buf, ssl_required_len);
966 if (NULL == ptr) {
967 printf_err(alloc_err);
968 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200969 b64_file = NULL;
970 break;
971 }
972 ssl_buf = ptr;
973 ssl_max_len = ssl_required_len;
974 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100975
David Horstmannceeaeb92023-01-05 15:44:23 +0000976 printf("\nDeserializing number %u:\n", ++b64_counter);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100977
David Horstmannceeaeb92023-01-05 15:44:23 +0000978 printf("\nBase64 code:\n");
979 print_b64(b64_buf, b64_len);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100980
David Horstmannceeaeb92023-01-05 15:44:23 +0000981 ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len);
982 if (ret != 0) {
983 mbedtls_strerror(ret, (char *) b64_buf, b64_max_len);
984 printf_err("base64 code cannot be decoded - %s\n", b64_buf);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100985 continue;
986 }
987
David Horstmannceeaeb92023-01-05 15:44:23 +0000988 if (debug) {
989 printf("\nDecoded data in hex:\n\t");
990 print_hex(ssl_buf, ssl_len, 25, "\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100991 }
Piotr Nowicki14d31052020-03-16 14:05:22 +0100992
David Horstmannceeaeb92023-01-05 15:44:23 +0000993 print_deserialized_ssl_context(ssl_buf, ssl_len);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100994
David Horstmannceeaeb92023-01-05 15:44:23 +0000995 } else {
996 fclose(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100997 b64_file = NULL;
998 }
999 }
1000
David Horstmannceeaeb92023-01-05 15:44:23 +00001001 free(b64_buf);
1002 free(ssl_buf);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001003
David Horstmannceeaeb92023-01-05 15:44:23 +00001004 if (b64_counter > 0) {
1005 printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
1006 } else {
1007 printf("Finished. No valid base64 code found\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001008 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001009
Piotr Nowicki9370f902020-03-13 14:43:22 +01001010 return 0;
1011}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001012
1013#endif /* MBEDTLS_X509_CRT_PARSE_C */