blob: bc9c6bd522145a66fc5cfa7d28131e86cf618f3b [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
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020022#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
Piotr Nowickif86192f2020-03-26 11:45:42 +010026#endif
27
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010028#include <stdio.h>
29#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020030
Gilles Peskinef4a6a052020-11-09 14:55:35 +010031#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
32 !defined(MBEDTLS_SSL_TLS_C)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020033int main( void )
34{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010035 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
36 "MBEDTLS_SSL_TLS_C not defined.\n");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020037 return( 0 );
38}
39#else
40
41#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
42#define _CRT_SECURE_NO_DEPRECATE 1
43#endif
44
Piotr Nowicki14d31052020-03-16 14:05:22 +010045#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010046#include <stdarg.h>
47#include <string.h>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010048#include <time.h>
49#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 */
66#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 )
73
74#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 )
78
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 */
92#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
93#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
94
95#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 )
98
99#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
100#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
101
102/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100103 * A macro that prevents from reading out of the ssl buffer range.
104 */
105#define CHECK_SSL_END( LEN ) \
106do \
107{ \
108 if( end - ssl < (int)( LEN ) ) \
109 { \
110 printf_err( "%s", buf_ln_err ); \
111 return; \
112 } \
113} while( 0 )
114
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 */
128void print_version( )
129{
130 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
131}
132
133void print_usage( )
134{
135 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200136 printf( "\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100137 "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"
152 );
153}
154
155void printf_dbg( const char *str, ... )
156{
157 if( debug )
158 {
159 va_list args;
160 va_start( args, str );
161 printf( "debug: " );
162 vprintf( str, args );
163 fflush( stdout );
164 va_end( args );
165 }
166}
167
168void printf_err( const char *str, ... )
169{
170 va_list args;
171 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100172 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100173 fprintf( stderr, "ERROR: " );
174 vfprintf( stderr, str, args );
175 fflush( stderr );
176 va_end( args );
177}
178
179/*
180 * Exit from the program in case of error
181 */
182void error_exit()
183{
184 if( NULL != b64_file )
185 {
186 fclose( b64_file );
187 }
188 exit( -1 );
189}
190
191/*
192 * This function takes the input arguments of this program
193 */
194void parse_arguments( int argc, char *argv[] )
195{
196 int i = 1;
197
198 if( argc < 2 )
199 {
200 print_usage();
201 error_exit();
202 }
203
204 while( i < argc )
205 {
206 if( strcmp( argv[i], "-d" ) == 0 )
207 {
208 debug = 1;
209 }
210 else if( strcmp( argv[i], "-h" ) == 0 )
211 {
212 print_usage();
213 }
214 else if( strcmp( argv[i], "-v" ) == 0 )
215 {
216 print_version();
217 }
218 else if( strcmp( argv[i], "-f" ) == 0 )
219 {
220 if( ++i >= argc )
221 {
222 printf_err( "File path is empty\n" );
223 error_exit();
224 }
225
226 if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
227 {
228 printf_err( "Cannot find file \"%s\"\n", argv[i] );
229 error_exit();
230 }
231 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100232 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
233 {
234 conf_keep_peer_certificate = 0;
235 }
236 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
237 {
238 conf_dtls_proto = 0;
239 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100240 else
241 {
242 print_usage();
243 error_exit();
244 }
245
246 i++;
247 }
248}
249
Piotr Nowicki14d31052020-03-16 14:05:22 +0100250/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100251 * This function prints base64 code to the stdout
252 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100253void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100254{
255 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100256 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100257 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100258 while( b < end )
259 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100260 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100261 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100262 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100263 i = 0;
264 }
265 printf( "%c", *b++ );
266 }
267 printf( "\n" );
268 fflush( stdout );
269}
270
271/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100272 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100273 *
274 * /p b buffer with data to print
275 * /p len number of bytes to print
276 * /p in_line number of bytes in one line
277 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100278 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100279void print_hex( const uint8_t *b, size_t len,
280 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100281{
282 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100283 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100284
285 if( prefix == NULL )
286 {
287 prefix = "";
288 }
289
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100290 while( b < end )
291 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100292 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100293 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100294 printf( "\n%s", prefix );
295 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100296 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100297 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100298 }
299 printf("\n");
300 fflush(stdout);
301}
302
303/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100304 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
305 */
306void print_time( const time_t *time )
307{
308 char buf[20];
309 struct tm *t = gmtime( time );
310 static const char format[] = "%Y-%m-%d %H:%M:%S";
311 if( NULL != t )
312 {
313 strftime( buf, sizeof( buf ), format, t );
314 printf( "%s\n", buf );
315 }
316 else
317 {
318 printf( "unknown\n" );
319 }
320}
321
322/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100323 * Print the input string if the bit is set in the value
324 */
325void print_if_bit( const char *str, int bit, int val )
326{
327 if( bit & val )
328 {
329 printf( "\t%s\n", str );
330 }
331}
332
333/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100334 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
335 */
336const char * get_enabled_str( int is_en )
337{
338 return ( is_en ) ? "enabled" : "disabled";
339}
340
341/*
342 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
343 */
344const char * get_mfl_str( int mfl_code )
345{
346 switch( mfl_code )
347 {
348 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
349 return "none";
350 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
351 return "512";
352 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
353 return "1024";
354 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
355 return "2048";
356 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
357 return "4096";
358 default:
359 return "error";
360 }
361}
362
363/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100364 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
365 * previously. After each call to this function, the internal file position
366 * indicator of the global b64_file is advanced.
367 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200368 * Note - This function checks the size of the input buffer and if necessary,
369 * increases it to the maximum MAX_BASE64_LEN
370 *
371 * /p b64 pointer to the pointer of the buffer for input data
372 * /p max_len pointer to the current buffer capacity. It can be changed if
373 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100374 *
375 * \retval number of bytes written in to the b64 buffer or 0 in case no more
376 * data was found
377 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200378size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100379{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200380 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100381 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100382 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000383 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100384
385 while( EOF != c )
386 {
387 char c_valid = 0;
388
Nayna Jaind696e7d2020-08-13 19:17:53 +0000389 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100390
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200391 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100392 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200393 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100394 {
395 c_valid = 1;
396 pad = 2;
397 }
398 }
399 else if( ( c >= 'A' && c <= 'Z' ) ||
400 ( c >= 'a' && c <= 'z' ) ||
401 ( c >= '0' && c <= '9' ) ||
402 c == '+' || c == '/' )
403 {
404 c_valid = 1;
405 }
406 else if( c == '=' )
407 {
408 c_valid = 1;
409 pad = 1;
410 }
411 else if( c == '-' )
412 {
413 c = '+';
414 c_valid = 1;
415 }
416 else if( c == '_' )
417 {
418 c = '/';
419 c_valid = 1;
420 }
421
422 if( c_valid )
423 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200424 /* A string of characters that could be a base64 code. */
425 valid_balance++;
426
427 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100428 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200429 ( *b64 )[ len++ ] = c;
430 }
431 else if( *max_len < MAX_BASE64_LEN )
432 {
433 /* Current buffer is too small, but can be resized. */
434 void *ptr;
435 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
436 *max_len + 4096 : MAX_BASE64_LEN;
437
438 ptr = realloc( *b64, new_size );
439 if( NULL == ptr )
440 {
441 printf_err( alloc_err );
442 return 0;
443 }
444 *b64 = ptr;
445 *max_len = new_size;
446 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100447 }
448 else
449 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200450 /* Too much data so it will be treated as invalid */
451 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100452 }
453 }
454 else if( len > 0 )
455 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200456 /* End of a string that could be a base64 code, but need to check
457 * that the length of the characters is correct. */
458
459 valid_balance--;
460
461 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100462 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200463 printf_dbg( "The code found is too small to be a SSL context.\n" );
464 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100465 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200466 else if( len > *max_len )
467 {
468 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
469 len = pad = 0;
470 }
471 else if( len % 4 != 0 )
472 {
473 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
474 len = pad = 0;
475 }
476 else
477 {
478 /* Base64 code with valid character length. */
479 return len;
480 }
481 }
482 else
483 {
484 valid_balance--;
485 }
486
487 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
488 if( valid_balance < -100 )
489 {
490 printf_err( "Too many bad symbols detected. File check aborted.\n" );
491 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100492 }
493 }
494
495 printf_dbg( "End of file\n" );
496 return 0;
497}
498
Hanno Becker2c2722d2020-10-09 09:36:23 +0100499#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100500/*
501 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100502 * about the certificates from provided data.
503 *
504 * /p ssl pointer to serialized certificate
505 * /p len number of bytes in the buffer
506*/
507void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
508{
509 enum { STRLEN = 4096 };
510 mbedtls_x509_crt crt;
511 int ret;
512 char str[STRLEN];
513
514 printf( "\nCertificate:\n" );
515
516 mbedtls_x509_crt_init( &crt );
517 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
518 if( 0 != ret )
519 {
520 mbedtls_strerror( ret, str, STRLEN );
521 printf_err( "Invalid format of X.509 - %s\n", str );
522 printf( "Cannot deserialize:\n\t" );
523 print_hex( ssl, len, 25, "\t" );
524 }
525 else
526 {
527 mbedtls_x509_crt *current = &crt;
528
529 while( current != NULL )
530 {
531 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
532 if( 0 > ret )
533 {
534 mbedtls_strerror( ret, str, STRLEN );
535 printf_err( "Cannot write to the output - %s\n", str );
536 }
537 else
538 {
539 printf( "%s", str );
540 }
541
542 current = current->next;
543
544 if( current )
545 {
546 printf( "\n" );
547 }
548
549 }
550 }
551
552 mbedtls_x509_crt_free( &crt );
553}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100554#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100555
556/*
557 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100558 * about the session from provided data. This function was built based on
559 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
560 * due to dependencies on the mbedTLS configuration.
561 *
562 * The data structure in the buffer:
563 * uint64 start_time;
564 * uint8 ciphersuite[2]; // defined by the standard
565 * uint8 compression; // 0 or 1
566 * uint8 session_id_len; // at most 32
567 * opaque session_id[32];
568 * opaque master[48]; // fixed length in the standard
569 * uint32 verify_result;
570 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
571 * opaque ticket<0..2^24-1>; // length 0 means no ticket
572 * uint32 ticket_lifetime;
573 * uint8 mfl_code; // up to 255 according to standard
574 * uint8 trunc_hmac; // 0 or 1
575 * uint8 encrypt_then_mac; // 0 or 1
576 *
577 * /p ssl pointer to serialized session
578 * /p len number of bytes in the buffer
579 * /p session_cfg_flag session configuration flags
580 */
581void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
582 int session_cfg_flag )
583{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100584 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
585 int ciphersuite_id;
586 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100587 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100588 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100589
590 printf( "\nSession info:\n" );
591
592 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
593 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100594 uint64_t start;
595 CHECK_SSL_END( 8 );
596 start = ( (uint64_t) ssl[0] << 56 ) |
597 ( (uint64_t) ssl[1] << 48 ) |
598 ( (uint64_t) ssl[2] << 40 ) |
599 ( (uint64_t) ssl[3] << 32 ) |
600 ( (uint64_t) ssl[4] << 24 ) |
601 ( (uint64_t) ssl[5] << 16 ) |
602 ( (uint64_t) ssl[6] << 8 ) |
603 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100604 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100605 printf( "\tstart time : " );
606 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607 }
608
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100609 CHECK_SSL_END( 2 );
610 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
611 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100612 ssl += 2;
613
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100614 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
615 if( ciphersuite_info == NULL )
616 {
617 printf_err( "Cannot find ciphersuite info\n" );
618 }
619 else
620 {
621 const mbedtls_cipher_info_t *cipher_info;
622 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100623
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100624 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
625 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
626
627 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
628 if( cipher_info == NULL )
629 {
630 printf_err( "Cannot find cipher info\n" );
631 }
632 else
633 {
634 printf( "\tcipher : %s\n", cipher_info->name );
635 }
636
637 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
638 if( md_info == NULL )
639 {
640 printf_err( "Cannot find Message-Digest info\n" );
641 }
642 else
643 {
Chris Jonesa1df4942021-03-11 17:44:43 +0000644 printf( "\tMessage-Digest : %s\n", mbedtls_md_get_name( md_info ) );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100645 }
646 }
647
648 CHECK_SSL_END( 1 );
649 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
650
651 /* Note - Here we can get session ID length from serialized data, but we
652 * use hardcoded 32-bytes length. This approach was taken from
653 * 'mbedtls_ssl_session_load()'. */
654 CHECK_SSL_END( 1 + 32 );
655 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
656 printf( "\tsession ID : ");
657 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100658 ssl += 32;
659
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100660 printf( "\tmaster secret : ");
661 CHECK_SSL_END( 48 );
662 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100663 ssl += 48;
664
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100665 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100666 verify_result = ( (uint32_t) ssl[0] << 24 ) |
667 ( (uint32_t) ssl[1] << 16 ) |
668 ( (uint32_t) ssl[2] << 8 ) |
669 ( (uint32_t) ssl[3] );
670 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100671 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100672
673 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
674 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100675 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100676 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100677 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100678 cert_len = ( (uint32_t) ssl[0] << 16 ) |
679 ( (uint32_t) ssl[1] << 8 ) |
680 ( (uint32_t) ssl[2] );
681 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100682 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100683
684 if( cert_len > 0 )
685 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100686 CHECK_SSL_END( cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100687#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100688 print_deserialized_ssl_cert( ssl, cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100689#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100690 ssl += cert_len;
691 }
692 }
693 else
694 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100695 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100696
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100697 CHECK_SSL_END( 1 );
698 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100699 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100700 case MBEDTLS_MD_NONE:
701 printf( "none\n" );
702 break;
703 case MBEDTLS_MD_MD2:
704 printf( "MD2\n" );
705 break;
706 case MBEDTLS_MD_MD4:
707 printf( "MD4\n" );
708 break;
709 case MBEDTLS_MD_MD5:
710 printf( "MD5\n" );
711 break;
712 case MBEDTLS_MD_SHA1:
713 printf( "SHA1\n" );
714 break;
715 case MBEDTLS_MD_SHA224:
716 printf( "SHA224\n" );
717 break;
718 case MBEDTLS_MD_SHA256:
719 printf( "SHA256\n" );
720 break;
721 case MBEDTLS_MD_SHA384:
722 printf( "SHA384\n" );
723 break;
724 case MBEDTLS_MD_SHA512:
725 printf( "SHA512\n" );
726 break;
727 case MBEDTLS_MD_RIPEMD160:
728 printf( "RIPEMD160\n" );
729 break;
730 default:
731 printf( "undefined or erroneous\n" );
732 break;
733 }
734
735 CHECK_SSL_END( 1 );
736 cert_len = (uint32_t) *ssl++;
737 printf_dbg( "Message-Digest length: %u\n", cert_len );
738
739 if( cert_len > 0 )
740 {
741 printf( "\tPeer digest cert : " );
742 CHECK_SSL_END( cert_len );
743 print_hex( ssl, cert_len, 16, "\t " );
744 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100745 }
746 }
747 }
748
749 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
750 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100751 printf( "\nTicket:\n" );
752
753 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100754 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
755 ( (uint32_t) ssl[1] << 8 ) |
756 ( (uint32_t) ssl[2] );
757 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100758 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100759
760 if( ticket_len > 0 )
761 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100762 printf( "\t" );
763 CHECK_SSL_END( ticket_len );
764 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100765 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100766 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100767 }
768
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100769 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100770 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
771 ( (uint32_t) ssl[1] << 16 ) |
772 ( (uint32_t) ssl[2] << 8 ) |
773 ( (uint32_t) ssl[3] );
774 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100775 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
776 }
777
778 if( ssl < end )
779 {
780 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100781 }
782
783 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
784 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100785 CHECK_SSL_END( 1 );
786 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100787 }
788
789 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
790 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100791 CHECK_SSL_END( 1 );
792 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100793 }
794
795 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
796 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100797 CHECK_SSL_END( 1 );
798 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100799 }
800
801 if( 0 != ( end - ssl ) )
802 {
803 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
804 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100805}
806
807/*
808 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100809 * about the context from provided data. This function was built based on
810 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
811 * due to dependencies on the mbedTLS configuration and the configuration of
812 * the context when serialization was created.
813 *
814 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200815 * // header
816 * uint8 version[3];
817 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100818 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200819 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100820 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
821 * // transform sub-structure
822 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200823 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100824 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200825 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100826 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
827 * // fields from ssl_context
828 * uint32 badmac_seen; // DTLS: number of records with failing MAC
829 * uint64 in_window_top; // DTLS: last validated record seq_num
830 * uint64 in_window; // DTLS: bitmask for replay protection
831 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
832 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
833 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200834 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100835 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
836 *
837 * /p ssl pointer to serialized session
838 * /p len number of bytes in the buffer
839 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100840void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100841{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100842 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100843 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100844 int session_cfg_flag;
845 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100846
847 printf( "\nMbed TLS version:\n" );
848
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100849 CHECK_SSL_END( 3 + 2 + 3 );
850
851 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
852 printf( "\tminor %u\n", (uint32_t) *ssl++ );
853 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100854
855 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100856
857 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
858 ssl += 2;
859
860 context_cfg_flag = ( (int) ssl[0] << 16 ) |
861 ( (int) ssl[1] << 8 ) |
862 ( (int) ssl[2] ) ;
863 ssl += 3;
864
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100865 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
866 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
867
868 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
869 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
870 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
871 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
872 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
873 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
874 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
875
876 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
877 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
878 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
879 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
880
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100881 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100882 session_len = ( (uint32_t) ssl[0] << 24 ) |
883 ( (uint32_t) ssl[1] << 16 ) |
884 ( (uint32_t) ssl[2] << 8 ) |
885 ( (uint32_t) ssl[3] );
886 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100887 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100888
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100889 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100890 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
891 ssl += session_len;
892
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100893 printf( "\nRandom bytes:\n\t");
894
895 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
896 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100897 ssl += TRANSFORM_RANDBYTE_LEN;
898
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100899 printf( "\nContext others:\n" );
900
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100901 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
902 {
903 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100904
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100905 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100906 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100907 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100908
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100909 printf( "\tin CID : " );
910 if( cid_len > 0 )
911 {
912 CHECK_SSL_END( cid_len );
913 print_hex( ssl, cid_len, 20, "\t" );
914 ssl += cid_len;
915 }
916 else
917 {
918 printf( "none\n" );
919 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100920
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100921 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100922 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100923 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100924
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100925 printf( "\tout CID : " );
926 if( cid_len > 0 )
927 {
928 CHECK_SSL_END( cid_len );
929 print_hex( ssl, cid_len, 20, "\t" );
930 ssl += cid_len;
931 }
932 else
933 {
934 printf( "none\n" );
935 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100936 }
937
938 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
939 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100940 uint32_t badmac_seen;
941
942 CHECK_SSL_END( 4 );
943 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
944 ( (uint32_t) ssl[1] << 16 ) |
945 ( (uint32_t) ssl[2] << 8 ) |
946 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100947 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100948 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100949
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100950 /* value 'in_window_top' from mbedtls_ssl_context */
951 printf( "\tlast validated record sequence no. : " );
952 CHECK_SSL_END( 8 );
953 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100954 ssl += 8;
955
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100956 /* value 'in_window' from mbedtls_ssl_context */
957 printf( "\tbitmask for replay detection : " );
958 CHECK_SSL_END( 8 );
959 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100960 ssl += 8;
961 }
962
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100963 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100964 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100965 CHECK_SSL_END( 1 );
966 printf( "\tDTLS datagram packing : %s\n",
967 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100968 }
969
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100970 /* value 'cur_out_ctr' from mbedtls_ssl_context */
971 printf( "\toutgoing record sequence no. : ");
972 CHECK_SSL_END( 8 );
973 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100974 ssl += 8;
975
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100976 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100977 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100978 uint16_t mtu;
979 CHECK_SSL_END( 2 );
980 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100981 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100982 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100983 }
984
985
986 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
987 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100988 uint8_t alpn_len;
989
990 CHECK_SSL_END( 1 );
991 alpn_len = *ssl++;
992 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
993
994 printf( "\tALPN negotiation : " );
995 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100996 if( alpn_len > 0 )
997 {
998 if( strlen( (const char*) ssl ) == alpn_len )
999 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001000 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001001 }
1002 else
1003 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001004 printf( "\n" );
1005 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001006 }
1007 ssl += alpn_len;
1008 }
1009 else
1010 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001011 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001012 }
1013 }
1014
Piotr Nowicki4e192002020-03-18 17:27:29 +01001015 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001016 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001017 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001018 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001019 printf( "\n" );
1020}
1021
Piotr Nowicki9370f902020-03-13 14:43:22 +01001022int main( int argc, char *argv[] )
1023{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001024 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001025
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001026 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001027 uint8_t *b64_buf = NULL;
1028 uint8_t *ssl_buf = NULL;
1029 size_t b64_max_len = SSL_INIT_LEN;
1030 size_t ssl_max_len = SSL_INIT_LEN;
1031 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001032
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001033 /* The 'b64_file' is opened when parsing arguments to check that the
1034 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001035 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001036
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001037 if( NULL != b64_file )
1038 {
1039 b64_buf = malloc( SSL_INIT_LEN );
1040 ssl_buf = malloc( SSL_INIT_LEN );
1041
1042 if( NULL == b64_buf || NULL == ssl_buf )
1043 {
1044 printf_err( alloc_err );
1045 fclose( b64_file );
1046 b64_file = NULL;
1047 }
1048 }
1049
Piotr Nowicki14d31052020-03-16 14:05:22 +01001050 while( NULL != b64_file )
1051 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001052 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001053 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001054 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001055 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001056 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1057
1058 /* Allocate more memory if necessary. */
1059 if( ssl_required_len > ssl_max_len )
1060 {
1061 void *ptr = realloc( ssl_buf, ssl_required_len );
1062 if( NULL == ptr )
1063 {
1064 printf_err( alloc_err );
1065 fclose( b64_file );
1066 b64_file = NULL;
1067 break;
1068 }
1069 ssl_buf = ptr;
1070 ssl_max_len = ssl_required_len;
1071 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001072
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001073 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001074
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001075 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001076 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001077
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001078 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001079 if( ret != 0)
1080 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001081 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1082 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001083 continue;
1084 }
1085
1086 if( debug )
1087 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001088 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001089 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001090 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001091
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001092 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001093
Piotr Nowicki14d31052020-03-16 14:05:22 +01001094 }
1095 else
1096 {
1097 fclose( b64_file );
1098 b64_file = NULL;
1099 }
1100 }
1101
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001102 free( b64_buf );
1103 free( ssl_buf );
1104
1105 if( b64_counter > 0 )
1106 {
1107 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1108 }
1109 else
1110 {
1111 printf( "Finished. No valid base64 code found\n" );
1112 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001113
Piotr Nowicki9370f902020-03-13 14:43:22 +01001114 return 0;
1115}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001116
1117#endif /* MBEDTLS_X509_CRT_PARSE_C */