blob: 7ac01d6df37afead2ac33cc7a09b11cf4f9df423 [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
2 * MbedTLS SSL context deserializer from base64 code
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Piotr Nowicki9370f902020-03-13 14:43:22 +01005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Piotr Nowicki9370f902020-03-13 14:43:22 +010018 */
19
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020020#if !defined(MBEDTLS_CONFIG_FILE)
21#include "mbedtls/config.h"
22#else
23#include MBEDTLS_CONFIG_FILE
Piotr Nowickif86192f2020-03-26 11:45:42 +010024#endif
25
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)
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020031int main( void )
32{
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");
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020035 return( 0 );
36}
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>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010046#include <time.h>
47#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010048#include "mbedtls/error.h"
49#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010050#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010051#include "mbedtls/md_internal.h"
52#include "mbedtls/x509_crt.h"
53#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010054
55/*
56 * This program version
57 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010058#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010059#define VER_MAJOR 0
60#define VER_MINOR 1
61
62/*
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020063 * Flags copied from the Mbed TLS library.
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010064 */
65#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
66#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
67#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
68#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
69#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
70#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
71#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
72
73#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
74#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
75#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
76#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
77
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010078#define TRANSFORM_RANDBYTE_LEN 64
79
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010080/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020081 * Minimum and maximum number of bytes for specific data: context, sessions,
82 * certificates, tickets and buffers in the program. The context and session
83 * size values have been calculated based on the 'print_deserialized_ssl_context()'
84 * and 'print_deserialized_ssl_session()' content.
85 */
86#define MIN_CONTEXT_LEN 84
87#define MIN_SESSION_LEN 88
88
89#define MAX_CONTEXT_LEN 875 /* without session data */
90#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
91#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
92#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
93
94#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
95#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
96 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
97
98#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
99#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
100
101/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100102 * A macro that prevents from reading out of the ssl buffer range.
103 */
104#define CHECK_SSL_END( LEN ) \
105do \
106{ \
107 if( end - ssl < (int)( LEN ) ) \
108 { \
109 printf_err( "%s", buf_ln_err ); \
110 return; \
111 } \
112} while( 0 )
113
114/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100115 * Global values
116 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100117FILE *b64_file = NULL; /* file with base64 codes to deserialize */
118char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
119char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
120char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200121const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100122const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100123
124/*
125 * Basic printing functions
126 */
127void print_version( )
128{
129 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
130}
131
132void print_usage( )
133{
134 print_version();
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200135 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 +0100136 "in the text file. The program can deserialize many codes from one file, but they must be\n"
137 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100138 printf(
139 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100140 "\t-f path - Path to the file with base64 code\n"
141 "\t-v - Show version\n"
142 "\t-h - Show this usage\n"
143 "\t-d - Print more information\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200144 "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100145 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
146 "\t flag. You can also use it if there are some problems with reading\n"
147 "\t the information about certificate\n"
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +0200148 "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100149 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100150 "\n"
151 );
152}
153
154void printf_dbg( const char *str, ... )
155{
156 if( debug )
157 {
158 va_list args;
159 va_start( args, str );
160 printf( "debug: " );
161 vprintf( str, args );
162 fflush( stdout );
163 va_end( args );
164 }
165}
166
167void printf_err( const char *str, ... )
168{
169 va_list args;
170 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100171 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100172 fprintf( stderr, "ERROR: " );
173 vfprintf( stderr, str, args );
174 fflush( stderr );
175 va_end( args );
176}
177
178/*
179 * Exit from the program in case of error
180 */
181void error_exit()
182{
183 if( NULL != b64_file )
184 {
185 fclose( b64_file );
186 }
187 exit( -1 );
188}
189
190/*
191 * This function takes the input arguments of this program
192 */
193void parse_arguments( int argc, char *argv[] )
194{
195 int i = 1;
196
197 if( argc < 2 )
198 {
199 print_usage();
200 error_exit();
201 }
202
203 while( i < argc )
204 {
205 if( strcmp( argv[i], "-d" ) == 0 )
206 {
207 debug = 1;
208 }
209 else if( strcmp( argv[i], "-h" ) == 0 )
210 {
211 print_usage();
212 }
213 else if( strcmp( argv[i], "-v" ) == 0 )
214 {
215 print_version();
216 }
217 else if( strcmp( argv[i], "-f" ) == 0 )
218 {
219 if( ++i >= argc )
220 {
221 printf_err( "File path is empty\n" );
222 error_exit();
223 }
224
Paul Elliott110afd02021-12-09 12:48:51 +0000225 if( NULL != b64_file )
226 {
227 printf_err( "Cannot specify more than one file with -f\n" );
228 error_exit( );
229 }
230
231 if( ( b64_file = fopen( argv[i], "r" )) == NULL )
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100232 {
233 printf_err( "Cannot find file \"%s\"\n", argv[i] );
234 error_exit();
235 }
236 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100237 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
238 {
239 conf_keep_peer_certificate = 0;
240 }
241 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
242 {
243 conf_dtls_proto = 0;
244 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100245 else
246 {
247 print_usage();
248 error_exit();
249 }
250
251 i++;
252 }
253}
254
Piotr Nowicki14d31052020-03-16 14:05:22 +0100255/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100256 * This function prints base64 code to the stdout
257 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100258void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100259{
260 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100261 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100262 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100263 while( b < end )
264 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100265 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100266 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100267 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100268 i = 0;
269 }
270 printf( "%c", *b++ );
271 }
272 printf( "\n" );
273 fflush( stdout );
274}
275
276/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100277 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100278 *
279 * /p b buffer with data to print
280 * /p len number of bytes to print
281 * /p in_line number of bytes in one line
282 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100283 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100284void print_hex( const uint8_t *b, size_t len,
285 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100286{
287 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100288 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100289
290 if( prefix == NULL )
291 {
292 prefix = "";
293 }
294
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100295 while( b < end )
296 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100297 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100298 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100299 printf( "\n%s", prefix );
300 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100301 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100302 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100303 }
304 printf("\n");
305 fflush(stdout);
306}
307
308/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100309 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
310 */
311void print_time( const time_t *time )
312{
313 char buf[20];
314 struct tm *t = gmtime( time );
315 static const char format[] = "%Y-%m-%d %H:%M:%S";
316 if( NULL != t )
317 {
318 strftime( buf, sizeof( buf ), format, t );
319 printf( "%s\n", buf );
320 }
321 else
322 {
323 printf( "unknown\n" );
324 }
325}
326
327/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100328 * Print the input string if the bit is set in the value
329 */
330void print_if_bit( const char *str, int bit, int val )
331{
332 if( bit & val )
333 {
334 printf( "\t%s\n", str );
335 }
336}
337
338/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100339 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
340 */
341const char * get_enabled_str( int is_en )
342{
343 return ( is_en ) ? "enabled" : "disabled";
344}
345
346/*
347 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
348 */
349const char * get_mfl_str( int mfl_code )
350{
351 switch( mfl_code )
352 {
353 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
354 return "none";
355 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
356 return "512";
357 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
358 return "1024";
359 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
360 return "2048";
361 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
362 return "4096";
363 default:
364 return "error";
365 }
366}
367
368/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100369 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
370 * previously. After each call to this function, the internal file position
371 * indicator of the global b64_file is advanced.
372 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200373 * Note - This function checks the size of the input buffer and if necessary,
374 * increases it to the maximum MAX_BASE64_LEN
375 *
376 * /p b64 pointer to the pointer of the buffer for input data
377 * /p max_len pointer to the current buffer capacity. It can be changed if
378 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100379 *
380 * \retval number of bytes written in to the b64 buffer or 0 in case no more
381 * data was found
382 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200383size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100384{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200385 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100386 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100387 char pad = 0;
Nayna Jaind696e7d2020-08-13 19:17:53 +0000388 int c = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100389
390 while( EOF != c )
391 {
392 char c_valid = 0;
393
Nayna Jaind696e7d2020-08-13 19:17:53 +0000394 c = fgetc( b64_file );
Piotr Nowicki14d31052020-03-16 14:05:22 +0100395
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200396 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100397 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200398 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100399 {
400 c_valid = 1;
401 pad = 2;
402 }
403 }
404 else if( ( c >= 'A' && c <= 'Z' ) ||
405 ( c >= 'a' && c <= 'z' ) ||
406 ( c >= '0' && c <= '9' ) ||
407 c == '+' || c == '/' )
408 {
409 c_valid = 1;
410 }
411 else if( c == '=' )
412 {
413 c_valid = 1;
414 pad = 1;
415 }
416 else if( c == '-' )
417 {
418 c = '+';
419 c_valid = 1;
420 }
421 else if( c == '_' )
422 {
423 c = '/';
424 c_valid = 1;
425 }
426
427 if( c_valid )
428 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200429 /* A string of characters that could be a base64 code. */
430 valid_balance++;
431
432 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100433 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200434 ( *b64 )[ len++ ] = c;
435 }
436 else if( *max_len < MAX_BASE64_LEN )
437 {
438 /* Current buffer is too small, but can be resized. */
439 void *ptr;
440 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
441 *max_len + 4096 : MAX_BASE64_LEN;
442
443 ptr = realloc( *b64, new_size );
444 if( NULL == ptr )
445 {
446 printf_err( alloc_err );
447 return 0;
448 }
449 *b64 = ptr;
450 *max_len = new_size;
451 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100452 }
453 else
454 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200455 /* Too much data so it will be treated as invalid */
456 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100457 }
458 }
459 else if( len > 0 )
460 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200461 /* End of a string that could be a base64 code, but need to check
462 * that the length of the characters is correct. */
463
464 valid_balance--;
465
466 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100467 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200468 printf_dbg( "The code found is too small to be a SSL context.\n" );
469 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100470 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200471 else if( len > *max_len )
472 {
473 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
474 len = pad = 0;
475 }
476 else if( len % 4 != 0 )
477 {
478 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
479 len = pad = 0;
480 }
481 else
482 {
483 /* Base64 code with valid character length. */
484 return len;
485 }
486 }
487 else
488 {
489 valid_balance--;
490 }
491
492 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
493 if( valid_balance < -100 )
494 {
495 printf_err( "Too many bad symbols detected. File check aborted.\n" );
496 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100497 }
498 }
499
500 printf_dbg( "End of file\n" );
501 return 0;
502}
503
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100504/*
505 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100506 * about the certificates from provided data.
507 *
508 * /p ssl pointer to serialized certificate
509 * /p len number of bytes in the buffer
510*/
511void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
512{
513 enum { STRLEN = 4096 };
514 mbedtls_x509_crt crt;
515 int ret;
516 char str[STRLEN];
517
518 printf( "\nCertificate:\n" );
519
520 mbedtls_x509_crt_init( &crt );
521 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
522 if( 0 != ret )
523 {
524 mbedtls_strerror( ret, str, STRLEN );
525 printf_err( "Invalid format of X.509 - %s\n", str );
526 printf( "Cannot deserialize:\n\t" );
527 print_hex( ssl, len, 25, "\t" );
528 }
529 else
530 {
531 mbedtls_x509_crt *current = &crt;
532
533 while( current != NULL )
534 {
535 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
536 if( 0 > ret )
537 {
538 mbedtls_strerror( ret, str, STRLEN );
539 printf_err( "Cannot write to the output - %s\n", str );
540 }
541 else
542 {
543 printf( "%s", str );
544 }
545
546 current = current->next;
547
548 if( current )
549 {
550 printf( "\n" );
551 }
552
553 }
554 }
555
556 mbedtls_x509_crt_free( &crt );
557}
558
559/*
560 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100561 * about the session from provided data. This function was built based on
562 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
563 * due to dependencies on the mbedTLS configuration.
564 *
565 * The data structure in the buffer:
566 * uint64 start_time;
567 * uint8 ciphersuite[2]; // defined by the standard
568 * uint8 compression; // 0 or 1
569 * uint8 session_id_len; // at most 32
570 * opaque session_id[32];
571 * opaque master[48]; // fixed length in the standard
572 * uint32 verify_result;
573 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
574 * opaque ticket<0..2^24-1>; // length 0 means no ticket
575 * uint32 ticket_lifetime;
576 * uint8 mfl_code; // up to 255 according to standard
577 * uint8 trunc_hmac; // 0 or 1
578 * uint8 encrypt_then_mac; // 0 or 1
579 *
580 * /p ssl pointer to serialized session
581 * /p len number of bytes in the buffer
582 * /p session_cfg_flag session configuration flags
583 */
584void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
585 int session_cfg_flag )
586{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100587 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
588 int ciphersuite_id;
589 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100590 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100591 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100592
593 printf( "\nSession info:\n" );
594
595 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
596 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100597 uint64_t start;
598 CHECK_SSL_END( 8 );
599 start = ( (uint64_t) ssl[0] << 56 ) |
600 ( (uint64_t) ssl[1] << 48 ) |
601 ( (uint64_t) ssl[2] << 40 ) |
602 ( (uint64_t) ssl[3] << 32 ) |
603 ( (uint64_t) ssl[4] << 24 ) |
604 ( (uint64_t) ssl[5] << 16 ) |
605 ( (uint64_t) ssl[6] << 8 ) |
606 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100607 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100608 printf( "\tstart time : " );
609 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100610 }
611
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100612 CHECK_SSL_END( 2 );
613 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
614 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100615 ssl += 2;
616
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100617 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
618 if( ciphersuite_info == NULL )
619 {
620 printf_err( "Cannot find ciphersuite info\n" );
621 }
622 else
623 {
624 const mbedtls_cipher_info_t *cipher_info;
625 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100626
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100627 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
628 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
629
630 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
631 if( cipher_info == NULL )
632 {
633 printf_err( "Cannot find cipher info\n" );
634 }
635 else
636 {
637 printf( "\tcipher : %s\n", cipher_info->name );
638 }
639
640 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
641 if( md_info == NULL )
642 {
643 printf_err( "Cannot find Message-Digest info\n" );
644 }
645 else
646 {
647 printf( "\tMessage-Digest : %s\n", md_info->name );
648 }
649 }
650
651 CHECK_SSL_END( 1 );
652 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
653
654 /* Note - Here we can get session ID length from serialized data, but we
655 * use hardcoded 32-bytes length. This approach was taken from
656 * 'mbedtls_ssl_session_load()'. */
657 CHECK_SSL_END( 1 + 32 );
658 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
659 printf( "\tsession ID : ");
660 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100661 ssl += 32;
662
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100663 printf( "\tmaster secret : ");
664 CHECK_SSL_END( 48 );
665 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100666 ssl += 48;
667
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100668 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100669 verify_result = ( (uint32_t) ssl[0] << 24 ) |
670 ( (uint32_t) ssl[1] << 16 ) |
671 ( (uint32_t) ssl[2] << 8 ) |
672 ( (uint32_t) ssl[3] );
673 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100674 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100675
676 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
677 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100678 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100679 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100680 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100681 cert_len = ( (uint32_t) ssl[0] << 16 ) |
682 ( (uint32_t) ssl[1] << 8 ) |
683 ( (uint32_t) ssl[2] );
684 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100685 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100686
687 if( cert_len > 0 )
688 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100689 CHECK_SSL_END( cert_len );
690 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100691 ssl += cert_len;
692 }
693 }
694 else
695 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100696 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100697
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100698 CHECK_SSL_END( 1 );
699 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100700 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100701 case MBEDTLS_MD_NONE:
702 printf( "none\n" );
703 break;
704 case MBEDTLS_MD_MD2:
705 printf( "MD2\n" );
706 break;
707 case MBEDTLS_MD_MD4:
708 printf( "MD4\n" );
709 break;
710 case MBEDTLS_MD_MD5:
711 printf( "MD5\n" );
712 break;
713 case MBEDTLS_MD_SHA1:
714 printf( "SHA1\n" );
715 break;
716 case MBEDTLS_MD_SHA224:
717 printf( "SHA224\n" );
718 break;
719 case MBEDTLS_MD_SHA256:
720 printf( "SHA256\n" );
721 break;
722 case MBEDTLS_MD_SHA384:
723 printf( "SHA384\n" );
724 break;
725 case MBEDTLS_MD_SHA512:
726 printf( "SHA512\n" );
727 break;
728 case MBEDTLS_MD_RIPEMD160:
729 printf( "RIPEMD160\n" );
730 break;
731 default:
732 printf( "undefined or erroneous\n" );
733 break;
734 }
735
736 CHECK_SSL_END( 1 );
737 cert_len = (uint32_t) *ssl++;
738 printf_dbg( "Message-Digest length: %u\n", cert_len );
739
740 if( cert_len > 0 )
741 {
742 printf( "\tPeer digest cert : " );
743 CHECK_SSL_END( cert_len );
744 print_hex( ssl, cert_len, 16, "\t " );
745 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100746 }
747 }
748 }
749
750 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
751 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100752 printf( "\nTicket:\n" );
753
754 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100755 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
756 ( (uint32_t) ssl[1] << 8 ) |
757 ( (uint32_t) ssl[2] );
758 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100759 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100760
761 if( ticket_len > 0 )
762 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100763 printf( "\t" );
764 CHECK_SSL_END( ticket_len );
765 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100766 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100767 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100768 }
769
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100770 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100771 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
772 ( (uint32_t) ssl[1] << 16 ) |
773 ( (uint32_t) ssl[2] << 8 ) |
774 ( (uint32_t) ssl[3] );
775 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100776 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
777 }
778
779 if( ssl < end )
780 {
781 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100782 }
783
784 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
785 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100786 CHECK_SSL_END( 1 );
787 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100788 }
789
790 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
791 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100792 CHECK_SSL_END( 1 );
793 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100794 }
795
796 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
797 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100798 CHECK_SSL_END( 1 );
799 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100800 }
801
802 if( 0 != ( end - ssl ) )
803 {
804 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
805 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100806}
807
808/*
809 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100810 * about the context from provided data. This function was built based on
811 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
812 * due to dependencies on the mbedTLS configuration and the configuration of
813 * the context when serialization was created.
814 *
815 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200816 * // header
817 * uint8 version[3];
818 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100819 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200820 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100821 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
822 * // transform sub-structure
823 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200824 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100825 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200826 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100827 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
828 * // fields from ssl_context
829 * uint32 badmac_seen; // DTLS: number of records with failing MAC
830 * uint64 in_window_top; // DTLS: last validated record seq_num
831 * uint64 in_window; // DTLS: bitmask for replay protection
832 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
833 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
834 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200835 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100836 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
837 *
838 * /p ssl pointer to serialized session
839 * /p len number of bytes in the buffer
840 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100841void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100842{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100843 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100844 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100845 int session_cfg_flag;
846 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100847
848 printf( "\nMbed TLS version:\n" );
849
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100850 CHECK_SSL_END( 3 + 2 + 3 );
851
852 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
853 printf( "\tminor %u\n", (uint32_t) *ssl++ );
854 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100855
856 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100857
858 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
859 ssl += 2;
860
861 context_cfg_flag = ( (int) ssl[0] << 16 ) |
862 ( (int) ssl[1] << 8 ) |
863 ( (int) ssl[2] ) ;
864 ssl += 3;
865
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100866 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
867 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
868
869 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
870 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
871 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
872 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
873 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
874 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
875 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
876
877 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
878 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
879 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
880 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
881
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100882 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100883 session_len = ( (uint32_t) ssl[0] << 24 ) |
884 ( (uint32_t) ssl[1] << 16 ) |
885 ( (uint32_t) ssl[2] << 8 ) |
886 ( (uint32_t) ssl[3] );
887 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100888 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100889
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100890 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100891 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
892 ssl += session_len;
893
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100894 printf( "\nRandom bytes:\n\t");
895
896 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
897 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100898 ssl += TRANSFORM_RANDBYTE_LEN;
899
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100900 printf( "\nContext others:\n" );
901
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100902 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
903 {
904 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100905
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100906 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100907 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100908 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100909
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100910 printf( "\tin CID : " );
911 if( cid_len > 0 )
912 {
913 CHECK_SSL_END( cid_len );
914 print_hex( ssl, cid_len, 20, "\t" );
915 ssl += cid_len;
916 }
917 else
918 {
919 printf( "none\n" );
920 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100921
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100922 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100923 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100924 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100925
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100926 printf( "\tout CID : " );
927 if( cid_len > 0 )
928 {
929 CHECK_SSL_END( cid_len );
930 print_hex( ssl, cid_len, 20, "\t" );
931 ssl += cid_len;
932 }
933 else
934 {
935 printf( "none\n" );
936 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100937 }
938
939 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
940 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100941 uint32_t badmac_seen;
942
943 CHECK_SSL_END( 4 );
944 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
945 ( (uint32_t) ssl[1] << 16 ) |
946 ( (uint32_t) ssl[2] << 8 ) |
947 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100948 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100949 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100950
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100951 /* value 'in_window_top' from mbedtls_ssl_context */
952 printf( "\tlast validated record sequence no. : " );
953 CHECK_SSL_END( 8 );
954 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100955 ssl += 8;
956
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100957 /* value 'in_window' from mbedtls_ssl_context */
958 printf( "\tbitmask for replay detection : " );
959 CHECK_SSL_END( 8 );
960 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100961 ssl += 8;
962 }
963
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100964 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100965 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100966 CHECK_SSL_END( 1 );
967 printf( "\tDTLS datagram packing : %s\n",
968 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100969 }
970
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100971 /* value 'cur_out_ctr' from mbedtls_ssl_context */
972 printf( "\toutgoing record sequence no. : ");
973 CHECK_SSL_END( 8 );
974 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100975 ssl += 8;
976
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100977 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100978 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100979 uint16_t mtu;
980 CHECK_SSL_END( 2 );
981 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100982 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100983 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100984 }
985
986
987 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
988 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100989 uint8_t alpn_len;
990
991 CHECK_SSL_END( 1 );
992 alpn_len = *ssl++;
993 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
994
995 printf( "\tALPN negotiation : " );
996 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100997 if( alpn_len > 0 )
998 {
999 if( strlen( (const char*) ssl ) == alpn_len )
1000 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001001 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001002 }
1003 else
1004 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001005 printf( "\n" );
1006 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001007 }
1008 ssl += alpn_len;
1009 }
1010 else
1011 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001012 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001013 }
1014 }
1015
Piotr Nowicki4e192002020-03-18 17:27:29 +01001016 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001017 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001018 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001019 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001020 printf( "\n" );
1021}
1022
Piotr Nowicki9370f902020-03-13 14:43:22 +01001023int main( int argc, char *argv[] )
1024{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001025 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001026
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001027 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001028 uint8_t *b64_buf = NULL;
1029 uint8_t *ssl_buf = NULL;
1030 size_t b64_max_len = SSL_INIT_LEN;
1031 size_t ssl_max_len = SSL_INIT_LEN;
1032 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001033
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001034 /* The 'b64_file' is opened when parsing arguments to check that the
1035 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001036 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001037
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001038 if( NULL != b64_file )
1039 {
1040 b64_buf = malloc( SSL_INIT_LEN );
1041 ssl_buf = malloc( SSL_INIT_LEN );
1042
1043 if( NULL == b64_buf || NULL == ssl_buf )
1044 {
1045 printf_err( alloc_err );
1046 fclose( b64_file );
1047 b64_file = NULL;
1048 }
1049 }
1050
Piotr Nowicki14d31052020-03-16 14:05:22 +01001051 while( NULL != b64_file )
1052 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001053 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001054 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001055 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001056 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001057 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1058
1059 /* Allocate more memory if necessary. */
1060 if( ssl_required_len > ssl_max_len )
1061 {
1062 void *ptr = realloc( ssl_buf, ssl_required_len );
1063 if( NULL == ptr )
1064 {
1065 printf_err( alloc_err );
1066 fclose( b64_file );
1067 b64_file = NULL;
1068 break;
1069 }
1070 ssl_buf = ptr;
1071 ssl_max_len = ssl_required_len;
1072 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001073
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001074 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001075
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001076 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001077 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001078
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001079 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001080 if( ret != 0)
1081 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001082 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1083 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001084 continue;
1085 }
1086
1087 if( debug )
1088 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001089 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001090 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001091 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001092
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001093 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001094
Piotr Nowicki14d31052020-03-16 14:05:22 +01001095 }
1096 else
1097 {
1098 fclose( b64_file );
1099 b64_file = NULL;
1100 }
1101 }
1102
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001103 free( b64_buf );
1104 free( ssl_buf );
1105
1106 if( b64_counter > 0 )
1107 {
1108 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1109 }
1110 else
1111 {
1112 printf( "Finished. No valid base64 code found\n" );
1113 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001114
Piotr Nowicki9370f902020-03-13 14:43:22 +01001115 return 0;
1116}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001117
1118#endif /* MBEDTLS_X509_CRT_PARSE_C */