blob: 0ba0d2c04c728cbf4c9b7060f62e02b2f4926d18 [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"
Paul Elliottef9ccca2021-12-09 14:48:47 +000023#include "mbedtls/debug.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010024
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010025#include <stdio.h>
26#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020027
Gilles Peskinef4a6a052020-11-09 14:55:35 +010028#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
29 !defined(MBEDTLS_SSL_TLS_C)
David Horstmann8b6068b2023-01-05 15:42:32 +000030int main(void)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020031{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010032 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
33 "MBEDTLS_SSL_TLS_C not defined.\n");
David Horstmann8b6068b2023-01-05 15:42:32 +000034 return 0;
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020035}
36#else
37
38#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
39#define _CRT_SECURE_NO_DEPRECATE 1
40#endif
41
Piotr Nowicki14d31052020-03-16 14:05:22 +010042#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010043#include <stdarg.h>
44#include <string.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020045#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010046#include <time.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020047#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010048#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010049#include "mbedtls/error.h"
50#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010051#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010052#include "mbedtls/x509_crt.h"
53#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010054
55/*
56 * This program version
57 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010058#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010059#define VER_MAJOR 0
60#define VER_MINOR 1
61
62/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020063 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010064 */
David Horstmann8b6068b2023-01-05 15:42:32 +000065#define SESSION_CONFIG_TIME_BIT (1 << 0)
66#define SESSION_CONFIG_CRT_BIT (1 << 1)
67#define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
68#define SESSION_CONFIG_MFL_BIT (1 << 3)
69#define SESSION_CONFIG_TRUNC_HMAC_BIT (1 << 4)
70#define SESSION_CONFIG_ETM_BIT (1 << 5)
71#define SESSION_CONFIG_TICKET_BIT (1 << 6)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010072
David Horstmann8b6068b2023-01-05 15:42:32 +000073#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT (1 << 0)
74#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT (1 << 1)
75#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT (1 << 2)
76#define CONTEXT_CONFIG_ALPN_BIT (1 << 3)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010077
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010078#define TRANSFORM_RANDBYTE_LEN 64
79
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010080/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020081 * Minimum and maximum number of bytes for specific data: context, sessions,
82 * certificates, tickets and buffers in the program. The context and session
83 * size values have been calculated based on the 'print_deserialized_ssl_context()'
84 * and 'print_deserialized_ssl_session()' content.
85 */
86#define MIN_CONTEXT_LEN 84
87#define MIN_SESSION_LEN 88
88
89#define MAX_CONTEXT_LEN 875 /* without session data */
90#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
David Horstmann8b6068b2023-01-05 15:42:32 +000091#define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
92#define MAX_TICKET_LEN ((1 << 24) - 1)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020093
David Horstmann8b6068b2023-01-05 15:42:32 +000094#define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
95#define MAX_SERIALIZED_DATA (MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
96 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020097
David Horstmann8b6068b2023-01-05 15:42:32 +000098#define MIN_BASE64_LEN (MIN_SERIALIZED_DATA * 4 / 3)
99#define MAX_BASE64_LEN (MAX_SERIALIZED_DATA * 4 / 3 + 3)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200100
101/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100102 * A macro that prevents from reading out of the ssl buffer range.
103 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000104#define CHECK_SSL_END(LEN) \
105 do \
106 { \
107 if (end - ssl < (int) (LEN)) \
108 { \
109 printf_err("%s", buf_ln_err); \
110 return; \
111 } \
112 } while (0)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100113
114/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100115 * Global values
116 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100117FILE *b64_file = NULL; /* file with base64 codes to deserialize */
118char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
119char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
120char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200121const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100122const char buf_ln_err[] = "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 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000127void print_version()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100128{
David Horstmann8b6068b2023-01-05 15:42:32 +0000129 printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100130}
131
David Horstmann8b6068b2023-01-05 15:42:32 +0000132void print_usage()
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100133{
134 print_version();
David Horstmann8b6068b2023-01-05 15:42:32 +0000135 printf("\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
136 "in the text file. The program can deserialize many codes from one file, but they must be\n"
137 "separated, e.g. by a newline.\n\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100138 printf(
139 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100140 "\t-f path - Path to the file with base64 code\n"
141 "\t-v - Show version\n"
142 "\t-h - Show this usage\n"
143 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200144 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100145 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
146 "\t flag. You can also use it if there are some problems with reading\n"
147 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200148 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100149 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100150 "\n"
David Horstmann8b6068b2023-01-05 15:42:32 +0000151 );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100152}
153
David Horstmann8b6068b2023-01-05 15:42:32 +0000154void printf_dbg(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100155{
David Horstmann8b6068b2023-01-05 15:42:32 +0000156 if (debug) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100157 va_list args;
David Horstmann8b6068b2023-01-05 15:42:32 +0000158 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
David Horstmann8b6068b2023-01-05 15:42:32 +0000166MBEDTLS_PRINTF_ATTRIBUTE(1, 2)
167void printf_err(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100168{
169 va_list args;
David Horstmann8b6068b2023-01-05 15:42:32 +0000170 va_start(args, str);
171 fflush(stdout);
172 fprintf(stderr, "ERROR: ");
173 vfprintf(stderr, str, args);
174 fflush(stderr);
175 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100176}
177
178/*
179 * Exit from the program in case of error
180 */
181void error_exit()
182{
David Horstmann8b6068b2023-01-05 15:42:32 +0000183 if (NULL != b64_file) {
184 fclose(b64_file);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100185 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000186 exit(-1);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100187}
188
189/*
190 * This function takes the input arguments of this program
191 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000192void parse_arguments(int argc, char *argv[])
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100193{
194 int i = 1;
195
David Horstmann8b6068b2023-01-05 15:42:32 +0000196 if (argc < 2) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100197 print_usage();
198 error_exit();
199 }
200
David Horstmann8b6068b2023-01-05 15:42:32 +0000201 while (i < argc) {
202 if (strcmp(argv[i], "-d") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100203 debug = 1;
David Horstmann8b6068b2023-01-05 15:42:32 +0000204 } else if (strcmp(argv[i], "-h") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100205 print_usage();
David Horstmann8b6068b2023-01-05 15:42:32 +0000206 } else if (strcmp(argv[i], "-v") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100207 print_version();
David Horstmann8b6068b2023-01-05 15:42:32 +0000208 } else if (strcmp(argv[i], "-f") == 0) {
209 if (++i >= argc) {
210 printf_err("File path is empty\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100211 error_exit();
212 }
213
David Horstmann8b6068b2023-01-05 15:42:32 +0000214 if (NULL != b64_file) {
215 printf_err("Cannot specify more than one file with -f\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100216 error_exit();
217 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000218
219 if ((b64_file = fopen(argv[i], "r")) == NULL) {
220 printf_err("Cannot find file \"%s\"\n", argv[i]);
221 error_exit();
222 }
223 } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100224 conf_keep_peer_certificate = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000225 } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100226 conf_dtls_proto = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000227 } else {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100228 print_usage();
229 error_exit();
230 }
231
232 i++;
233 }
234}
235
Piotr Nowicki14d31052020-03-16 14:05:22 +0100236/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100237 * This function prints base64 code to the stdout
238 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000239void print_b64(const uint8_t *b, size_t len)
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100240{
241 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100242 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100243 printf("\t");
David Horstmann8b6068b2023-01-05 15:42:32 +0000244 while (b < end) {
245 if (++i > 75) {
246 printf("\n\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100247 i = 0;
248 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000249 printf("%c", *b++);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100250 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000251 printf("\n");
252 fflush(stdout);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100253}
254
255/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100256 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100257 *
258 * /p b buffer with data to print
259 * /p len number of bytes to print
260 * /p in_line number of bytes in one line
261 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100262 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000263void print_hex(const uint8_t *b, size_t len,
264 const size_t in_line, const char *prefix)
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100265{
266 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100267 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100268
David Horstmann8b6068b2023-01-05 15:42:32 +0000269 if (prefix == NULL) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100270 prefix = "";
271 }
272
David Horstmann8b6068b2023-01-05 15:42:32 +0000273 while (b < end) {
274 if (++i > in_line) {
275 printf("\n%s", prefix);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100276 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100277 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000278 printf("%02X ", (uint8_t) *b++);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100279 }
280 printf("\n");
281 fflush(stdout);
282}
283
284/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100285 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
286 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000287void print_time(const uint64_t *time)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100288{
Andrzej Kurek541318a2022-02-28 05:51:57 -0500289#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100290 char buf[20];
David Horstmann8b6068b2023-01-05 15:42:32 +0000291 struct tm *t = gmtime((time_t *) time);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100292 static const char format[] = "%Y-%m-%d %H:%M:%S";
David Horstmann8b6068b2023-01-05 15:42:32 +0000293 if (NULL != t) {
294 strftime(buf, sizeof(buf), format, t);
295 printf("%s\n", buf);
296 } else {
297 printf("unknown\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100298 }
Andrzej Kurek541318a2022-02-28 05:51:57 -0500299#else
300 (void) time;
David Horstmann8b6068b2023-01-05 15:42:32 +0000301 printf("not supported\n");
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200302#endif
Andrzej Kurek541318a2022-02-28 05:51:57 -0500303}
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100304
305/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100306 * Print the input string if the bit is set in the value
307 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000308void print_if_bit(const char *str, int bit, int val)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100309{
David Horstmann8b6068b2023-01-05 15:42:32 +0000310 if (bit & val) {
311 printf("\t%s\n", str);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100312 }
313}
314
315/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100316 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
317 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000318const char *get_enabled_str(int is_en)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100319{
David Horstmann8b6068b2023-01-05 15:42:32 +0000320 return (is_en) ? "enabled" : "disabled";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100321}
322
323/*
324 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
325 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000326const char *get_mfl_str(int mfl_code)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100327{
David Horstmann8b6068b2023-01-05 15:42:32 +0000328 switch (mfl_code) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100329 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
330 return "none";
331 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
332 return "512";
333 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
334 return "1024";
335 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
336 return "2048";
337 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
338 return "4096";
339 default:
340 return "error";
341 }
342}
343
344/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100345 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
346 * previously. After each call to this function, the internal file position
347 * indicator of the global b64_file is advanced.
348 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200349 * Note - This function checks the size of the input buffer and if necessary,
350 * increases it to the maximum MAX_BASE64_LEN
351 *
352 * /p b64 pointer to the pointer of the buffer for input data
353 * /p max_len pointer to the current buffer capacity. It can be changed if
354 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100355 *
356 * \retval number of bytes written in to the b64 buffer or 0 in case no more
357 * data was found
358 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000359size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
Piotr Nowicki14d31052020-03-16 14:05:22 +0100360{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200361 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100362 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100363 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000364 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100365
David Horstmann8b6068b2023-01-05 15:42:32 +0000366 while (EOF != c) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100367 char c_valid = 0;
368
David Horstmann8b6068b2023-01-05 15:42:32 +0000369 c = fgetc(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100370
David Horstmann8b6068b2023-01-05 15:42:32 +0000371 if (pad > 0) {
372 if (c == '=' && pad == 1) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100373 c_valid = 1;
374 pad = 2;
375 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000376 } else if ((c >= 'A' && c <= 'Z') ||
377 (c >= 'a' && c <= 'z') ||
378 (c >= '0' && c <= '9') ||
379 c == '+' || c == '/') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100380 c_valid = 1;
David Horstmann8b6068b2023-01-05 15:42:32 +0000381 } else if (c == '=') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100382 c_valid = 1;
383 pad = 1;
David Horstmann8b6068b2023-01-05 15:42:32 +0000384 } else if (c == '-') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100385 c = '+';
386 c_valid = 1;
David Horstmann8b6068b2023-01-05 15:42:32 +0000387 } else if (c == '_') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100388 c = '/';
389 c_valid = 1;
390 }
391
David Horstmann8b6068b2023-01-05 15:42:32 +0000392 if (c_valid) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200393 /* A string of characters that could be a base64 code. */
394 valid_balance++;
395
David Horstmann8b6068b2023-01-05 15:42:32 +0000396 if (len < *max_len) {
397 (*b64)[len++] = c;
398 } else if (*max_len < MAX_BASE64_LEN) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200399 /* Current buffer is too small, but can be resized. */
400 void *ptr;
David Horstmann8b6068b2023-01-05 15:42:32 +0000401 size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200402 *max_len + 4096 : MAX_BASE64_LEN;
403
David Horstmann8b6068b2023-01-05 15:42:32 +0000404 ptr = realloc(*b64, new_size);
405 if (NULL == ptr) {
406 printf_err(alloc_err);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200407 return 0;
408 }
409 *b64 = ptr;
410 *max_len = new_size;
David Horstmann8b6068b2023-01-05 15:42:32 +0000411 (*b64)[len++] = c;
412 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200413 /* Too much data so it will be treated as invalid */
414 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100415 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000416 } else if (len > 0) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200417 /* End of a string that could be a base64 code, but need to check
418 * that the length of the characters is correct. */
419
420 valid_balance--;
421
David Horstmann8b6068b2023-01-05 15:42:32 +0000422 if (len < MIN_CONTEXT_LEN) {
423 printf_dbg("The code found is too small to be a SSL context.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200424 len = pad = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000425 } else if (len > *max_len) {
426 printf_err("The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
427 len - *max_len);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200428 len = pad = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000429 } else if (len % 4 != 0) {
430 printf_err("The length of the base64 code found should be a multiple of 4.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200431 len = pad = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000432 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200433 /* Base64 code with valid character length. */
434 return len;
435 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000436 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200437 valid_balance--;
438 }
439
440 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
David Horstmann8b6068b2023-01-05 15:42:32 +0000441 if (valid_balance < -100) {
442 printf_err("Too many bad symbols detected. File check aborted.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200443 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100444 }
445 }
446
David Horstmann8b6068b2023-01-05 15:42:32 +0000447 printf_dbg("End of file\n");
Piotr Nowicki14d31052020-03-16 14:05:22 +0100448 return 0;
449}
450
Hanno Becker2c2722d2020-10-09 09:36:23 +0100451#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100452/*
453 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100454 * about the certificates from provided data.
455 *
456 * /p ssl pointer to serialized certificate
457 * /p len number of bytes in the buffer
David Horstmann8b6068b2023-01-05 15:42:32 +0000458 */
459void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100460{
461 enum { STRLEN = 4096 };
462 mbedtls_x509_crt crt;
463 int ret;
464 char str[STRLEN];
465
David Horstmann8b6068b2023-01-05 15:42:32 +0000466 printf("\nCertificate:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100467
David Horstmann8b6068b2023-01-05 15:42:32 +0000468 mbedtls_x509_crt_init(&crt);
469 ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
470 if (0 != ret) {
471 mbedtls_strerror(ret, str, STRLEN);
472 printf_err("Invalid format of X.509 - %s\n", str);
473 printf("Cannot deserialize:\n\t");
474 print_hex(ssl, len, 25, "\t");
475 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100476 mbedtls_x509_crt *current = &crt;
477
David Horstmann8b6068b2023-01-05 15:42:32 +0000478 while (current != NULL) {
479 ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
480 if (0 > ret) {
481 mbedtls_strerror(ret, str, STRLEN);
482 printf_err("Cannot write to the output - %s\n", str);
483 } else {
484 printf("%s", str);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100485 }
486
487 current = current->next;
488
David Horstmann8b6068b2023-01-05 15:42:32 +0000489 if (current) {
490 printf("\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100491 }
492
493 }
494 }
495
David Horstmann8b6068b2023-01-05 15:42:32 +0000496 mbedtls_x509_crt_free(&crt);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100497}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100498#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100499
500/*
501 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100502 * about the session from provided data. This function was built based on
503 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
504 * due to dependencies on the mbedTLS configuration.
505 *
506 * The data structure in the buffer:
507 * uint64 start_time;
508 * uint8 ciphersuite[2]; // defined by the standard
509 * uint8 compression; // 0 or 1
510 * uint8 session_id_len; // at most 32
511 * opaque session_id[32];
512 * opaque master[48]; // fixed length in the standard
513 * uint32 verify_result;
514 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
515 * opaque ticket<0..2^24-1>; // length 0 means no ticket
516 * uint32 ticket_lifetime;
517 * uint8 mfl_code; // up to 255 according to standard
518 * uint8 trunc_hmac; // 0 or 1
519 * uint8 encrypt_then_mac; // 0 or 1
520 *
521 * /p ssl pointer to serialized session
522 * /p len number of bytes in the buffer
523 * /p session_cfg_flag session configuration flags
524 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000525void print_deserialized_ssl_session(const uint8_t *ssl, uint32_t len,
526 int session_cfg_flag)
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100527{
David Horstmann8b6068b2023-01-05 15:42:32 +0000528 const struct mbedtls_ssl_ciphersuite_t *ciphersuite_info;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100529 int ciphersuite_id;
530 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100531 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100532 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100533
David Horstmann8b6068b2023-01-05 15:42:32 +0000534 printf("\nSession info:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100535
David Horstmann8b6068b2023-01-05 15:42:32 +0000536 if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100537 uint64_t start;
David Horstmann8b6068b2023-01-05 15:42:32 +0000538 CHECK_SSL_END(8);
539 start = ((uint64_t) ssl[0] << 56) |
540 ((uint64_t) ssl[1] << 48) |
541 ((uint64_t) ssl[2] << 40) |
542 ((uint64_t) ssl[3] << 32) |
543 ((uint64_t) ssl[4] << 24) |
544 ((uint64_t) ssl[5] << 16) |
545 ((uint64_t) ssl[6] << 8) |
546 ((uint64_t) ssl[7]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100547 ssl += 8;
David Horstmann8b6068b2023-01-05 15:42:32 +0000548 printf("\tstart time : ");
549 print_time(&start);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100550 }
551
David Horstmann8b6068b2023-01-05 15:42:32 +0000552 CHECK_SSL_END(2);
553 ciphersuite_id = ((int) ssl[0] << 8) | (int) ssl[1];
554 printf_dbg("Ciphersuite ID: %d\n", ciphersuite_id);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100555 ssl += 2;
556
David Horstmann8b6068b2023-01-05 15:42:32 +0000557 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
558 if (ciphersuite_info == NULL) {
559 printf_err("Cannot find ciphersuite info\n");
560 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100561 const mbedtls_cipher_info_t *cipher_info;
Andrzej Kurekdcce5052022-08-30 17:56:08 -0400562#if defined(MBEDTLS_MD_C)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100563 const mbedtls_md_info_t *md_info;
Andrzej Kurekdcce5052022-08-30 17:56:08 -0400564#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100565
David Horstmann8b6068b2023-01-05 15:42:32 +0000566 printf("\tciphersuite : %s\n", ciphersuite_info->name);
567 printf("\tcipher flags : 0x%02X\n", ciphersuite_info->flags);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100568
David Horstmann8b6068b2023-01-05 15:42:32 +0000569 cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
570 if (cipher_info == NULL) {
571 printf_err("Cannot find cipher info\n");
572 } else {
573 printf("\tcipher : %s\n", cipher_info->name);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100574 }
Andrzej Kurek8c95ac42022-08-17 16:17:00 -0400575#if defined(MBEDTLS_MD_C)
David Horstmann8b6068b2023-01-05 15:42:32 +0000576 md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
577 if (md_info == NULL) {
578 printf_err("Cannot find Message-Digest info\n");
579 } else {
580 printf("\tMessage-Digest : %s\n", mbedtls_md_get_name(md_info));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100581 }
Andrzej Kurekcccb0442022-08-19 03:42:11 -0400582#endif /* MBEDTLS_MD_C */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100583 }
584
David Horstmann8b6068b2023-01-05 15:42:32 +0000585 CHECK_SSL_END(1);
586 printf("\tcompression : %s\n", get_enabled_str(*ssl++));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100587
588 /* Note - Here we can get session ID length from serialized data, but we
589 * use hardcoded 32-bytes length. This approach was taken from
590 * 'mbedtls_ssl_session_load()'. */
David Horstmann8b6068b2023-01-05 15:42:32 +0000591 CHECK_SSL_END(1 + 32);
592 printf_dbg("Session id length: %u\n", (uint32_t) *ssl++);
593 printf("\tsession ID : ");
594 print_hex(ssl, 32, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100595 ssl += 32;
596
David Horstmann8b6068b2023-01-05 15:42:32 +0000597 printf("\tmaster secret : ");
598 CHECK_SSL_END(48);
599 print_hex(ssl, 48, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100600 ssl += 48;
601
David Horstmann8b6068b2023-01-05 15:42:32 +0000602 CHECK_SSL_END(4);
603 verify_result = ((uint32_t) ssl[0] << 24) |
604 ((uint32_t) ssl[1] << 16) |
605 ((uint32_t) ssl[2] << 8) |
606 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607 ssl += 4;
David Horstmann8b6068b2023-01-05 15:42:32 +0000608 printf("\tverify result : 0x%08X\n", verify_result);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100609
David Horstmann8b6068b2023-01-05 15:42:32 +0000610 if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
611 if (conf_keep_peer_certificate) {
612 CHECK_SSL_END(3);
613 cert_len = ((uint32_t) ssl[0] << 16) |
614 ((uint32_t) ssl[1] << 8) |
615 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100616 ssl += 3;
David Horstmann8b6068b2023-01-05 15:42:32 +0000617 printf_dbg("Certificate length: %u\n", cert_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100618
David Horstmann8b6068b2023-01-05 15:42:32 +0000619 if (cert_len > 0) {
620 CHECK_SSL_END(cert_len);
Hanno Becker2c2722d2020-10-09 09:36:23 +0100621#if !defined(MBEDTLS_X509_REMOVE_INFO)
David Horstmann8b6068b2023-01-05 15:42:32 +0000622 print_deserialized_ssl_cert(ssl, cert_len);
Hanno Becker2c2722d2020-10-09 09:36:23 +0100623#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100624 ssl += cert_len;
625 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000626 } else {
627 printf("\tPeer digest : ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100628
David Horstmann8b6068b2023-01-05 15:42:32 +0000629 CHECK_SSL_END(1);
630 switch ((mbedtls_md_type_t) *ssl++) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100631 case MBEDTLS_MD_NONE:
David Horstmann8b6068b2023-01-05 15:42:32 +0000632 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100633 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100634 case MBEDTLS_MD_MD5:
David Horstmann8b6068b2023-01-05 15:42:32 +0000635 printf("MD5\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100636 break;
637 case MBEDTLS_MD_SHA1:
David Horstmann8b6068b2023-01-05 15:42:32 +0000638 printf("SHA1\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100639 break;
640 case MBEDTLS_MD_SHA224:
David Horstmann8b6068b2023-01-05 15:42:32 +0000641 printf("SHA224\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100642 break;
643 case MBEDTLS_MD_SHA256:
David Horstmann8b6068b2023-01-05 15:42:32 +0000644 printf("SHA256\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100645 break;
646 case MBEDTLS_MD_SHA384:
David Horstmann8b6068b2023-01-05 15:42:32 +0000647 printf("SHA384\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100648 break;
649 case MBEDTLS_MD_SHA512:
David Horstmann8b6068b2023-01-05 15:42:32 +0000650 printf("SHA512\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100651 break;
652 case MBEDTLS_MD_RIPEMD160:
David Horstmann8b6068b2023-01-05 15:42:32 +0000653 printf("RIPEMD160\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100654 break;
655 default:
David Horstmann8b6068b2023-01-05 15:42:32 +0000656 printf("undefined or erroneous\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100657 break;
658 }
659
David Horstmann8b6068b2023-01-05 15:42:32 +0000660 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100661 cert_len = (uint32_t) *ssl++;
David Horstmann8b6068b2023-01-05 15:42:32 +0000662 printf_dbg("Message-Digest length: %u\n", cert_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100663
David Horstmann8b6068b2023-01-05 15:42:32 +0000664 if (cert_len > 0) {
665 printf("\tPeer digest cert : ");
666 CHECK_SSL_END(cert_len);
667 print_hex(ssl, cert_len, 16, "\t ");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100668 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100669 }
670 }
671 }
672
David Horstmann8b6068b2023-01-05 15:42:32 +0000673 if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
674 printf("\nTicket:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100675
David Horstmann8b6068b2023-01-05 15:42:32 +0000676 CHECK_SSL_END(3);
677 ticket_len = ((uint32_t) ssl[0] << 16) |
678 ((uint32_t) ssl[1] << 8) |
679 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100680 ssl += 3;
David Horstmann8b6068b2023-01-05 15:42:32 +0000681 printf_dbg("Ticket length: %u\n", ticket_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100682
David Horstmann8b6068b2023-01-05 15:42:32 +0000683 if (ticket_len > 0) {
684 printf("\t");
685 CHECK_SSL_END(ticket_len);
686 print_hex(ssl, ticket_len, 22, "\t");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100687 ssl += ticket_len;
David Horstmann8b6068b2023-01-05 15:42:32 +0000688 printf("\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100689 }
690
David Horstmann8b6068b2023-01-05 15:42:32 +0000691 CHECK_SSL_END(4);
692 ticket_lifetime = ((uint32_t) ssl[0] << 24) |
693 ((uint32_t) ssl[1] << 16) |
694 ((uint32_t) ssl[2] << 8) |
695 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100696 ssl += 4;
David Horstmann8b6068b2023-01-05 15:42:32 +0000697 printf("\tlifetime : %u sec.\n", ticket_lifetime);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100698 }
699
David Horstmann8b6068b2023-01-05 15:42:32 +0000700 if (ssl < end) {
701 printf("\nSession others:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100702 }
703
David Horstmann8b6068b2023-01-05 15:42:32 +0000704 if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
705 CHECK_SSL_END(1);
706 printf("\tMFL : %s\n", get_mfl_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100707 }
708
David Horstmann8b6068b2023-01-05 15:42:32 +0000709 if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
710 CHECK_SSL_END(1);
711 printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100712 }
713
David Horstmann8b6068b2023-01-05 15:42:32 +0000714 if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
715 CHECK_SSL_END(1);
716 printf("\tEncrypt-then-MAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100717 }
718
David Horstmann8b6068b2023-01-05 15:42:32 +0000719 if (0 != (end - ssl)) {
720 printf_err("%i bytes left to analyze from session\n", (int32_t) (end - ssl));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100721 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100722}
723
724/*
725 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100726 * about the context from provided data. This function was built based on
727 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
728 * due to dependencies on the mbedTLS configuration and the configuration of
729 * the context when serialization was created.
730 *
731 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200732 * // header
733 * uint8 version[3];
734 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100735 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200736 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100737 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
738 * // transform sub-structure
739 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200740 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100741 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200742 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100743 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
744 * // fields from ssl_context
745 * uint32 badmac_seen; // DTLS: number of records with failing MAC
746 * uint64 in_window_top; // DTLS: last validated record seq_num
747 * uint64 in_window; // DTLS: bitmask for replay protection
748 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
749 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
750 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200751 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100752 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
753 *
754 * /p ssl pointer to serialized session
755 * /p len number of bytes in the buffer
756 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000757void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100758{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100759 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100760 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100761 int session_cfg_flag;
762 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100763
David Horstmann8b6068b2023-01-05 15:42:32 +0000764 printf("\nMbed TLS version:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100765
David Horstmann8b6068b2023-01-05 15:42:32 +0000766 CHECK_SSL_END(3 + 2 + 3);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100767
David Horstmann8b6068b2023-01-05 15:42:32 +0000768 printf("\tmajor %u\n", (uint32_t) *ssl++);
769 printf("\tminor %u\n", (uint32_t) *ssl++);
770 printf("\tpath %u\n", (uint32_t) *ssl++);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100771
David Horstmann8b6068b2023-01-05 15:42:32 +0000772 printf("\nEnabled session and context configuration:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100773
David Horstmann8b6068b2023-01-05 15:42:32 +0000774 session_cfg_flag = ((int) ssl[0] << 8) | ((int) ssl[1]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100775 ssl += 2;
776
David Horstmann8b6068b2023-01-05 15:42:32 +0000777 context_cfg_flag = ((int) ssl[0] << 16) |
778 ((int) ssl[1] << 8) |
779 ((int) ssl[2]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100780 ssl += 3;
781
David Horstmann8b6068b2023-01-05 15:42:32 +0000782 printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
783 printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100784
David Horstmann8b6068b2023-01-05 15:42:32 +0000785 print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag);
786 print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag);
787 print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag);
788 print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag);
789 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag);
790 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
791 SESSION_CONFIG_CLIENT_TICKET_BIT,
792 session_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100793
David Horstmann8b6068b2023-01-05 15:42:32 +0000794 print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
795 CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT,
796 context_cfg_flag);
797 print_if_bit("MBEDTLS_SSL_DTLS_ANTI_REPLAY",
798 CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT,
799 context_cfg_flag);
800 print_if_bit("MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100801
David Horstmann8b6068b2023-01-05 15:42:32 +0000802 CHECK_SSL_END(4);
803 session_len = ((uint32_t) ssl[0] << 24) |
804 ((uint32_t) ssl[1] << 16) |
805 ((uint32_t) ssl[2] << 8) |
806 ((uint32_t) ssl[3]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100807 ssl += 4;
David Horstmann8b6068b2023-01-05 15:42:32 +0000808 printf_dbg("Session length %u\n", session_len);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100809
David Horstmann8b6068b2023-01-05 15:42:32 +0000810 CHECK_SSL_END(session_len);
811 print_deserialized_ssl_session(ssl, session_len, session_cfg_flag);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100812 ssl += session_len;
813
David Horstmann8b6068b2023-01-05 15:42:32 +0000814 printf("\nRandom bytes:\n\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100815
David Horstmann8b6068b2023-01-05 15:42:32 +0000816 CHECK_SSL_END(TRANSFORM_RANDBYTE_LEN);
817 print_hex(ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100818 ssl += TRANSFORM_RANDBYTE_LEN;
819
David Horstmann8b6068b2023-01-05 15:42:32 +0000820 printf("\nContext others:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100821
David Horstmann8b6068b2023-01-05 15:42:32 +0000822 if (CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag) {
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100823 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100824
David Horstmann8b6068b2023-01-05 15:42:32 +0000825 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100826 cid_len = *ssl++;
David Horstmann8b6068b2023-01-05 15:42:32 +0000827 printf_dbg("In CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100828
David Horstmann8b6068b2023-01-05 15:42:32 +0000829 printf("\tin CID : ");
830 if (cid_len > 0) {
831 CHECK_SSL_END(cid_len);
832 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100833 ssl += cid_len;
David Horstmann8b6068b2023-01-05 15:42:32 +0000834 } else {
835 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100836 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100837
David Horstmann8b6068b2023-01-05 15:42:32 +0000838 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100839 cid_len = *ssl++;
David Horstmann8b6068b2023-01-05 15:42:32 +0000840 printf_dbg("Out CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100841
David Horstmann8b6068b2023-01-05 15:42:32 +0000842 printf("\tout CID : ");
843 if (cid_len > 0) {
844 CHECK_SSL_END(cid_len);
845 print_hex(ssl, cid_len, 20, "\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100846 ssl += cid_len;
David Horstmann8b6068b2023-01-05 15:42:32 +0000847 } else {
848 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100849 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100850 }
851
David Horstmann8b6068b2023-01-05 15:42:32 +0000852 if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100853 uint32_t badmac_seen;
854
David Horstmann8b6068b2023-01-05 15:42:32 +0000855 CHECK_SSL_END(4);
856 badmac_seen = ((uint32_t) ssl[0] << 24) |
857 ((uint32_t) ssl[1] << 16) |
858 ((uint32_t) ssl[2] << 8) |
859 ((uint32_t) ssl[3]);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100860 ssl += 4;
David Horstmann8b6068b2023-01-05 15:42:32 +0000861 printf("\tbad MAC seen number : %u\n", badmac_seen);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100862
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100863 /* value 'in_window_top' from mbedtls_ssl_context */
David Horstmann8b6068b2023-01-05 15:42:32 +0000864 printf("\tlast validated record sequence no. : ");
865 CHECK_SSL_END(8);
866 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100867 ssl += 8;
868
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100869 /* value 'in_window' from mbedtls_ssl_context */
David Horstmann8b6068b2023-01-05 15:42:32 +0000870 printf("\tbitmask for replay detection : ");
871 CHECK_SSL_END(8);
872 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100873 ssl += 8;
874 }
875
David Horstmann8b6068b2023-01-05 15:42:32 +0000876 if (conf_dtls_proto) {
877 CHECK_SSL_END(1);
878 printf("\tDTLS datagram packing : %s\n",
879 get_enabled_str(!(*ssl++)));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100880 }
881
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100882 /* value 'cur_out_ctr' from mbedtls_ssl_context */
David Horstmann8b6068b2023-01-05 15:42:32 +0000883 printf("\toutgoing record sequence no. : ");
884 CHECK_SSL_END(8);
885 print_hex(ssl, 8, 20, "");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100886 ssl += 8;
887
David Horstmann8b6068b2023-01-05 15:42:32 +0000888 if (conf_dtls_proto) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100889 uint16_t mtu;
David Horstmann8b6068b2023-01-05 15:42:32 +0000890 CHECK_SSL_END(2);
891 mtu = (ssl[0] << 8) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100892 ssl += 2;
David Horstmann8b6068b2023-01-05 15:42:32 +0000893 printf("\tMTU : %u\n", mtu);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100894 }
895
896
David Horstmann8b6068b2023-01-05 15:42:32 +0000897 if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100898 uint8_t alpn_len;
899
David Horstmann8b6068b2023-01-05 15:42:32 +0000900 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100901 alpn_len = *ssl++;
David Horstmann8b6068b2023-01-05 15:42:32 +0000902 printf_dbg("ALPN length %u\n", (uint32_t) alpn_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100903
David Horstmann8b6068b2023-01-05 15:42:32 +0000904 printf("\tALPN negotiation : ");
905 CHECK_SSL_END(alpn_len);
906 if (alpn_len > 0) {
907 if (strlen((const char *) ssl) == alpn_len) {
908 printf("%s\n", ssl);
909 } else {
910 printf("\n");
911 printf_err("\tALPN negotiation is incorrect\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100912 }
913 ssl += alpn_len;
David Horstmann8b6068b2023-01-05 15:42:32 +0000914 } else {
915 printf("not selected\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100916 }
917 }
918
David Horstmann8b6068b2023-01-05 15:42:32 +0000919 if (0 != (end - ssl)) {
920 printf_err("%i bytes left to analyze from context\n", (int32_t) (end - ssl));
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100921 }
David Horstmann8b6068b2023-01-05 15:42:32 +0000922 printf("\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100923}
924
David Horstmann8b6068b2023-01-05 15:42:32 +0000925int main(int argc, char *argv[])
Piotr Nowicki9370f902020-03-13 14:43:22 +0100926{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200927 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100928
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100929 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200930 uint8_t *b64_buf = NULL;
931 uint8_t *ssl_buf = NULL;
932 size_t b64_max_len = SSL_INIT_LEN;
933 size_t ssl_max_len = SSL_INIT_LEN;
934 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100935
David Horstmann8b6068b2023-01-05 15:42:32 +0000936 /* The 'b64_file' is opened when parsing arguments to check that the
937 * file name is correct */
938 parse_arguments(argc, argv);
Piotr Nowicki9370f902020-03-13 14:43:22 +0100939
David Horstmann8b6068b2023-01-05 15:42:32 +0000940 if (NULL != b64_file) {
941 b64_buf = malloc(SSL_INIT_LEN);
942 ssl_buf = malloc(SSL_INIT_LEN);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200943
David Horstmann8b6068b2023-01-05 15:42:32 +0000944 if (NULL == b64_buf || NULL == ssl_buf) {
945 printf_err(alloc_err);
946 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200947 b64_file = NULL;
948 }
949 }
950
David Horstmann8b6068b2023-01-05 15:42:32 +0000951 while (NULL != b64_file) {
952 size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
953 if (b64_len > 0) {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100954 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200955 size_t ssl_required_len = b64_len * 3 / 4 + 1;
956
957 /* Allocate more memory if necessary. */
David Horstmann8b6068b2023-01-05 15:42:32 +0000958 if (ssl_required_len > ssl_max_len) {
959 void *ptr = realloc(ssl_buf, ssl_required_len);
960 if (NULL == ptr) {
961 printf_err(alloc_err);
962 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200963 b64_file = NULL;
964 break;
965 }
966 ssl_buf = ptr;
967 ssl_max_len = ssl_required_len;
968 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100969
David Horstmann8b6068b2023-01-05 15:42:32 +0000970 printf("\nDeserializing number %u:\n", ++b64_counter);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100971
David Horstmann8b6068b2023-01-05 15:42:32 +0000972 printf("\nBase64 code:\n");
973 print_b64(b64_buf, b64_len);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100974
David Horstmann8b6068b2023-01-05 15:42:32 +0000975 ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len);
976 if (ret != 0) {
977 mbedtls_strerror(ret, (char *) b64_buf, b64_max_len);
978 printf_err("base64 code cannot be decoded - %s\n", b64_buf);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100979 continue;
980 }
981
David Horstmann8b6068b2023-01-05 15:42:32 +0000982 if (debug) {
983 printf("\nDecoded data in hex:\n\t");
984 print_hex(ssl_buf, ssl_len, 25, "\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100985 }
Piotr Nowicki14d31052020-03-16 14:05:22 +0100986
David Horstmann8b6068b2023-01-05 15:42:32 +0000987 print_deserialized_ssl_context(ssl_buf, ssl_len);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100988
David Horstmann8b6068b2023-01-05 15:42:32 +0000989 } else {
990 fclose(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100991 b64_file = NULL;
992 }
993 }
994
David Horstmann8b6068b2023-01-05 15:42:32 +0000995 free(b64_buf);
996 free(ssl_buf);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200997
David Horstmann8b6068b2023-01-05 15:42:32 +0000998 if (b64_counter > 0) {
999 printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
1000 } else {
1001 printf("Finished. No valid base64 code found\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001002 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001003
Piotr Nowicki9370f902020-03-13 14:43:22 +01001004 return 0;
1005}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001006
1007#endif /* MBEDTLS_X509_CRT_PARSE_C */