blob: 999bfe89b2937deeb3875682e15b996a152bdd76 [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
2 * MbedTLS SSL context deserializer from base64 code
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Piotr Nowicki9370f902020-03-13 14:43:22 +01005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Piotr Nowicki9370f902020-03-13 14:43:22 +010018 */
19
Mateusz Starzyk6c2e9b62021-05-19 17:54:54 +020020#define MBEDTLS_ALLOW_PRIVATE_ACCESS
21
Bence Szépkútic662b362021-05-27 11:25:03 +020022#include "mbedtls/build_info.h"
Piotr Nowickif86192f2020-03-26 11:45:42 +010023
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010024#include <stdio.h>
25#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020026
Gilles Peskinef4a6a052020-11-09 14:55:35 +010027#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
28 !defined(MBEDTLS_SSL_TLS_C)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020029int main( void )
30{
Gilles Peskinef4a6a052020-11-09 14:55:35 +010031 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
32 "MBEDTLS_SSL_TLS_C not defined.\n");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020033 return( 0 );
34}
35#else
36
37#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
38#define _CRT_SECURE_NO_DEPRECATE 1
39#endif
40
Piotr Nowicki14d31052020-03-16 14:05:22 +010041#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010042#include <stdarg.h>
43#include <string.h>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010044#include <time.h>
45#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010046#include "mbedtls/error.h"
47#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010048#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010049#include "mbedtls/x509_crt.h"
50#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010051
52/*
53 * This program version
54 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010055#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010056#define VER_MAJOR 0
57#define VER_MINOR 1
58
59/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020060 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010061 */
62#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
63#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
64#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
65#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
66#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
67#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
68#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
69
70#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
71#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
72#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
73#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
74
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010075#define TRANSFORM_RANDBYTE_LEN 64
76
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010077/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020078 * Minimum and maximum number of bytes for specific data: context, sessions,
79 * certificates, tickets and buffers in the program. The context and session
80 * size values have been calculated based on the 'print_deserialized_ssl_context()'
81 * and 'print_deserialized_ssl_session()' content.
82 */
83#define MIN_CONTEXT_LEN 84
84#define MIN_SESSION_LEN 88
85
86#define MAX_CONTEXT_LEN 875 /* without session data */
87#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
88#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
89#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
90
91#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
92#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
93 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
94
95#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
96#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
97
98/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010099 * A macro that prevents from reading out of the ssl buffer range.
100 */
101#define CHECK_SSL_END( LEN ) \
102do \
103{ \
104 if( end - ssl < (int)( LEN ) ) \
105 { \
106 printf_err( "%s", buf_ln_err ); \
107 return; \
108 } \
109} while( 0 )
110
111/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100112 * Global values
113 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100114FILE *b64_file = NULL; /* file with base64 codes to deserialize */
115char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
116char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
117char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200118const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100119const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100120
121/*
122 * Basic printing functions
123 */
124void print_version( )
125{
126 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
127}
128
129void print_usage( )
130{
131 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200132 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 +0100133 "in the text file. The program can deserialize many codes from one file, but they must be\n"
134 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100135 printf(
136 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100137 "\t-f path - Path to the file with base64 code\n"
138 "\t-v - Show version\n"
139 "\t-h - Show this usage\n"
140 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200141 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100142 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
143 "\t flag. You can also use it if there are some problems with reading\n"
144 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200145 "\t--dtls-protocol=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 without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100147 "\n"
148 );
149}
150
151void printf_dbg( const char *str, ... )
152{
153 if( debug )
154 {
155 va_list args;
156 va_start( args, str );
157 printf( "debug: " );
158 vprintf( str, args );
159 fflush( stdout );
160 va_end( args );
161 }
162}
163
164void printf_err( const char *str, ... )
165{
166 va_list args;
167 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100168 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100169 fprintf( stderr, "ERROR: " );
170 vfprintf( stderr, str, args );
171 fflush( stderr );
172 va_end( args );
173}
174
175/*
176 * Exit from the program in case of error
177 */
178void error_exit()
179{
180 if( NULL != b64_file )
181 {
182 fclose( b64_file );
183 }
184 exit( -1 );
185}
186
187/*
188 * This function takes the input arguments of this program
189 */
190void parse_arguments( int argc, char *argv[] )
191{
192 int i = 1;
193
194 if( argc < 2 )
195 {
196 print_usage();
197 error_exit();
198 }
199
200 while( i < argc )
201 {
202 if( strcmp( argv[i], "-d" ) == 0 )
203 {
204 debug = 1;
205 }
206 else if( strcmp( argv[i], "-h" ) == 0 )
207 {
208 print_usage();
209 }
210 else if( strcmp( argv[i], "-v" ) == 0 )
211 {
212 print_version();
213 }
214 else if( strcmp( argv[i], "-f" ) == 0 )
215 {
216 if( ++i >= argc )
217 {
218 printf_err( "File path is empty\n" );
219 error_exit();
220 }
221
Paul Elliott3820c152021-12-09 12:48:51 +0000222 if( NULL != b64_file )
223 {
224 printf_err( "Cannot specify more than one file with -f\n" );
225 error_exit( );
226 }
227
228 if( ( b64_file = fopen( argv[i], "r" )) == NULL )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100229 {
230 printf_err( "Cannot find file \"%s\"\n", argv[i] );
231 error_exit();
232 }
233 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100234 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
235 {
236 conf_keep_peer_certificate = 0;
237 }
238 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
239 {
240 conf_dtls_proto = 0;
241 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100242 else
243 {
244 print_usage();
245 error_exit();
246 }
247
248 i++;
249 }
250}
251
Piotr Nowicki14d31052020-03-16 14:05:22 +0100252/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100253 * This function prints base64 code to the stdout
254 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100255void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100256{
257 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100258 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100259 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100260 while( b < end )
261 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100262 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100263 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100264 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100265 i = 0;
266 }
267 printf( "%c", *b++ );
268 }
269 printf( "\n" );
270 fflush( stdout );
271}
272
273/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100274 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100275 *
276 * /p b buffer with data to print
277 * /p len number of bytes to print
278 * /p in_line number of bytes in one line
279 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100280 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100281void print_hex( const uint8_t *b, size_t len,
282 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100283{
284 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100285 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100286
287 if( prefix == NULL )
288 {
289 prefix = "";
290 }
291
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100292 while( b < end )
293 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100294 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100295 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100296 printf( "\n%s", prefix );
297 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100298 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100299 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100300 }
301 printf("\n");
302 fflush(stdout);
303}
304
305/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100306 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
307 */
308void print_time( const time_t *time )
309{
310 char buf[20];
311 struct tm *t = gmtime( time );
312 static const char format[] = "%Y-%m-%d %H:%M:%S";
313 if( NULL != t )
314 {
315 strftime( buf, sizeof( buf ), format, t );
316 printf( "%s\n", buf );
317 }
318 else
319 {
320 printf( "unknown\n" );
321 }
322}
323
324/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100325 * Print the input string if the bit is set in the value
326 */
327void print_if_bit( const char *str, int bit, int val )
328{
329 if( bit & val )
330 {
331 printf( "\t%s\n", str );
332 }
333}
334
335/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100336 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
337 */
338const char * get_enabled_str( int is_en )
339{
340 return ( is_en ) ? "enabled" : "disabled";
341}
342
343/*
344 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
345 */
346const char * get_mfl_str( int mfl_code )
347{
348 switch( mfl_code )
349 {
350 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
351 return "none";
352 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
353 return "512";
354 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
355 return "1024";
356 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
357 return "2048";
358 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
359 return "4096";
360 default:
361 return "error";
362 }
363}
364
365/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100366 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
367 * previously. After each call to this function, the internal file position
368 * indicator of the global b64_file is advanced.
369 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200370 * Note - This function checks the size of the input buffer and if necessary,
371 * increases it to the maximum MAX_BASE64_LEN
372 *
373 * /p b64 pointer to the pointer of the buffer for input data
374 * /p max_len pointer to the current buffer capacity. It can be changed if
375 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100376 *
377 * \retval number of bytes written in to the b64 buffer or 0 in case no more
378 * data was found
379 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200380size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100381{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200382 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100383 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100384 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000385 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100386
387 while( EOF != c )
388 {
389 char c_valid = 0;
390
Nayna Jaind696e7d2020-08-13 19:17:53 +0000391 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100392
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200393 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100394 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200395 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100396 {
397 c_valid = 1;
398 pad = 2;
399 }
400 }
401 else if( ( c >= 'A' && c <= 'Z' ) ||
402 ( c >= 'a' && c <= 'z' ) ||
403 ( c >= '0' && c <= '9' ) ||
404 c == '+' || c == '/' )
405 {
406 c_valid = 1;
407 }
408 else if( c == '=' )
409 {
410 c_valid = 1;
411 pad = 1;
412 }
413 else if( c == '-' )
414 {
415 c = '+';
416 c_valid = 1;
417 }
418 else if( c == '_' )
419 {
420 c = '/';
421 c_valid = 1;
422 }
423
424 if( c_valid )
425 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200426 /* A string of characters that could be a base64 code. */
427 valid_balance++;
428
429 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100430 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200431 ( *b64 )[ len++ ] = c;
432 }
433 else if( *max_len < MAX_BASE64_LEN )
434 {
435 /* Current buffer is too small, but can be resized. */
436 void *ptr;
437 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
438 *max_len + 4096 : MAX_BASE64_LEN;
439
440 ptr = realloc( *b64, new_size );
441 if( NULL == ptr )
442 {
443 printf_err( alloc_err );
444 return 0;
445 }
446 *b64 = ptr;
447 *max_len = new_size;
448 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100449 }
450 else
451 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200452 /* Too much data so it will be treated as invalid */
453 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100454 }
455 }
456 else if( len > 0 )
457 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200458 /* End of a string that could be a base64 code, but need to check
459 * that the length of the characters is correct. */
460
461 valid_balance--;
462
463 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100464 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200465 printf_dbg( "The code found is too small to be a SSL context.\n" );
466 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100467 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200468 else if( len > *max_len )
469 {
470 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
471 len = pad = 0;
472 }
473 else if( len % 4 != 0 )
474 {
475 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
476 len = pad = 0;
477 }
478 else
479 {
480 /* Base64 code with valid character length. */
481 return len;
482 }
483 }
484 else
485 {
486 valid_balance--;
487 }
488
489 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
490 if( valid_balance < -100 )
491 {
492 printf_err( "Too many bad symbols detected. File check aborted.\n" );
493 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100494 }
495 }
496
497 printf_dbg( "End of file\n" );
498 return 0;
499}
500
Hanno Becker2c2722d2020-10-09 09:36:23 +0100501#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100502/*
503 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100504 * about the certificates from provided data.
505 *
506 * /p ssl pointer to serialized certificate
507 * /p len number of bytes in the buffer
508*/
509void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
510{
511 enum { STRLEN = 4096 };
512 mbedtls_x509_crt crt;
513 int ret;
514 char str[STRLEN];
515
516 printf( "\nCertificate:\n" );
517
518 mbedtls_x509_crt_init( &crt );
519 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
520 if( 0 != ret )
521 {
522 mbedtls_strerror( ret, str, STRLEN );
523 printf_err( "Invalid format of X.509 - %s\n", str );
524 printf( "Cannot deserialize:\n\t" );
525 print_hex( ssl, len, 25, "\t" );
526 }
527 else
528 {
529 mbedtls_x509_crt *current = &crt;
530
531 while( current != NULL )
532 {
533 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
534 if( 0 > ret )
535 {
536 mbedtls_strerror( ret, str, STRLEN );
537 printf_err( "Cannot write to the output - %s\n", str );
538 }
539 else
540 {
541 printf( "%s", str );
542 }
543
544 current = current->next;
545
546 if( current )
547 {
548 printf( "\n" );
549 }
550
551 }
552 }
553
554 mbedtls_x509_crt_free( &crt );
555}
Hanno Becker2c2722d2020-10-09 09:36:23 +0100556#endif /* !MBEDTLS_X509_REMOVE_INFO */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100557
558/*
559 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100560 * about the session from provided data. This function was built based on
561 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
562 * due to dependencies on the mbedTLS configuration.
563 *
564 * The data structure in the buffer:
565 * uint64 start_time;
566 * uint8 ciphersuite[2]; // defined by the standard
567 * uint8 compression; // 0 or 1
568 * uint8 session_id_len; // at most 32
569 * opaque session_id[32];
570 * opaque master[48]; // fixed length in the standard
571 * uint32 verify_result;
572 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
573 * opaque ticket<0..2^24-1>; // length 0 means no ticket
574 * uint32 ticket_lifetime;
575 * uint8 mfl_code; // up to 255 according to standard
576 * uint8 trunc_hmac; // 0 or 1
577 * uint8 encrypt_then_mac; // 0 or 1
578 *
579 * /p ssl pointer to serialized session
580 * /p len number of bytes in the buffer
581 * /p session_cfg_flag session configuration flags
582 */
583void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
584 int session_cfg_flag )
585{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100586 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
587 int ciphersuite_id;
588 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100589 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100590 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100591
592 printf( "\nSession info:\n" );
593
594 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
595 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100596 uint64_t start;
597 CHECK_SSL_END( 8 );
598 start = ( (uint64_t) ssl[0] << 56 ) |
599 ( (uint64_t) ssl[1] << 48 ) |
600 ( (uint64_t) ssl[2] << 40 ) |
601 ( (uint64_t) ssl[3] << 32 ) |
602 ( (uint64_t) ssl[4] << 24 ) |
603 ( (uint64_t) ssl[5] << 16 ) |
604 ( (uint64_t) ssl[6] << 8 ) |
605 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100606 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100607 printf( "\tstart time : " );
608 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100609 }
610
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100611 CHECK_SSL_END( 2 );
612 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
613 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100614 ssl += 2;
615
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100616 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
617 if( ciphersuite_info == NULL )
618 {
619 printf_err( "Cannot find ciphersuite info\n" );
620 }
621 else
622 {
623 const mbedtls_cipher_info_t *cipher_info;
624 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100625
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100626 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
627 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
628
629 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
630 if( cipher_info == NULL )
631 {
632 printf_err( "Cannot find cipher info\n" );
633 }
634 else
635 {
636 printf( "\tcipher : %s\n", cipher_info->name );
637 }
638
639 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
640 if( md_info == NULL )
641 {
642 printf_err( "Cannot find Message-Digest info\n" );
643 }
644 else
645 {
Chris Jonesa1df4942021-03-11 17:44:43 +0000646 printf( "\tMessage-Digest : %s\n", mbedtls_md_get_name( md_info ) );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100647 }
648 }
649
650 CHECK_SSL_END( 1 );
651 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
652
653 /* Note - Here we can get session ID length from serialized data, but we
654 * use hardcoded 32-bytes length. This approach was taken from
655 * 'mbedtls_ssl_session_load()'. */
656 CHECK_SSL_END( 1 + 32 );
657 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
658 printf( "\tsession ID : ");
659 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100660 ssl += 32;
661
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100662 printf( "\tmaster secret : ");
663 CHECK_SSL_END( 48 );
664 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100665 ssl += 48;
666
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100667 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100668 verify_result = ( (uint32_t) ssl[0] << 24 ) |
669 ( (uint32_t) ssl[1] << 16 ) |
670 ( (uint32_t) ssl[2] << 8 ) |
671 ( (uint32_t) ssl[3] );
672 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100673 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100674
675 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
676 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100677 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100678 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100679 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100680 cert_len = ( (uint32_t) ssl[0] << 16 ) |
681 ( (uint32_t) ssl[1] << 8 ) |
682 ( (uint32_t) ssl[2] );
683 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100684 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100685
686 if( cert_len > 0 )
687 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100688 CHECK_SSL_END( cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100689#if !defined(MBEDTLS_X509_REMOVE_INFO)
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100690 print_deserialized_ssl_cert( ssl, cert_len );
Hanno Becker2c2722d2020-10-09 09:36:23 +0100691#endif
Piotr Nowicki4e192002020-03-18 17:27:29 +0100692 ssl += cert_len;
693 }
694 }
695 else
696 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100697 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100698
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100699 CHECK_SSL_END( 1 );
700 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100701 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100702 case MBEDTLS_MD_NONE:
703 printf( "none\n" );
704 break;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100705 case MBEDTLS_MD_MD5:
706 printf( "MD5\n" );
707 break;
708 case MBEDTLS_MD_SHA1:
709 printf( "SHA1\n" );
710 break;
711 case MBEDTLS_MD_SHA224:
712 printf( "SHA224\n" );
713 break;
714 case MBEDTLS_MD_SHA256:
715 printf( "SHA256\n" );
716 break;
717 case MBEDTLS_MD_SHA384:
718 printf( "SHA384\n" );
719 break;
720 case MBEDTLS_MD_SHA512:
721 printf( "SHA512\n" );
722 break;
723 case MBEDTLS_MD_RIPEMD160:
724 printf( "RIPEMD160\n" );
725 break;
726 default:
727 printf( "undefined or erroneous\n" );
728 break;
729 }
730
731 CHECK_SSL_END( 1 );
732 cert_len = (uint32_t) *ssl++;
733 printf_dbg( "Message-Digest length: %u\n", cert_len );
734
735 if( cert_len > 0 )
736 {
737 printf( "\tPeer digest cert : " );
738 CHECK_SSL_END( cert_len );
739 print_hex( ssl, cert_len, 16, "\t " );
740 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100741 }
742 }
743 }
744
745 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
746 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100747 printf( "\nTicket:\n" );
748
749 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100750 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
751 ( (uint32_t) ssl[1] << 8 ) |
752 ( (uint32_t) ssl[2] );
753 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100754 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100755
756 if( ticket_len > 0 )
757 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100758 printf( "\t" );
759 CHECK_SSL_END( ticket_len );
760 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100761 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100762 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100763 }
764
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100765 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100766 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
767 ( (uint32_t) ssl[1] << 16 ) |
768 ( (uint32_t) ssl[2] << 8 ) |
769 ( (uint32_t) ssl[3] );
770 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100771 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
772 }
773
774 if( ssl < end )
775 {
776 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100777 }
778
779 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
780 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100781 CHECK_SSL_END( 1 );
782 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100783 }
784
785 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
786 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100787 CHECK_SSL_END( 1 );
788 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100789 }
790
791 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
792 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100793 CHECK_SSL_END( 1 );
794 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100795 }
796
797 if( 0 != ( end - ssl ) )
798 {
799 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
800 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100801}
802
803/*
804 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100805 * about the context from provided data. This function was built based on
806 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
807 * due to dependencies on the mbedTLS configuration and the configuration of
808 * the context when serialization was created.
809 *
810 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200811 * // header
812 * uint8 version[3];
813 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100814 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200815 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100816 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
817 * // transform sub-structure
818 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200819 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100820 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200821 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100822 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
823 * // fields from ssl_context
824 * uint32 badmac_seen; // DTLS: number of records with failing MAC
825 * uint64 in_window_top; // DTLS: last validated record seq_num
826 * uint64 in_window; // DTLS: bitmask for replay protection
827 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
828 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
829 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200830 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100831 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
832 *
833 * /p ssl pointer to serialized session
834 * /p len number of bytes in the buffer
835 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100836void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100837{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100838 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100839 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100840 int session_cfg_flag;
841 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100842
843 printf( "\nMbed TLS version:\n" );
844
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100845 CHECK_SSL_END( 3 + 2 + 3 );
846
847 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
848 printf( "\tminor %u\n", (uint32_t) *ssl++ );
849 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100850
851 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100852
853 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
854 ssl += 2;
855
856 context_cfg_flag = ( (int) ssl[0] << 16 ) |
857 ( (int) ssl[1] << 8 ) |
858 ( (int) ssl[2] ) ;
859 ssl += 3;
860
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100861 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
862 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
863
864 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
865 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
866 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100867 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
868 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
869 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
870
871 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100872 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
873 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
874
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100875 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100876 session_len = ( (uint32_t) ssl[0] << 24 ) |
877 ( (uint32_t) ssl[1] << 16 ) |
878 ( (uint32_t) ssl[2] << 8 ) |
879 ( (uint32_t) ssl[3] );
880 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100881 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100882
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100883 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100884 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
885 ssl += session_len;
886
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100887 printf( "\nRandom bytes:\n\t");
888
889 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
890 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100891 ssl += TRANSFORM_RANDBYTE_LEN;
892
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100893 printf( "\nContext others:\n" );
894
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100895 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
896 {
897 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100899 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100900 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100901 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100902
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100903 printf( "\tin CID : " );
904 if( cid_len > 0 )
905 {
906 CHECK_SSL_END( cid_len );
907 print_hex( ssl, cid_len, 20, "\t" );
908 ssl += cid_len;
909 }
910 else
911 {
912 printf( "none\n" );
913 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100914
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100915 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100916 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100917 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100918
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100919 printf( "\tout CID : " );
920 if( cid_len > 0 )
921 {
922 CHECK_SSL_END( cid_len );
923 print_hex( ssl, cid_len, 20, "\t" );
924 ssl += cid_len;
925 }
926 else
927 {
928 printf( "none\n" );
929 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100930 }
931
932 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
933 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100934 uint32_t badmac_seen;
935
936 CHECK_SSL_END( 4 );
937 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
938 ( (uint32_t) ssl[1] << 16 ) |
939 ( (uint32_t) ssl[2] << 8 ) |
940 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100941 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100942 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100943
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100944 /* value 'in_window_top' from mbedtls_ssl_context */
945 printf( "\tlast validated record sequence no. : " );
946 CHECK_SSL_END( 8 );
947 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100948 ssl += 8;
949
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100950 /* value 'in_window' from mbedtls_ssl_context */
951 printf( "\tbitmask for replay detection : " );
952 CHECK_SSL_END( 8 );
953 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100954 ssl += 8;
955 }
956
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100957 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100958 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100959 CHECK_SSL_END( 1 );
960 printf( "\tDTLS datagram packing : %s\n",
961 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100962 }
963
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100964 /* value 'cur_out_ctr' from mbedtls_ssl_context */
965 printf( "\toutgoing record sequence no. : ");
966 CHECK_SSL_END( 8 );
967 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100968 ssl += 8;
969
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100970 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100971 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100972 uint16_t mtu;
973 CHECK_SSL_END( 2 );
974 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100975 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100976 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100977 }
978
979
980 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
981 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100982 uint8_t alpn_len;
983
984 CHECK_SSL_END( 1 );
985 alpn_len = *ssl++;
986 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
987
988 printf( "\tALPN negotiation : " );
989 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100990 if( alpn_len > 0 )
991 {
992 if( strlen( (const char*) ssl ) == alpn_len )
993 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100994 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100995 }
996 else
997 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100998 printf( "\n" );
999 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001000 }
1001 ssl += alpn_len;
1002 }
1003 else
1004 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001005 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001006 }
1007 }
1008
Piotr Nowicki4e192002020-03-18 17:27:29 +01001009 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001010 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001011 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001012 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001013 printf( "\n" );
1014}
1015
Piotr Nowicki9370f902020-03-13 14:43:22 +01001016int main( int argc, char *argv[] )
1017{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001018 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001019
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001020 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001021 uint8_t *b64_buf = NULL;
1022 uint8_t *ssl_buf = NULL;
1023 size_t b64_max_len = SSL_INIT_LEN;
1024 size_t ssl_max_len = SSL_INIT_LEN;
1025 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001026
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001027 /* The 'b64_file' is opened when parsing arguments to check that the
1028 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001029 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001030
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001031 if( NULL != b64_file )
1032 {
1033 b64_buf = malloc( SSL_INIT_LEN );
1034 ssl_buf = malloc( SSL_INIT_LEN );
1035
1036 if( NULL == b64_buf || NULL == ssl_buf )
1037 {
1038 printf_err( alloc_err );
1039 fclose( b64_file );
1040 b64_file = NULL;
1041 }
1042 }
1043
Piotr Nowicki14d31052020-03-16 14:05:22 +01001044 while( NULL != b64_file )
1045 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001046 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001047 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001048 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001049 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001050 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1051
1052 /* Allocate more memory if necessary. */
1053 if( ssl_required_len > ssl_max_len )
1054 {
1055 void *ptr = realloc( ssl_buf, ssl_required_len );
1056 if( NULL == ptr )
1057 {
1058 printf_err( alloc_err );
1059 fclose( b64_file );
1060 b64_file = NULL;
1061 break;
1062 }
1063 ssl_buf = ptr;
1064 ssl_max_len = ssl_required_len;
1065 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001066
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001067 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001068
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001069 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001070 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001071
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001072 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001073 if( ret != 0)
1074 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001075 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1076 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001077 continue;
1078 }
1079
1080 if( debug )
1081 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001082 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001083 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001084 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001085
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001086 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001087
Piotr Nowicki14d31052020-03-16 14:05:22 +01001088 }
1089 else
1090 {
1091 fclose( b64_file );
1092 b64_file = NULL;
1093 }
1094 }
1095
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001096 free( b64_buf );
1097 free( ssl_buf );
1098
1099 if( b64_counter > 0 )
1100 {
1101 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1102 }
1103 else
1104 {
1105 printf( "Finished. No valid base64 code found\n" );
1106 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001107
Piotr Nowicki9370f902020-03-13 14:43:22 +01001108 return 0;
1109}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001110
1111#endif /* MBEDTLS_X509_CRT_PARSE_C */