blob: fca6afdcbdcafc7b49d7989f46b2128238c6cc9a [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
Thomas Daubney540324c2023-10-06 17:07:24 +01002 * Mbed TLS SSL context deserializer from base64 code
Piotr Nowicki9370f902020-03-13 14:43:22 +01003 *
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"
Przemek Stekiel89c636e2023-04-14 09:26:39 +020024#include "mbedtls/platform.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010025
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010026#include <stdio.h>
27#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020028
Gilles Peskinef4a6a052020-11-09 14:55:35 +010029#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
30 !defined(MBEDTLS_SSL_TLS_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010031int main(void)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020032{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010033 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
34 "MBEDTLS_SSL_TLS_C not defined.\n");
Gilles Peskine449bd832023-01-11 14:50:10 +010035 return 0;
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020036}
37#else
38
39#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
40#define _CRT_SECURE_NO_DEPRECATE 1
41#endif
42
Piotr Nowicki14d31052020-03-16 14:05:22 +010043#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010044#include <stdarg.h>
45#include <string.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020046#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010047#include <time.h>
Raoul Strackx9ed9bc92020-06-22 14:08:57 +020048#endif
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010049#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010050#include "mbedtls/error.h"
51#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010052#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010053#include "mbedtls/x509_crt.h"
54#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010055
56/*
57 * This program version
58 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010059#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010060#define VER_MAJOR 0
61#define VER_MINOR 1
62
63/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020064 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010065 */
Gilles Peskine449bd832023-01-11 14:50:10 +010066#define SESSION_CONFIG_TIME_BIT (1 << 0)
67#define SESSION_CONFIG_CRT_BIT (1 << 1)
68#define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
69#define SESSION_CONFIG_MFL_BIT (1 << 3)
70#define SESSION_CONFIG_TRUNC_HMAC_BIT (1 << 4)
71#define SESSION_CONFIG_ETM_BIT (1 << 5)
72#define SESSION_CONFIG_TICKET_BIT (1 << 6)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010073
Gilles Peskine449bd832023-01-11 14:50:10 +010074#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT (1 << 0)
75#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT (1 << 1)
76#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT (1 << 2)
77#define CONTEXT_CONFIG_ALPN_BIT (1 << 3)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010078
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010079#define TRANSFORM_RANDBYTE_LEN 64
80
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010081/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020082 * Minimum and maximum number of bytes for specific data: context, sessions,
83 * certificates, tickets and buffers in the program. The context and session
84 * size values have been calculated based on the 'print_deserialized_ssl_context()'
85 * and 'print_deserialized_ssl_session()' content.
86 */
87#define MIN_CONTEXT_LEN 84
88#define MIN_SESSION_LEN 88
89
90#define MAX_CONTEXT_LEN 875 /* without session data */
91#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
Gilles Peskine449bd832023-01-11 14:50:10 +010092#define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
93#define MAX_TICKET_LEN ((1 << 24) - 1)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020094
Gilles Peskine449bd832023-01-11 14:50:10 +010095#define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
96#define MAX_SERIALIZED_DATA (MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
97 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020098
Gilles Peskine449bd832023-01-11 14:50:10 +010099#define MIN_BASE64_LEN (MIN_SERIALIZED_DATA * 4 / 3)
100#define MAX_BASE64_LEN (MAX_SERIALIZED_DATA * 4 / 3 + 3)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200101
102/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100103 * A macro that prevents from reading out of the ssl buffer range.
104 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100105#define CHECK_SSL_END(LEN) \
106 do \
107 { \
108 if (end - ssl < (int) (LEN)) \
109 { \
110 printf_err("%s", buf_ln_err); \
111 return; \
112 } \
113 } while (0)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100114
115/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100116 * Global values
117 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100118FILE *b64_file = NULL; /* file with base64 codes to deserialize */
119char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
120char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
121char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200122const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100123const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100124
125/*
126 * Basic printing functions
127 */
Gowtham Suresh Kumar186731b2023-07-26 15:47:45 +0100128void print_version(void)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100129{
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100131}
132
Gowtham Suresh Kumar186731b2023-07-26 15:47:45 +0100133void print_usage(void)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100134{
135 print_version();
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 printf("\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
137 "in the text file. The program can deserialize many codes from one file, but they must be\n"
138 "separated, e.g. by a newline.\n\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100139 printf(
140 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100141 "\t-f path - Path to the file with base64 code\n"
142 "\t-v - Show version\n"
143 "\t-h - Show this usage\n"
144 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200145 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100146 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
147 "\t flag. You can also use it if there are some problems with reading\n"
148 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200149 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100150 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100151 "\n"
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100153}
154
Gilles Peskine449bd832023-01-11 14:50:10 +0100155void printf_dbg(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100156{
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 if (debug) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100158 va_list args;
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 va_start(args, str);
160 printf("debug: ");
161 vprintf(str, args);
162 fflush(stdout);
163 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100164 }
165}
166
Gilles Peskine449bd832023-01-11 14:50:10 +0100167MBEDTLS_PRINTF_ATTRIBUTE(1, 2)
168void printf_err(const char *str, ...)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100169{
170 va_list args;
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 va_start(args, str);
172 fflush(stdout);
173 fprintf(stderr, "ERROR: ");
174 vfprintf(stderr, str, args);
175 fflush(stderr);
176 va_end(args);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100177}
178
179/*
180 * Exit from the program in case of error
181 */
Gowtham Suresh Kumar186731b2023-07-26 15:47:45 +0100182void error_exit(void)
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100183{
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 if (NULL != b64_file) {
185 fclose(b64_file);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100186 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 exit(-1);
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100188}
189
190/*
191 * This function takes the input arguments of this program
192 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100193void parse_arguments(int argc, char *argv[])
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100194{
195 int i = 1;
196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 if (argc < 2) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100198 print_usage();
199 error_exit();
200 }
201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 while (i < argc) {
203 if (strcmp(argv[i], "-d") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100204 debug = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 } else if (strcmp(argv[i], "-h") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100206 print_usage();
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 } else if (strcmp(argv[i], "-v") == 0) {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100208 print_version();
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 } else if (strcmp(argv[i], "-f") == 0) {
210 if (++i >= argc) {
211 printf_err("File path is empty\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100212 error_exit();
213 }
214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 if (NULL != b64_file) {
216 printf_err("Cannot specify more than one file with -f\n");
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100217 error_exit();
218 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100219
220 if ((b64_file = fopen(argv[i], "r")) == NULL) {
221 printf_err("Cannot find file \"%s\"\n", argv[i]);
222 error_exit();
223 }
224 } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100225 conf_keep_peer_certificate = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100227 conf_dtls_proto = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 } else {
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100229 print_usage();
230 error_exit();
231 }
232
233 i++;
234 }
235}
236
Piotr Nowicki14d31052020-03-16 14:05:22 +0100237/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100238 * This function prints base64 code to the stdout
239 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100240void print_b64(const uint8_t *b, size_t len)
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100241{
242 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100243 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100244 printf("\t");
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 while (b < end) {
246 if (++i > 75) {
247 printf("\n\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100248 i = 0;
249 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 printf("%c", *b++);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100251 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 printf("\n");
253 fflush(stdout);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100254}
255
256/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100257 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100258 *
259 * /p b buffer with data to print
260 * /p len number of bytes to print
261 * /p in_line number of bytes in one line
262 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100263 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100264void print_hex(const uint8_t *b, size_t len,
265 const size_t in_line, const char *prefix)
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100266{
267 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100268 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 if (prefix == NULL) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100271 prefix = "";
272 }
273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 while (b < end) {
275 if (++i > in_line) {
276 printf("\n%s", prefix);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100277 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100278 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 printf("%02X ", (uint8_t) *b++);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100280 }
281 printf("\n");
282 fflush(stdout);
283}
284
285/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100286 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
287 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100288void print_time(const uint64_t *time)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100289{
Andrzej Kurek541318a2022-02-28 05:51:57 -0500290#if defined(MBEDTLS_HAVE_TIME)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100291 char buf[20];
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 struct tm *t = gmtime((time_t *) time);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100293 static const char format[] = "%Y-%m-%d %H:%M:%S";
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 if (NULL != t) {
295 strftime(buf, sizeof(buf), format, t);
296 printf("%s\n", buf);
297 } else {
298 printf("unknown\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100299 }
Andrzej Kurek541318a2022-02-28 05:51:57 -0500300#else
301 (void) time;
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 printf("not supported\n");
Raoul Strackx9ed9bc92020-06-22 14:08:57 +0200303#endif
Andrzej Kurek541318a2022-02-28 05:51:57 -0500304}
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100305
306/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100307 * Print the input string if the bit is set in the value
308 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100309void print_if_bit(const char *str, int bit, int val)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100310{
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if (bit & val) {
312 printf("\t%s\n", str);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100313 }
314}
315
316/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100317 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
318 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100319const char *get_enabled_str(int is_en)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100320{
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 return (is_en) ? "enabled" : "disabled";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100322}
323
324/*
325 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
326 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100327const char *get_mfl_str(int mfl_code)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100328{
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 switch (mfl_code) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100330 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
331 return "none";
332 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
333 return "512";
334 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
335 return "1024";
336 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
337 return "2048";
338 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
339 return "4096";
340 default:
341 return "error";
342 }
343}
344
345/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100346 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
347 * previously. After each call to this function, the internal file position
348 * indicator of the global b64_file is advanced.
349 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200350 * Note - This function checks the size of the input buffer and if necessary,
351 * increases it to the maximum MAX_BASE64_LEN
352 *
353 * /p b64 pointer to the pointer of the buffer for input data
354 * /p max_len pointer to the current buffer capacity. It can be changed if
355 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100356 *
357 * \retval number of bytes written in to the b64 buffer or 0 in case no more
358 * data was found
359 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100360size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
Piotr Nowicki14d31052020-03-16 14:05:22 +0100361{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200362 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100363 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100364 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000365 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 while (EOF != c) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100368 char c_valid = 0;
369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 c = fgetc(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +0100371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 if (pad > 0) {
373 if (c == '=' && pad == 1) {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100374 c_valid = 1;
375 pad = 2;
376 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 } else if ((c >= 'A' && c <= 'Z') ||
378 (c >= 'a' && c <= 'z') ||
379 (c >= '0' && c <= '9') ||
380 c == '+' || c == '/') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100381 c_valid = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 } else if (c == '=') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100383 c_valid = 1;
384 pad = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 } else if (c == '-') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100386 c = '+';
387 c_valid = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 } else if (c == '_') {
Piotr Nowicki14d31052020-03-16 14:05:22 +0100389 c = '/';
390 c_valid = 1;
391 }
392
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 if (c_valid) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200394 /* A string of characters that could be a base64 code. */
395 valid_balance++;
396
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 if (len < *max_len) {
398 (*b64)[len++] = c;
399 } else if (*max_len < MAX_BASE64_LEN) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200400 /* Current buffer is too small, but can be resized. */
401 void *ptr;
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200403 *max_len + 4096 : MAX_BASE64_LEN;
404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 ptr = realloc(*b64, new_size);
406 if (NULL == ptr) {
407 printf_err(alloc_err);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200408 return 0;
409 }
410 *b64 = ptr;
411 *max_len = new_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 (*b64)[len++] = c;
413 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200414 /* Too much data so it will be treated as invalid */
415 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100416 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 } else if (len > 0) {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200418 /* End of a string that could be a base64 code, but need to check
419 * that the length of the characters is correct. */
420
421 valid_balance--;
422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 if (len < MIN_CONTEXT_LEN) {
424 printf_dbg("The code found is too small to be a SSL context.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200425 len = pad = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 } else if (len > *max_len) {
427 printf_err("The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
428 len - *max_len);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200429 len = pad = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 } else if (len % 4 != 0) {
431 printf_err("The length of the base64 code found should be a multiple of 4.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200432 len = pad = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200434 /* Base64 code with valid character length. */
435 return len;
436 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 } else {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200438 valid_balance--;
439 }
440
441 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 if (valid_balance < -100) {
443 printf_err("Too many bad symbols detected. File check aborted.\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200444 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100445 }
446 }
447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 printf_dbg("End of file\n");
Piotr Nowicki14d31052020-03-16 14:05:22 +0100449 return 0;
450}
451
Hanno Becker2c2722d2020-10-09 09:36:23 +0100452#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100453/*
454 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100455 * about the certificates from provided data.
456 *
457 * /p ssl pointer to serialized certificate
458 * /p len number of bytes in the buffer
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 */
460void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100461{
462 enum { STRLEN = 4096 };
463 mbedtls_x509_crt crt;
464 int ret;
465 char str[STRLEN];
466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 printf("\nCertificate:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 mbedtls_x509_crt_init(&crt);
470 ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
471 if (0 != ret) {
472 mbedtls_strerror(ret, str, STRLEN);
473 printf_err("Invalid format of X.509 - %s\n", str);
474 printf("Cannot deserialize:\n\t");
475 print_hex(ssl, len, 25, "\t");
476 } else {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100477 mbedtls_x509_crt *current = &crt;
478
Gilles Peskine449bd832023-01-11 14:50:10 +0100479 while (current != NULL) {
480 ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
481 if (0 > ret) {
482 mbedtls_strerror(ret, str, STRLEN);
483 printf_err("Cannot write to the output - %s\n", str);
484 } else {
485 printf("%s", str);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100486 }
487
488 current = current->next;
489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 if (current) {
491 printf("\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100492 }
493
494 }
495 }
496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 mbedtls_x509_crt_free(&crt);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100498}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100499#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100500
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100526void print_deserialized_ssl_session(const uint8_t *ssl, uint32_t len,
527 int session_cfg_flag)
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100528{
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 printf("\nSession info:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100536
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100538 uint64_t start;
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 printf("\tstart time : ");
550 print_time(&start);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100551 }
552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
559 if (ciphersuite_info == NULL) {
560 printf_err("Cannot find ciphersuite info\n");
561 } else {
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
Gilles Peskine449bd832023-01-11 14:50:10 +0100566 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
Valerio Settidc554702023-10-27 12:12:53 +0200569#if defined(MBEDTLS_CIPHER_C)
570 const mbedtls_cipher_info_t *cipher_info;
Gilles Peskine449bd832023-01-11 14:50:10 +0100571 cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
572 if (cipher_info == NULL) {
573 printf_err("Cannot find cipher info\n");
574 } else {
575 printf("\tcipher : %s\n", cipher_info->name);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100576 }
Valerio Settidc554702023-10-27 12:12:53 +0200577#else /* MBEDTLS_CIPHER_C */
578 printf("\tcipher type : %d\n", ciphersuite_info->cipher);
579#endif /* MBEDTLS_CIPHER_C */
580
Andrzej Kurek8c95ac42022-08-17 16:17:00 -0400581#if defined(MBEDTLS_MD_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100582 md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
583 if (md_info == NULL) {
584 printf_err("Cannot find Message-Digest info\n");
585 } else {
586 printf("\tMessage-Digest : %s\n", mbedtls_md_get_name(md_info));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100587 }
Andrzej Kurekcccb0442022-08-19 03:42:11 -0400588#endif /* MBEDTLS_MD_C */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100589 }
590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 CHECK_SSL_END(1);
592 printf("\tcompression : %s\n", get_enabled_str(*ssl++));
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100593
594 /* Note - Here we can get session ID length from serialized data, but we
595 * use hardcoded 32-bytes length. This approach was taken from
596 * 'mbedtls_ssl_session_load()'. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 CHECK_SSL_END(1 + 32);
598 printf_dbg("Session id length: %u\n", (uint32_t) *ssl++);
599 printf("\tsession ID : ");
600 print_hex(ssl, 32, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100601 ssl += 32;
602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 printf("\tmaster secret : ");
604 CHECK_SSL_END(48);
605 print_hex(ssl, 48, 16, "\t ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100606 ssl += 48;
607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 CHECK_SSL_END(4);
609 verify_result = ((uint32_t) ssl[0] << 24) |
610 ((uint32_t) ssl[1] << 16) |
611 ((uint32_t) ssl[2] << 8) |
612 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100613 ssl += 4;
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 printf("\tverify result : 0x%08X\n", verify_result);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100615
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
617 if (conf_keep_peer_certificate) {
618 CHECK_SSL_END(3);
619 cert_len = ((uint32_t) ssl[0] << 16) |
620 ((uint32_t) ssl[1] << 8) |
621 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100622 ssl += 3;
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 printf_dbg("Certificate length: %u\n", cert_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100624
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 if (cert_len > 0) {
626 CHECK_SSL_END(cert_len);
Hanno Becker2c2722d2020-10-09 09:36:23 +0100627#if !defined(MBEDTLS_X509_REMOVE_INFO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 print_deserialized_ssl_cert(ssl, cert_len);
Hanno Becker2c2722d2020-10-09 09:36:23 +0100629#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100630 ssl += cert_len;
631 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 } else {
633 printf("\tPeer digest : ");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100634
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 CHECK_SSL_END(1);
636 switch ((mbedtls_md_type_t) *ssl++) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100637 case MBEDTLS_MD_NONE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100639 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100640 case MBEDTLS_MD_MD5:
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 printf("MD5\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100642 break;
643 case MBEDTLS_MD_SHA1:
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 printf("SHA1\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100645 break;
646 case MBEDTLS_MD_SHA224:
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 printf("SHA224\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100648 break;
649 case MBEDTLS_MD_SHA256:
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 printf("SHA256\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100651 break;
652 case MBEDTLS_MD_SHA384:
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 printf("SHA384\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100654 break;
655 case MBEDTLS_MD_SHA512:
Gilles Peskine449bd832023-01-11 14:50:10 +0100656 printf("SHA512\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100657 break;
658 case MBEDTLS_MD_RIPEMD160:
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 printf("RIPEMD160\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100660 break;
661 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 printf("undefined or erroneous\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100663 break;
664 }
665
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100667 cert_len = (uint32_t) *ssl++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 printf_dbg("Message-Digest length: %u\n", cert_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100669
Gilles Peskine449bd832023-01-11 14:50:10 +0100670 if (cert_len > 0) {
671 printf("\tPeer digest cert : ");
672 CHECK_SSL_END(cert_len);
673 print_hex(ssl, cert_len, 16, "\t ");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100674 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100675 }
676 }
677 }
678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
680 printf("\nTicket:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100681
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 CHECK_SSL_END(3);
683 ticket_len = ((uint32_t) ssl[0] << 16) |
684 ((uint32_t) ssl[1] << 8) |
685 ((uint32_t) ssl[2]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100686 ssl += 3;
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 printf_dbg("Ticket length: %u\n", ticket_len);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100688
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 if (ticket_len > 0) {
690 printf("\t");
691 CHECK_SSL_END(ticket_len);
692 print_hex(ssl, ticket_len, 22, "\t");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100693 ssl += ticket_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100694 printf("\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100695 }
696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 CHECK_SSL_END(4);
698 ticket_lifetime = ((uint32_t) ssl[0] << 24) |
699 ((uint32_t) ssl[1] << 16) |
700 ((uint32_t) ssl[2] << 8) |
701 ((uint32_t) ssl[3]);
Piotr Nowicki4e192002020-03-18 17:27:29 +0100702 ssl += 4;
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 printf("\tlifetime : %u sec.\n", ticket_lifetime);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100704 }
705
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 if (ssl < end) {
707 printf("\nSession others:\n");
Piotr Nowicki4e192002020-03-18 17:27:29 +0100708 }
709
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
711 CHECK_SSL_END(1);
712 printf("\tMFL : %s\n", get_mfl_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100713 }
714
Gilles Peskine449bd832023-01-11 14:50:10 +0100715 if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
716 CHECK_SSL_END(1);
717 printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100718 }
719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
721 CHECK_SSL_END(1);
722 printf("\tEncrypt-then-MAC : %s\n", get_enabled_str(*ssl++));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100723 }
724
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 if (0 != (end - ssl)) {
726 printf_err("%i bytes left to analyze from session\n", (int32_t) (end - ssl));
Piotr Nowicki4e192002020-03-18 17:27:29 +0100727 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100728}
729
730/*
731 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100732 * about the context from provided data. This function was built based on
733 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
734 * due to dependencies on the mbedTLS configuration and the configuration of
735 * the context when serialization was created.
736 *
737 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200738 * // header
739 * uint8 version[3];
740 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100741 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200742 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100743 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
744 * // transform sub-structure
745 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200746 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100747 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200748 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100749 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
750 * // fields from ssl_context
751 * uint32 badmac_seen; // DTLS: number of records with failing MAC
752 * uint64 in_window_top; // DTLS: last validated record seq_num
753 * uint64 in_window; // DTLS: bitmask for replay protection
754 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
755 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
756 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200757 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100758 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
759 *
760 * /p ssl pointer to serialized session
761 * /p len number of bytes in the buffer
762 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100763void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100764{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100765 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100766 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100767 int session_cfg_flag;
768 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100769
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 printf("\nMbed TLS version:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100771
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 CHECK_SSL_END(3 + 2 + 3);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100773
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 printf("\tmajor %u\n", (uint32_t) *ssl++);
775 printf("\tminor %u\n", (uint32_t) *ssl++);
776 printf("\tpath %u\n", (uint32_t) *ssl++);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100777
Gilles Peskine449bd832023-01-11 14:50:10 +0100778 printf("\nEnabled session and context configuration:\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100779
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 session_cfg_flag = ((int) ssl[0] << 8) | ((int) ssl[1]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100781 ssl += 2;
782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 context_cfg_flag = ((int) ssl[0] << 16) |
784 ((int) ssl[1] << 8) |
785 ((int) ssl[2]);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100786 ssl += 3;
787
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
789 printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100790
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag);
792 print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag);
793 print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag);
794 print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag);
795 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag);
796 print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
797 SESSION_CONFIG_CLIENT_TICKET_BIT,
798 session_cfg_flag);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100799
Gilles Peskine449bd832023-01-11 14:50:10 +0100800 print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
801 CONTEXT_CONFIG_DTLS_CONNECTION_ID_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
Gilles Peskine449bd832023-01-11 14:50:10 +0100808 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100814 printf_dbg("Session length %u\n", session_len);
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100815
Gilles Peskine449bd832023-01-11 14:50:10 +0100816 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 printf("\nRandom bytes:\n\t");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100821
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100826 printf("\nContext others:\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100827
Gilles Peskine449bd832023-01-11 14:50:10 +0100828 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100832 cid_len = *ssl++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 printf_dbg("In CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100834
Gilles Peskine449bd832023-01-11 14:50:10 +0100835 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100840 } else {
841 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100842 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100843
Gilles Peskine449bd832023-01-11 14:50:10 +0100844 CHECK_SSL_END(1);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100845 cid_len = *ssl++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100846 printf_dbg("Out CID length %u\n", (uint32_t) cid_len);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100847
Gilles Peskine449bd832023-01-11 14:50:10 +0100848 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100853 } else {
854 printf("none\n");
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100855 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100856 }
857
Gilles Peskine449bd832023-01-11 14:50:10 +0100858 if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100859 uint32_t badmac_seen;
860
Gilles Peskine449bd832023-01-11 14:50:10 +0100861 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100867 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100870 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100876 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100882 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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100889 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100894 if (conf_dtls_proto) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100895 uint16_t mtu;
Gilles Peskine449bd832023-01-11 14:50:10 +0100896 CHECK_SSL_END(2);
897 mtu = (ssl[0] << 8) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898 ssl += 2;
Gilles Peskine449bd832023-01-11 14:50:10 +0100899 printf("\tMTU : %u\n", mtu);
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100900 }
901
902
Gilles Peskine449bd832023-01-11 14:50:10 +0100903 if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100904 uint8_t alpn_len;
905
Gilles Peskine449bd832023-01-11 14:50:10 +0100906 CHECK_SSL_END(1);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100907 alpn_len = *ssl++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100908 printf_dbg("ALPN length %u\n", (uint32_t) alpn_len);
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100909
Gilles Peskine449bd832023-01-11 14:50:10 +0100910 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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100920 } else {
921 printf("not selected\n");
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100922 }
923 }
924
Gilles Peskine449bd832023-01-11 14:50:10 +0100925 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 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 printf("\n");
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100929}
930
Gilles Peskine449bd832023-01-11 14:50:10 +0100931int 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
Przemek Stekiel89c636e2023-04-14 09:26:39 +0200942#if defined(MBEDTLS_USE_PSA_CRYPTO)
943 psa_status_t status = psa_crypto_init();
944 if (status != PSA_SUCCESS) {
945 mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
946 (int) status);
947 return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
948 }
949#endif /* MBEDTLS_USE_PSA_CRYPTO */
950
Gilles Peskine449bd832023-01-11 14:50:10 +0100951 /* The 'b64_file' is opened when parsing arguments to check that the
952 * file name is correct */
953 parse_arguments(argc, argv);
Piotr Nowicki9370f902020-03-13 14:43:22 +0100954
Gilles Peskine449bd832023-01-11 14:50:10 +0100955 if (NULL != b64_file) {
956 b64_buf = malloc(SSL_INIT_LEN);
957 ssl_buf = malloc(SSL_INIT_LEN);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200958
Gilles Peskine449bd832023-01-11 14:50:10 +0100959 if (NULL == b64_buf || NULL == ssl_buf) {
960 printf_err(alloc_err);
961 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200962 b64_file = NULL;
963 }
964 }
965
Gilles Peskine449bd832023-01-11 14:50:10 +0100966 while (NULL != b64_file) {
967 size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
968 if (b64_len > 0) {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100969 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200970 size_t ssl_required_len = b64_len * 3 / 4 + 1;
971
972 /* Allocate more memory if necessary. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100973 if (ssl_required_len > ssl_max_len) {
974 void *ptr = realloc(ssl_buf, ssl_required_len);
975 if (NULL == ptr) {
976 printf_err(alloc_err);
977 fclose(b64_file);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200978 b64_file = NULL;
979 break;
980 }
981 ssl_buf = ptr;
982 ssl_max_len = ssl_required_len;
983 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100984
Gilles Peskine449bd832023-01-11 14:50:10 +0100985 printf("\nDeserializing number %u:\n", ++b64_counter);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100986
Gilles Peskine449bd832023-01-11 14:50:10 +0100987 printf("\nBase64 code:\n");
988 print_b64(b64_buf, b64_len);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100989
Gilles Peskine449bd832023-01-11 14:50:10 +0100990 ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len);
991 if (ret != 0) {
992 mbedtls_strerror(ret, (char *) b64_buf, b64_max_len);
993 printf_err("base64 code cannot be decoded - %s\n", b64_buf);
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100994 continue;
995 }
996
Gilles Peskine449bd832023-01-11 14:50:10 +0100997 if (debug) {
998 printf("\nDecoded data in hex:\n\t");
999 print_hex(ssl_buf, ssl_len, 25, "\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001000 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001001
Gilles Peskine449bd832023-01-11 14:50:10 +01001002 print_deserialized_ssl_context(ssl_buf, ssl_len);
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001003
Gilles Peskine449bd832023-01-11 14:50:10 +01001004 } else {
1005 fclose(b64_file);
Piotr Nowicki14d31052020-03-16 14:05:22 +01001006 b64_file = NULL;
1007 }
1008 }
1009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 free(b64_buf);
1011 free(ssl_buf);
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001012
Gilles Peskine449bd832023-01-11 14:50:10 +01001013 if (b64_counter > 0) {
1014 printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
1015 } else {
1016 printf("Finished. No valid base64 code found\n");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001017 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001018
Przemek Stekiel758aef62023-04-19 13:47:43 +02001019#if defined(MBEDTLS_USE_PSA_CRYPTO)
Przemek Stekiela8c560a2023-04-19 10:15:26 +02001020 mbedtls_psa_crypto_free();
Przemek Stekiel758aef62023-04-19 13:47:43 +02001021#endif /* MBEDTLS_USE_PSA_CRYPTO */
Przemek Stekiela8c560a2023-04-19 10:15:26 +02001022
Piotr Nowicki9370f902020-03-13 14:43:22 +01001023 return 0;
1024}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001025
1026#endif /* MBEDTLS_X509_CRT_PARSE_C */