blob: 2c3e0e7142578194cbb4690bd9714c1f037cdaf2 [file] [log] [blame]
Piotr Nowicki9370f902020-03-13 14:43:22 +01001/*
2 * MbedTLS SSL context deserializer from base64 code
3 *
4 * Copyright (C) 2006-2020, ARM Limited, All Rights Reserved
5 * 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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
Piotr Nowickif86192f2020-03-26 11:45:42 +010022#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
23#define _CRT_SECURE_NO_DEPRECATE 1
24#endif
25
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010026#include <stdio.h>
27#include <stdlib.h>
Piotr Nowicki14d31052020-03-16 14:05:22 +010028#include <stdint.h>
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010029#include <stdarg.h>
30#include <string.h>
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010031#include <time.h>
32#include "mbedtls/ssl.h"
Piotr Nowickic7d681c2020-03-17 09:51:31 +010033#include "mbedtls/error.h"
34#include "mbedtls/base64.h"
Piotr Nowicki4e192002020-03-18 17:27:29 +010035#include "mbedtls/md.h"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010036#include "mbedtls/md_internal.h"
37#include "mbedtls/x509_crt.h"
38#include "mbedtls/ssl_ciphersuites.h"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010039
40/*
41 * This program version
42 */
Piotr Nowickibc876d42020-03-26 12:49:15 +010043#define PROG_NAME "ssl_context_info"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010044#define VER_MAJOR 0
45#define VER_MINOR 1
46
47/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010048 * Flags copied from the mbedTLS library.
49 */
50#define SESSION_CONFIG_TIME_BIT ( 1 << 0 )
51#define SESSION_CONFIG_CRT_BIT ( 1 << 1 )
52#define SESSION_CONFIG_CLIENT_TICKET_BIT ( 1 << 2 )
53#define SESSION_CONFIG_MFL_BIT ( 1 << 3 )
54#define SESSION_CONFIG_TRUNC_HMAC_BIT ( 1 << 4 )
55#define SESSION_CONFIG_ETM_BIT ( 1 << 5 )
56#define SESSION_CONFIG_TICKET_BIT ( 1 << 6 )
57
58#define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ( 1 << 0 )
59#define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ( 1 << 1 )
60#define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ( 1 << 2 )
61#define CONTEXT_CONFIG_ALPN_BIT ( 1 << 3 )
62
Piotr Nowickiab3ecd82020-03-18 15:12:41 +010063#define TRANSFORM_RANDBYTE_LEN 64
64
Piotr Nowicki6b2baf92020-03-17 15:36:52 +010065/*
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +020066 * Minimum and maximum number of bytes for specific data: context, sessions,
67 * certificates, tickets and buffers in the program. The context and session
68 * size values have been calculated based on the 'print_deserialized_ssl_context()'
69 * and 'print_deserialized_ssl_session()' content.
70 */
71#define MIN_CONTEXT_LEN 84
72#define MIN_SESSION_LEN 88
73
74#define MAX_CONTEXT_LEN 875 /* without session data */
75#define MAX_SESSION_LEN 109 /* without certificate and ticket data */
76#define MAX_CERTIFICATE_LEN ( ( 1 << 24 ) - 1 )
77#define MAX_TICKET_LEN ( ( 1 << 24 ) - 1 )
78
79#define MIN_SERIALIZED_DATA ( MIN_CONTEXT_LEN + MIN_SESSION_LEN )
80#define MAX_SERIALIZED_DATA ( MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
81 MAX_CERTIFICATE_LEN + MAX_TICKET_LEN )
82
83#define MIN_BASE64_LEN ( MIN_SERIALIZED_DATA * 4 / 3 )
84#define MAX_BASE64_LEN ( MAX_SERIALIZED_DATA * 4 / 3 + 3 )
85
86/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +010087 * A macro that prevents from reading out of the ssl buffer range.
88 */
89#define CHECK_SSL_END( LEN ) \
90do \
91{ \
92 if( end - ssl < (int)( LEN ) ) \
93 { \
94 printf_err( "%s", buf_ln_err ); \
95 return; \
96 } \
97} while( 0 )
98
99/*
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100100 * Global values
101 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100102FILE *b64_file = NULL; /* file with base64 codes to deserialize */
103char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
104char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
105char debug = 0; /* flag for debug messages */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200106const char alloc_err[] = "Cannot allocate memory\n";
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100107const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100108
109/*
110 * Basic printing functions
111 */
112void print_version( )
113{
114 printf( "%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR );
115}
116
117void print_usage( )
118{
119 print_version();
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100120 printf( "\nThis program is used to deserialize an mbedTLS SSL session from the base64 code provided\n"
121 "in the text file. The program can deserialize many codes from one file, but they must be\n"
122 "separated, e.g. by a newline.\n\n" );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100123 printf(
124 "Usage:\n"
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100125 "\t-f path - Path to the file with base64 code\n"
126 "\t-v - Show version\n"
127 "\t-h - Show this usage\n"
128 "\t-d - Print more information\n"
129 "\t--keep-peer-cert=0 - Use this option if you know that the mbedTLS library\n"
130 "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
131 "\t flag. You can also use it if there are some problems with reading\n"
132 "\t the information about certificate\n"
133 "\t--dtls-protocol=0 - Use this option if you know that the mbedTLS library\n"
134 "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100135 "\n"
136 );
137}
138
139void printf_dbg( const char *str, ... )
140{
141 if( debug )
142 {
143 va_list args;
144 va_start( args, str );
145 printf( "debug: " );
146 vprintf( str, args );
147 fflush( stdout );
148 va_end( args );
149 }
150}
151
152void printf_err( const char *str, ... )
153{
154 va_list args;
155 va_start( args, str );
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100156 fflush( stdout );
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100157 fprintf( stderr, "ERROR: " );
158 vfprintf( stderr, str, args );
159 fflush( stderr );
160 va_end( args );
161}
162
163/*
164 * Exit from the program in case of error
165 */
166void error_exit()
167{
168 if( NULL != b64_file )
169 {
170 fclose( b64_file );
171 }
172 exit( -1 );
173}
174
175/*
176 * This function takes the input arguments of this program
177 */
178void parse_arguments( int argc, char *argv[] )
179{
180 int i = 1;
181
182 if( argc < 2 )
183 {
184 print_usage();
185 error_exit();
186 }
187
188 while( i < argc )
189 {
190 if( strcmp( argv[i], "-d" ) == 0 )
191 {
192 debug = 1;
193 }
194 else if( strcmp( argv[i], "-h" ) == 0 )
195 {
196 print_usage();
197 }
198 else if( strcmp( argv[i], "-v" ) == 0 )
199 {
200 print_version();
201 }
202 else if( strcmp( argv[i], "-f" ) == 0 )
203 {
204 if( ++i >= argc )
205 {
206 printf_err( "File path is empty\n" );
207 error_exit();
208 }
209
210 if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
211 {
212 printf_err( "Cannot find file \"%s\"\n", argv[i] );
213 error_exit();
214 }
215 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100216 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
217 {
218 conf_keep_peer_certificate = 0;
219 }
220 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
221 {
222 conf_dtls_proto = 0;
223 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100224 else
225 {
226 print_usage();
227 error_exit();
228 }
229
230 i++;
231 }
232}
233
Piotr Nowicki14d31052020-03-16 14:05:22 +0100234/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100235 * This function prints base64 code to the stdout
236 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100237void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100238{
239 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100240 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100241 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100242 while( b < end )
243 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100244 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100245 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100246 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100247 i = 0;
248 }
249 printf( "%c", *b++ );
250 }
251 printf( "\n" );
252 fflush( stdout );
253}
254
255/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100256 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100257 *
258 * /p b buffer with data to print
259 * /p len number of bytes to print
260 * /p in_line number of bytes in one line
261 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100262 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100263void print_hex( const uint8_t *b, size_t len,
264 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100265{
266 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100267 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100268
269 if( prefix == NULL )
270 {
271 prefix = "";
272 }
273
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100274 while( b < end )
275 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100276 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100277 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100278 printf( "\n%s", prefix );
279 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100280 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100281 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100282 }
283 printf("\n");
284 fflush(stdout);
285}
286
287/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100288 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
289 */
290void print_time( const time_t *time )
291{
292 char buf[20];
293 struct tm *t = gmtime( time );
294 static const char format[] = "%Y-%m-%d %H:%M:%S";
295 if( NULL != t )
296 {
297 strftime( buf, sizeof( buf ), format, t );
298 printf( "%s\n", buf );
299 }
300 else
301 {
302 printf( "unknown\n" );
303 }
304}
305
306/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100307 * Print the input string if the bit is set in the value
308 */
309void print_if_bit( const char *str, int bit, int val )
310{
311 if( bit & val )
312 {
313 printf( "\t%s\n", str );
314 }
315}
316
317/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100318 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
319 */
320const char * get_enabled_str( int is_en )
321{
322 return ( is_en ) ? "enabled" : "disabled";
323}
324
325/*
326 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
327 */
328const char * get_mfl_str( int mfl_code )
329{
330 switch( mfl_code )
331 {
332 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
333 return "none";
334 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
335 return "512";
336 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
337 return "1024";
338 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
339 return "2048";
340 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
341 return "4096";
342 default:
343 return "error";
344 }
345}
346
347/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100348 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
349 * previously. After each call to this function, the internal file position
350 * indicator of the global b64_file is advanced.
351 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200352 * Note - This function checks the size of the input buffer and if necessary,
353 * increases it to the maximum MAX_BASE64_LEN
354 *
355 * /p b64 pointer to the pointer of the buffer for input data
356 * /p max_len pointer to the current buffer capacity. It can be changed if
357 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100358 *
359 * \retval number of bytes written in to the b64 buffer or 0 in case no more
360 * data was found
361 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200362size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100363{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200364 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100365 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100366 char pad = 0;
367 char c = 0;
368
369 while( EOF != c )
370 {
371 char c_valid = 0;
372
373 c = (char) fgetc( b64_file );
374
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200375 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100376 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200377 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100378 {
379 c_valid = 1;
380 pad = 2;
381 }
382 }
383 else if( ( c >= 'A' && c <= 'Z' ) ||
384 ( c >= 'a' && c <= 'z' ) ||
385 ( c >= '0' && c <= '9' ) ||
386 c == '+' || c == '/' )
387 {
388 c_valid = 1;
389 }
390 else if( c == '=' )
391 {
392 c_valid = 1;
393 pad = 1;
394 }
395 else if( c == '-' )
396 {
397 c = '+';
398 c_valid = 1;
399 }
400 else if( c == '_' )
401 {
402 c = '/';
403 c_valid = 1;
404 }
405
406 if( c_valid )
407 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200408 /* A string of characters that could be a base64 code. */
409 valid_balance++;
410
411 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100412 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200413 ( *b64 )[ len++ ] = c;
414 }
415 else if( *max_len < MAX_BASE64_LEN )
416 {
417 /* Current buffer is too small, but can be resized. */
418 void *ptr;
419 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
420 *max_len + 4096 : MAX_BASE64_LEN;
421
422 ptr = realloc( *b64, new_size );
423 if( NULL == ptr )
424 {
425 printf_err( alloc_err );
426 return 0;
427 }
428 *b64 = ptr;
429 *max_len = new_size;
430 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100431 }
432 else
433 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200434 /* Too much data so it will be treated as invalid */
435 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100436 }
437 }
438 else if( len > 0 )
439 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200440 /* End of a string that could be a base64 code, but need to check
441 * that the length of the characters is correct. */
442
443 valid_balance--;
444
445 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100446 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200447 printf_dbg( "The code found is too small to be a SSL context.\n" );
448 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100449 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200450 else if( len > *max_len )
451 {
452 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
453 len = pad = 0;
454 }
455 else if( len % 4 != 0 )
456 {
457 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
458 len = pad = 0;
459 }
460 else
461 {
462 /* Base64 code with valid character length. */
463 return len;
464 }
465 }
466 else
467 {
468 valid_balance--;
469 }
470
471 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
472 if( valid_balance < -100 )
473 {
474 printf_err( "Too many bad symbols detected. File check aborted.\n" );
475 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100476 }
477 }
478
479 printf_dbg( "End of file\n" );
480 return 0;
481}
482
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100483/*
484 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100485 * about the certificates from provided data.
486 *
487 * /p ssl pointer to serialized certificate
488 * /p len number of bytes in the buffer
489*/
490void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
491{
492 enum { STRLEN = 4096 };
493 mbedtls_x509_crt crt;
494 int ret;
495 char str[STRLEN];
496
497 printf( "\nCertificate:\n" );
498
499 mbedtls_x509_crt_init( &crt );
500 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
501 if( 0 != ret )
502 {
503 mbedtls_strerror( ret, str, STRLEN );
504 printf_err( "Invalid format of X.509 - %s\n", str );
505 printf( "Cannot deserialize:\n\t" );
506 print_hex( ssl, len, 25, "\t" );
507 }
508 else
509 {
510 mbedtls_x509_crt *current = &crt;
511
512 while( current != NULL )
513 {
514 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
515 if( 0 > ret )
516 {
517 mbedtls_strerror( ret, str, STRLEN );
518 printf_err( "Cannot write to the output - %s\n", str );
519 }
520 else
521 {
522 printf( "%s", str );
523 }
524
525 current = current->next;
526
527 if( current )
528 {
529 printf( "\n" );
530 }
531
532 }
533 }
534
535 mbedtls_x509_crt_free( &crt );
536}
537
538/*
539 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100540 * about the session from provided data. This function was built based on
541 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
542 * due to dependencies on the mbedTLS configuration.
543 *
544 * The data structure in the buffer:
545 * uint64 start_time;
546 * uint8 ciphersuite[2]; // defined by the standard
547 * uint8 compression; // 0 or 1
548 * uint8 session_id_len; // at most 32
549 * opaque session_id[32];
550 * opaque master[48]; // fixed length in the standard
551 * uint32 verify_result;
552 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
553 * opaque ticket<0..2^24-1>; // length 0 means no ticket
554 * uint32 ticket_lifetime;
555 * uint8 mfl_code; // up to 255 according to standard
556 * uint8 trunc_hmac; // 0 or 1
557 * uint8 encrypt_then_mac; // 0 or 1
558 *
559 * /p ssl pointer to serialized session
560 * /p len number of bytes in the buffer
561 * /p session_cfg_flag session configuration flags
562 */
563void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
564 int session_cfg_flag )
565{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100566 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
567 int ciphersuite_id;
568 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100569 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100570 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100571
572 printf( "\nSession info:\n" );
573
574 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
575 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100576 uint64_t start;
577 CHECK_SSL_END( 8 );
578 start = ( (uint64_t) ssl[0] << 56 ) |
579 ( (uint64_t) ssl[1] << 48 ) |
580 ( (uint64_t) ssl[2] << 40 ) |
581 ( (uint64_t) ssl[3] << 32 ) |
582 ( (uint64_t) ssl[4] << 24 ) |
583 ( (uint64_t) ssl[5] << 16 ) |
584 ( (uint64_t) ssl[6] << 8 ) |
585 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100586 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100587 printf( "\tstart time : " );
588 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100589 }
590
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100591 CHECK_SSL_END( 2 );
592 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
593 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100594 ssl += 2;
595
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100596 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
597 if( ciphersuite_info == NULL )
598 {
599 printf_err( "Cannot find ciphersuite info\n" );
600 }
601 else
602 {
603 const mbedtls_cipher_info_t *cipher_info;
604 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100605
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100606 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
607 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
608
609 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
610 if( cipher_info == NULL )
611 {
612 printf_err( "Cannot find cipher info\n" );
613 }
614 else
615 {
616 printf( "\tcipher : %s\n", cipher_info->name );
617 }
618
619 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
620 if( md_info == NULL )
621 {
622 printf_err( "Cannot find Message-Digest info\n" );
623 }
624 else
625 {
626 printf( "\tMessage-Digest : %s\n", md_info->name );
627 }
628 }
629
630 CHECK_SSL_END( 1 );
631 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
632
633 /* Note - Here we can get session ID length from serialized data, but we
634 * use hardcoded 32-bytes length. This approach was taken from
635 * 'mbedtls_ssl_session_load()'. */
636 CHECK_SSL_END( 1 + 32 );
637 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
638 printf( "\tsession ID : ");
639 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100640 ssl += 32;
641
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100642 printf( "\tmaster secret : ");
643 CHECK_SSL_END( 48 );
644 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100645 ssl += 48;
646
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100647 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100648 verify_result = ( (uint32_t) ssl[0] << 24 ) |
649 ( (uint32_t) ssl[1] << 16 ) |
650 ( (uint32_t) ssl[2] << 8 ) |
651 ( (uint32_t) ssl[3] );
652 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100653 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100654
655 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
656 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100657 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100658 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100659 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100660 cert_len = ( (uint32_t) ssl[0] << 16 ) |
661 ( (uint32_t) ssl[1] << 8 ) |
662 ( (uint32_t) ssl[2] );
663 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100664 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100665
666 if( cert_len > 0 )
667 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100668 CHECK_SSL_END( cert_len );
669 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100670 ssl += cert_len;
671 }
672 }
673 else
674 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100675 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100676
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100677 CHECK_SSL_END( 1 );
678 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100679 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100680 case MBEDTLS_MD_NONE:
681 printf( "none\n" );
682 break;
683 case MBEDTLS_MD_MD2:
684 printf( "MD2\n" );
685 break;
686 case MBEDTLS_MD_MD4:
687 printf( "MD4\n" );
688 break;
689 case MBEDTLS_MD_MD5:
690 printf( "MD5\n" );
691 break;
692 case MBEDTLS_MD_SHA1:
693 printf( "SHA1\n" );
694 break;
695 case MBEDTLS_MD_SHA224:
696 printf( "SHA224\n" );
697 break;
698 case MBEDTLS_MD_SHA256:
699 printf( "SHA256\n" );
700 break;
701 case MBEDTLS_MD_SHA384:
702 printf( "SHA384\n" );
703 break;
704 case MBEDTLS_MD_SHA512:
705 printf( "SHA512\n" );
706 break;
707 case MBEDTLS_MD_RIPEMD160:
708 printf( "RIPEMD160\n" );
709 break;
710 default:
711 printf( "undefined or erroneous\n" );
712 break;
713 }
714
715 CHECK_SSL_END( 1 );
716 cert_len = (uint32_t) *ssl++;
717 printf_dbg( "Message-Digest length: %u\n", cert_len );
718
719 if( cert_len > 0 )
720 {
721 printf( "\tPeer digest cert : " );
722 CHECK_SSL_END( cert_len );
723 print_hex( ssl, cert_len, 16, "\t " );
724 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100725 }
726 }
727 }
728
729 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
730 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100731 printf( "\nTicket:\n" );
732
733 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100734 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
735 ( (uint32_t) ssl[1] << 8 ) |
736 ( (uint32_t) ssl[2] );
737 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100738 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100739
740 if( ticket_len > 0 )
741 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100742 printf( "\t" );
743 CHECK_SSL_END( ticket_len );
744 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100745 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100746 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100747 }
748
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100749 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100750 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
751 ( (uint32_t) ssl[1] << 16 ) |
752 ( (uint32_t) ssl[2] << 8 ) |
753 ( (uint32_t) ssl[3] );
754 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100755 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
756 }
757
758 if( ssl < end )
759 {
760 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100761 }
762
763 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
764 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100765 CHECK_SSL_END( 1 );
766 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100767 }
768
769 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
770 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100771 CHECK_SSL_END( 1 );
772 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100773 }
774
775 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
776 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100777 CHECK_SSL_END( 1 );
778 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100779 }
780
781 if( 0 != ( end - ssl ) )
782 {
783 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
784 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100785}
786
787/*
788 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100789 * about the context from provided data. This function was built based on
790 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
791 * due to dependencies on the mbedTLS configuration and the configuration of
792 * the context when serialization was created.
793 *
794 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200795 * // header
796 * uint8 version[3];
797 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100798 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200799 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100800 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
801 * // transform sub-structure
802 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200803 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100804 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200805 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100806 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
807 * // fields from ssl_context
808 * uint32 badmac_seen; // DTLS: number of records with failing MAC
809 * uint64 in_window_top; // DTLS: last validated record seq_num
810 * uint64 in_window; // DTLS: bitmask for replay protection
811 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
812 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
813 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200814 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100815 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
816 *
817 * /p ssl pointer to serialized session
818 * /p len number of bytes in the buffer
819 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100820void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100821{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100822 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100823 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100824 int session_cfg_flag;
825 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100826
827 printf( "\nMbed TLS version:\n" );
828
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100829 CHECK_SSL_END( 3 + 2 + 3 );
830
831 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
832 printf( "\tminor %u\n", (uint32_t) *ssl++ );
833 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100834
835 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100836
837 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
838 ssl += 2;
839
840 context_cfg_flag = ( (int) ssl[0] << 16 ) |
841 ( (int) ssl[1] << 8 ) |
842 ( (int) ssl[2] ) ;
843 ssl += 3;
844
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100845 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
846 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
847
848 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
849 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
850 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
851 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
852 print_if_bit( "MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag );
853 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag );
854 print_if_bit( "MBEDTLS_SSL_SESSION_TICKETS and client", SESSION_CONFIG_CLIENT_TICKET_BIT, session_cfg_flag );
855
856 print_if_bit( "MBEDTLS_SSL_DTLS_CONNECTION_ID", CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT, context_cfg_flag );
857 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
858 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
859 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
860
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100861 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100862 session_len = ( (uint32_t) ssl[0] << 24 ) |
863 ( (uint32_t) ssl[1] << 16 ) |
864 ( (uint32_t) ssl[2] << 8 ) |
865 ( (uint32_t) ssl[3] );
866 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100867 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100868
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100869 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100870 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
871 ssl += session_len;
872
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100873 printf( "\nRandom bytes:\n\t");
874
875 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
876 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100877 ssl += TRANSFORM_RANDBYTE_LEN;
878
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100879 printf( "\nContext others:\n" );
880
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100881 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
882 {
883 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100884
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100885 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100886 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100887 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100888
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100889 printf( "\tin CID : " );
890 if( cid_len > 0 )
891 {
892 CHECK_SSL_END( cid_len );
893 print_hex( ssl, cid_len, 20, "\t" );
894 ssl += cid_len;
895 }
896 else
897 {
898 printf( "none\n" );
899 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100900
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100901 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100902 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100903 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100904
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100905 printf( "\tout CID : " );
906 if( cid_len > 0 )
907 {
908 CHECK_SSL_END( cid_len );
909 print_hex( ssl, cid_len, 20, "\t" );
910 ssl += cid_len;
911 }
912 else
913 {
914 printf( "none\n" );
915 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100916 }
917
918 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
919 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100920 uint32_t badmac_seen;
921
922 CHECK_SSL_END( 4 );
923 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
924 ( (uint32_t) ssl[1] << 16 ) |
925 ( (uint32_t) ssl[2] << 8 ) |
926 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100927 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100928 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100929
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100930 /* value 'in_window_top' from mbedtls_ssl_context */
931 printf( "\tlast validated record sequence no. : " );
932 CHECK_SSL_END( 8 );
933 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100934 ssl += 8;
935
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100936 /* value 'in_window' from mbedtls_ssl_context */
937 printf( "\tbitmask for replay detection : " );
938 CHECK_SSL_END( 8 );
939 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100940 ssl += 8;
941 }
942
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100943 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100944 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100945 CHECK_SSL_END( 1 );
946 printf( "\tDTLS datagram packing : %s\n",
947 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100948 }
949
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100950 /* value 'cur_out_ctr' from mbedtls_ssl_context */
951 printf( "\toutgoing 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 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100957 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100958 uint16_t mtu;
959 CHECK_SSL_END( 2 );
960 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100961 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100962 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100963 }
964
965
966 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
967 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100968 uint8_t alpn_len;
969
970 CHECK_SSL_END( 1 );
971 alpn_len = *ssl++;
972 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
973
974 printf( "\tALPN negotiation : " );
975 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100976 if( alpn_len > 0 )
977 {
978 if( strlen( (const char*) ssl ) == alpn_len )
979 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100980 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100981 }
982 else
983 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100984 printf( "\n" );
985 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100986 }
987 ssl += alpn_len;
988 }
989 else
990 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100991 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100992 }
993 }
994
Piotr Nowicki4e192002020-03-18 17:27:29 +0100995 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100996 {
Piotr Nowicki4e192002020-03-18 17:27:29 +0100997 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100998 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100999 printf( "\n" );
1000}
1001
Piotr Nowicki9370f902020-03-13 14:43:22 +01001002int main( int argc, char *argv[] )
1003{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001004 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001005
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001006 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001007 uint8_t *b64_buf = NULL;
1008 uint8_t *ssl_buf = NULL;
1009 size_t b64_max_len = SSL_INIT_LEN;
1010 size_t ssl_max_len = SSL_INIT_LEN;
1011 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001012
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001013 /* The 'b64_file' is opened when parsing arguments to check that the
1014 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001015 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001016
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001017 if( NULL != b64_file )
1018 {
1019 b64_buf = malloc( SSL_INIT_LEN );
1020 ssl_buf = malloc( SSL_INIT_LEN );
1021
1022 if( NULL == b64_buf || NULL == ssl_buf )
1023 {
1024 printf_err( alloc_err );
1025 fclose( b64_file );
1026 b64_file = NULL;
1027 }
1028 }
1029
Piotr Nowicki14d31052020-03-16 14:05:22 +01001030 while( NULL != b64_file )
1031 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001032 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001033 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001034 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001035 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001036 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1037
1038 /* Allocate more memory if necessary. */
1039 if( ssl_required_len > ssl_max_len )
1040 {
1041 void *ptr = realloc( ssl_buf, ssl_required_len );
1042 if( NULL == ptr )
1043 {
1044 printf_err( alloc_err );
1045 fclose( b64_file );
1046 b64_file = NULL;
1047 break;
1048 }
1049 ssl_buf = ptr;
1050 ssl_max_len = ssl_required_len;
1051 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001052
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001053 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001054
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001055 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001056 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001057
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001058 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001059 if( ret != 0)
1060 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001061 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1062 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001063 continue;
1064 }
1065
1066 if( debug )
1067 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001068 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001069 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001070 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001071
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001072 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001073
Piotr Nowicki14d31052020-03-16 14:05:22 +01001074 }
1075 else
1076 {
1077 fclose( b64_file );
1078 b64_file = NULL;
1079 }
1080 }
1081
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001082 free( b64_buf );
1083 free( ssl_buf );
1084
1085 if( b64_counter > 0 )
1086 {
1087 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1088 }
1089 else
1090 {
1091 printf( "Finished. No valid base64 code found\n" );
1092 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001093
Piotr Nowicki9370f902020-03-13 14:43:22 +01001094 return 0;
1095}