blob: 9bea31c69024bae0cdc8dad556dfc137def3542b [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 Nowicki97dcb1c2020-04-09 17:00:57 +020022#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
Piotr Nowickif86192f2020-03-26 11:45:42 +010026#endif
27
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +010028#include <stdio.h>
29#include <stdlib.h>
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +020030
31#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C)
32int main( void )
33{
34 printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C not defined.\n");
35 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
225 if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
226 {
227 printf_err( "Cannot find file \"%s\"\n", argv[i] );
228 error_exit();
229 }
230 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100231 else if( strcmp( argv[i], "--keep-peer-cert=0" ) == 0 )
232 {
233 conf_keep_peer_certificate = 0;
234 }
235 else if( strcmp( argv[i], "--dtls-protocol=0" ) == 0 )
236 {
237 conf_dtls_proto = 0;
238 }
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +0100239 else
240 {
241 print_usage();
242 error_exit();
243 }
244
245 i++;
246 }
247}
248
Piotr Nowicki14d31052020-03-16 14:05:22 +0100249/*
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100250 * This function prints base64 code to the stdout
251 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100252void print_b64( const uint8_t *b, size_t len )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100253{
254 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100255 const uint8_t *end = b + len;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100256 printf("\t");
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100257 while( b < end )
258 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100259 if( ++i > 75 )
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100260 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100261 printf( "\n\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +0100262 i = 0;
263 }
264 printf( "%c", *b++ );
265 }
266 printf( "\n" );
267 fflush( stdout );
268}
269
270/*
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100271 * This function prints hex code from the buffer to the stdout.
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100272 *
273 * /p b buffer with data to print
274 * /p len number of bytes to print
275 * /p in_line number of bytes in one line
276 * /p prefix prefix for the new lines
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100277 */
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100278void print_hex( const uint8_t *b, size_t len,
279 const size_t in_line, const char *prefix )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100280{
281 size_t i = 0;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100282 const uint8_t *end = b + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100283
284 if( prefix == NULL )
285 {
286 prefix = "";
287 }
288
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100289 while( b < end )
290 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100291 if( ++i > in_line )
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100292 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100293 printf( "\n%s", prefix );
294 i = 1;
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100295 }
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100296 printf( "%02X ", (uint8_t) *b++ );
Piotr Nowickic7d681c2020-03-17 09:51:31 +0100297 }
298 printf("\n");
299 fflush(stdout);
300}
301
302/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100303 * Print the value of time_t in format e.g. 2020-01-23 13:05:59
304 */
305void print_time( const time_t *time )
306{
307 char buf[20];
308 struct tm *t = gmtime( time );
309 static const char format[] = "%Y-%m-%d %H:%M:%S";
310 if( NULL != t )
311 {
312 strftime( buf, sizeof( buf ), format, t );
313 printf( "%s\n", buf );
314 }
315 else
316 {
317 printf( "unknown\n" );
318 }
319}
320
321/*
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100322 * Print the input string if the bit is set in the value
323 */
324void print_if_bit( const char *str, int bit, int val )
325{
326 if( bit & val )
327 {
328 printf( "\t%s\n", str );
329 }
330}
331
332/*
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100333 * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
334 */
335const char * get_enabled_str( int is_en )
336{
337 return ( is_en ) ? "enabled" : "disabled";
338}
339
340/*
341 * Return pointer to hardcoded MFL string value depending on the MFL code at the input
342 */
343const char * get_mfl_str( int mfl_code )
344{
345 switch( mfl_code )
346 {
347 case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
348 return "none";
349 case MBEDTLS_SSL_MAX_FRAG_LEN_512:
350 return "512";
351 case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
352 return "1024";
353 case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
354 return "2048";
355 case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
356 return "4096";
357 default:
358 return "error";
359 }
360}
361
362/*
Piotr Nowicki14d31052020-03-16 14:05:22 +0100363 * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
364 * previously. After each call to this function, the internal file position
365 * indicator of the global b64_file is advanced.
366 *
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200367 * Note - This function checks the size of the input buffer and if necessary,
368 * increases it to the maximum MAX_BASE64_LEN
369 *
370 * /p b64 pointer to the pointer of the buffer for input data
371 * /p max_len pointer to the current buffer capacity. It can be changed if
372 * the buffer needs to be increased
Piotr Nowicki14d31052020-03-16 14:05:22 +0100373 *
374 * \retval number of bytes written in to the b64 buffer or 0 in case no more
375 * data was found
376 */
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200377size_t read_next_b64_code( uint8_t **b64, size_t *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100378{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200379 int valid_balance = 0; /* balance between valid and invalid characters */
Piotr Nowicki14d31052020-03-16 14:05:22 +0100380 size_t len = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100381 char pad = 0;
382 char c = 0;
383
384 while( EOF != c )
385 {
386 char c_valid = 0;
387
388 c = (char) fgetc( b64_file );
389
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200390 if( pad > 0 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100391 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200392 if( c == '=' && pad == 1 )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100393 {
394 c_valid = 1;
395 pad = 2;
396 }
397 }
398 else if( ( c >= 'A' && c <= 'Z' ) ||
399 ( c >= 'a' && c <= 'z' ) ||
400 ( c >= '0' && c <= '9' ) ||
401 c == '+' || c == '/' )
402 {
403 c_valid = 1;
404 }
405 else if( c == '=' )
406 {
407 c_valid = 1;
408 pad = 1;
409 }
410 else if( c == '-' )
411 {
412 c = '+';
413 c_valid = 1;
414 }
415 else if( c == '_' )
416 {
417 c = '/';
418 c_valid = 1;
419 }
420
421 if( c_valid )
422 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200423 /* A string of characters that could be a base64 code. */
424 valid_balance++;
425
426 if( len < *max_len )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100427 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200428 ( *b64 )[ len++ ] = c;
429 }
430 else if( *max_len < MAX_BASE64_LEN )
431 {
432 /* Current buffer is too small, but can be resized. */
433 void *ptr;
434 size_t new_size = ( MAX_BASE64_LEN - 4096 > *max_len ) ?
435 *max_len + 4096 : MAX_BASE64_LEN;
436
437 ptr = realloc( *b64, new_size );
438 if( NULL == ptr )
439 {
440 printf_err( alloc_err );
441 return 0;
442 }
443 *b64 = ptr;
444 *max_len = new_size;
445 ( *b64 )[ len++ ] = c;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100446 }
447 else
448 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200449 /* Too much data so it will be treated as invalid */
450 len++;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100451 }
452 }
453 else if( len > 0 )
454 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200455 /* End of a string that could be a base64 code, but need to check
456 * that the length of the characters is correct. */
457
458 valid_balance--;
459
460 if( len < MIN_CONTEXT_LEN )
Piotr Nowicki14d31052020-03-16 14:05:22 +0100461 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200462 printf_dbg( "The code found is too small to be a SSL context.\n" );
463 len = pad = 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100464 }
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200465 else if( len > *max_len )
466 {
467 printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
468 len = pad = 0;
469 }
470 else if( len % 4 != 0 )
471 {
472 printf_err( "The length of the base64 code found should be a multiple of 4.\n" );
473 len = pad = 0;
474 }
475 else
476 {
477 /* Base64 code with valid character length. */
478 return len;
479 }
480 }
481 else
482 {
483 valid_balance--;
484 }
485
486 /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
487 if( valid_balance < -100 )
488 {
489 printf_err( "Too many bad symbols detected. File check aborted.\n" );
490 return 0;
Piotr Nowicki14d31052020-03-16 14:05:22 +0100491 }
492 }
493
494 printf_dbg( "End of file\n" );
495 return 0;
496}
497
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100498/*
499 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100500 * about the certificates from provided data.
501 *
502 * /p ssl pointer to serialized certificate
503 * /p len number of bytes in the buffer
504*/
505void print_deserialized_ssl_cert( const uint8_t *ssl, uint32_t len )
506{
507 enum { STRLEN = 4096 };
508 mbedtls_x509_crt crt;
509 int ret;
510 char str[STRLEN];
511
512 printf( "\nCertificate:\n" );
513
514 mbedtls_x509_crt_init( &crt );
515 ret = mbedtls_x509_crt_parse_der( &crt, ssl, len );
516 if( 0 != ret )
517 {
518 mbedtls_strerror( ret, str, STRLEN );
519 printf_err( "Invalid format of X.509 - %s\n", str );
520 printf( "Cannot deserialize:\n\t" );
521 print_hex( ssl, len, 25, "\t" );
522 }
523 else
524 {
525 mbedtls_x509_crt *current = &crt;
526
527 while( current != NULL )
528 {
529 ret = mbedtls_x509_crt_info( str, STRLEN, "\t", current );
530 if( 0 > ret )
531 {
532 mbedtls_strerror( ret, str, STRLEN );
533 printf_err( "Cannot write to the output - %s\n", str );
534 }
535 else
536 {
537 printf( "%s", str );
538 }
539
540 current = current->next;
541
542 if( current )
543 {
544 printf( "\n" );
545 }
546
547 }
548 }
549
550 mbedtls_x509_crt_free( &crt );
551}
552
553/*
554 * This function deserializes and prints to the stdout all obtained information
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100555 * about the session from provided data. This function was built based on
556 * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
557 * due to dependencies on the mbedTLS configuration.
558 *
559 * The data structure in the buffer:
560 * uint64 start_time;
561 * uint8 ciphersuite[2]; // defined by the standard
562 * uint8 compression; // 0 or 1
563 * uint8 session_id_len; // at most 32
564 * opaque session_id[32];
565 * opaque master[48]; // fixed length in the standard
566 * uint32 verify_result;
567 * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
568 * opaque ticket<0..2^24-1>; // length 0 means no ticket
569 * uint32 ticket_lifetime;
570 * uint8 mfl_code; // up to 255 according to standard
571 * uint8 trunc_hmac; // 0 or 1
572 * uint8 encrypt_then_mac; // 0 or 1
573 *
574 * /p ssl pointer to serialized session
575 * /p len number of bytes in the buffer
576 * /p session_cfg_flag session configuration flags
577 */
578void print_deserialized_ssl_session( const uint8_t *ssl, uint32_t len,
579 int session_cfg_flag )
580{
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100581 const struct mbedtls_ssl_ciphersuite_t * ciphersuite_info;
582 int ciphersuite_id;
583 uint32_t cert_len, ticket_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100584 uint32_t verify_result, ticket_lifetime;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100585 const uint8_t *end = ssl + len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100586
587 printf( "\nSession info:\n" );
588
589 if( session_cfg_flag & SESSION_CONFIG_TIME_BIT )
590 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100591 uint64_t start;
592 CHECK_SSL_END( 8 );
593 start = ( (uint64_t) ssl[0] << 56 ) |
594 ( (uint64_t) ssl[1] << 48 ) |
595 ( (uint64_t) ssl[2] << 40 ) |
596 ( (uint64_t) ssl[3] << 32 ) |
597 ( (uint64_t) ssl[4] << 24 ) |
598 ( (uint64_t) ssl[5] << 16 ) |
599 ( (uint64_t) ssl[6] << 8 ) |
600 ( (uint64_t) ssl[7] );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100601 ssl += 8;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100602 printf( "\tstart time : " );
603 print_time( (time_t*) &start );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100604 }
605
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100606 CHECK_SSL_END( 2 );
607 ciphersuite_id = ( (int) ssl[0] << 8 ) | (int) ssl[1];
608 printf_dbg( "Ciphersuite ID: %d\n", ciphersuite_id );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100609 ssl += 2;
610
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100611 ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
612 if( ciphersuite_info == NULL )
613 {
614 printf_err( "Cannot find ciphersuite info\n" );
615 }
616 else
617 {
618 const mbedtls_cipher_info_t *cipher_info;
619 const mbedtls_md_info_t *md_info;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100620
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100621 printf( "\tciphersuite : %s\n", ciphersuite_info->name );
622 printf( "\tcipher flags : 0x%02X\n", ciphersuite_info->flags );
623
624 cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
625 if( cipher_info == NULL )
626 {
627 printf_err( "Cannot find cipher info\n" );
628 }
629 else
630 {
631 printf( "\tcipher : %s\n", cipher_info->name );
632 }
633
634 md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
635 if( md_info == NULL )
636 {
637 printf_err( "Cannot find Message-Digest info\n" );
638 }
639 else
640 {
641 printf( "\tMessage-Digest : %s\n", md_info->name );
642 }
643 }
644
645 CHECK_SSL_END( 1 );
646 printf( "\tcompression : %s\n", get_enabled_str( *ssl++ ) );
647
648 /* Note - Here we can get session ID length from serialized data, but we
649 * use hardcoded 32-bytes length. This approach was taken from
650 * 'mbedtls_ssl_session_load()'. */
651 CHECK_SSL_END( 1 + 32 );
652 printf_dbg( "Session id length: %u\n", (uint32_t) *ssl++ );
653 printf( "\tsession ID : ");
654 print_hex( ssl, 32, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100655 ssl += 32;
656
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100657 printf( "\tmaster secret : ");
658 CHECK_SSL_END( 48 );
659 print_hex( ssl, 48, 16, "\t " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100660 ssl += 48;
661
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100662 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100663 verify_result = ( (uint32_t) ssl[0] << 24 ) |
664 ( (uint32_t) ssl[1] << 16 ) |
665 ( (uint32_t) ssl[2] << 8 ) |
666 ( (uint32_t) ssl[3] );
667 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100668 printf( "\tverify result : 0x%08X\n", verify_result );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100669
670 if( SESSION_CONFIG_CRT_BIT & session_cfg_flag )
671 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100672 if( conf_keep_peer_certificate )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100673 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100674 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100675 cert_len = ( (uint32_t) ssl[0] << 16 ) |
676 ( (uint32_t) ssl[1] << 8 ) |
677 ( (uint32_t) ssl[2] );
678 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100679 printf_dbg( "Certificate length: %u\n", cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100680
681 if( cert_len > 0 )
682 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100683 CHECK_SSL_END( cert_len );
684 print_deserialized_ssl_cert( ssl, cert_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100685 ssl += cert_len;
686 }
687 }
688 else
689 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100690 printf( "\tPeer digest : " );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100691
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100692 CHECK_SSL_END( 1 );
693 switch( (mbedtls_md_type_t) *ssl++ )
Piotr Nowicki4e192002020-03-18 17:27:29 +0100694 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100695 case MBEDTLS_MD_NONE:
696 printf( "none\n" );
697 break;
698 case MBEDTLS_MD_MD2:
699 printf( "MD2\n" );
700 break;
701 case MBEDTLS_MD_MD4:
702 printf( "MD4\n" );
703 break;
704 case MBEDTLS_MD_MD5:
705 printf( "MD5\n" );
706 break;
707 case MBEDTLS_MD_SHA1:
708 printf( "SHA1\n" );
709 break;
710 case MBEDTLS_MD_SHA224:
711 printf( "SHA224\n" );
712 break;
713 case MBEDTLS_MD_SHA256:
714 printf( "SHA256\n" );
715 break;
716 case MBEDTLS_MD_SHA384:
717 printf( "SHA384\n" );
718 break;
719 case MBEDTLS_MD_SHA512:
720 printf( "SHA512\n" );
721 break;
722 case MBEDTLS_MD_RIPEMD160:
723 printf( "RIPEMD160\n" );
724 break;
725 default:
726 printf( "undefined or erroneous\n" );
727 break;
728 }
729
730 CHECK_SSL_END( 1 );
731 cert_len = (uint32_t) *ssl++;
732 printf_dbg( "Message-Digest length: %u\n", cert_len );
733
734 if( cert_len > 0 )
735 {
736 printf( "\tPeer digest cert : " );
737 CHECK_SSL_END( cert_len );
738 print_hex( ssl, cert_len, 16, "\t " );
739 ssl += cert_len;
Piotr Nowicki4e192002020-03-18 17:27:29 +0100740 }
741 }
742 }
743
744 if( SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag )
745 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100746 printf( "\nTicket:\n" );
747
748 CHECK_SSL_END( 3 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100749 ticket_len = ( (uint32_t) ssl[0] << 16 ) |
750 ( (uint32_t) ssl[1] << 8 ) |
751 ( (uint32_t) ssl[2] );
752 ssl += 3;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100753 printf_dbg( "Ticket length: %u\n", ticket_len );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100754
755 if( ticket_len > 0 )
756 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100757 printf( "\t" );
758 CHECK_SSL_END( ticket_len );
759 print_hex( ssl, ticket_len, 22, "\t" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100760 ssl += ticket_len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100761 printf( "\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100762 }
763
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100764 CHECK_SSL_END( 4 );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100765 ticket_lifetime = ( (uint32_t) ssl[0] << 24 ) |
766 ( (uint32_t) ssl[1] << 16 ) |
767 ( (uint32_t) ssl[2] << 8 ) |
768 ( (uint32_t) ssl[3] );
769 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100770 printf( "\tlifetime : %u sec.\n", ticket_lifetime );
771 }
772
773 if( ssl < end )
774 {
775 printf( "\nSession others:\n" );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100776 }
777
778 if( SESSION_CONFIG_MFL_BIT & session_cfg_flag )
779 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100780 CHECK_SSL_END( 1 );
781 printf( "\tMFL : %s\n", get_mfl_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100782 }
783
784 if( SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag )
785 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100786 CHECK_SSL_END( 1 );
787 printf( "\tnegotiate truncated HMAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100788 }
789
790 if( SESSION_CONFIG_ETM_BIT & session_cfg_flag )
791 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100792 CHECK_SSL_END( 1 );
793 printf( "\tEncrypt-then-MAC : %s\n", get_enabled_str( *ssl++ ) );
Piotr Nowicki4e192002020-03-18 17:27:29 +0100794 }
795
796 if( 0 != ( end - ssl ) )
797 {
798 printf_err( "%i bytes left to analyze from session\n", (int32_t)( end - ssl ) );
799 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100800}
801
802/*
803 * This function deserializes and prints to the stdout all obtained information
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100804 * about the context from provided data. This function was built based on
805 * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
806 * due to dependencies on the mbedTLS configuration and the configuration of
807 * the context when serialization was created.
808 *
809 * The data structure in the buffer:
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200810 * // header
811 * uint8 version[3];
812 * uint8 configuration[5];
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100813 * // session sub-structure
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200814 * uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100815 * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
816 * // transform sub-structure
817 * uint8 random[64]; // ServerHello.random+ClientHello.random
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200818 * uint8 in_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100819 * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200820 * uint8 out_cid_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100821 * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
822 * // fields from ssl_context
823 * uint32 badmac_seen; // DTLS: number of records with failing MAC
824 * uint64 in_window_top; // DTLS: last validated record seq_num
825 * uint64 in_window; // DTLS: bitmask for replay protection
826 * uint8 disable_datagram_packing; // DTLS: only one record per datagram
827 * uint64 cur_out_ctr; // Record layer: outgoing sequence number
828 * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +0200829 * uint8 alpn_chosen_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100830 * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
831 *
832 * /p ssl pointer to serialized session
833 * /p len number of bytes in the buffer
834 */
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100835void print_deserialized_ssl_context( const uint8_t *ssl, size_t len )
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100836{
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100837 const uint8_t *end = ssl + len;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100838 uint32_t session_len;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100839 int session_cfg_flag;
840 int context_cfg_flag;
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100841
842 printf( "\nMbed TLS version:\n" );
843
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100844 CHECK_SSL_END( 3 + 2 + 3 );
845
846 printf( "\tmajor %u\n", (uint32_t) *ssl++ );
847 printf( "\tminor %u\n", (uint32_t) *ssl++ );
848 printf( "\tpath %u\n", (uint32_t) *ssl++ );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100849
850 printf( "\nEnabled session and context configuration:\n" );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100851
852 session_cfg_flag = ( (int) ssl[0] << 8 ) | ( (int) ssl[1] );
853 ssl += 2;
854
855 context_cfg_flag = ( (int) ssl[0] << 16 ) |
856 ( (int) ssl[1] << 8 ) |
857 ( (int) ssl[2] ) ;
858 ssl += 3;
859
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100860 printf_dbg( "Session config flags 0x%04X\n", session_cfg_flag );
861 printf_dbg( "Context config flags 0x%06X\n", context_cfg_flag );
862
863 print_if_bit( "MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag );
864 print_if_bit( "MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag );
865 print_if_bit( "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag );
866 print_if_bit( "MBEDTLS_SSL_TRUNCATED_HMAC", SESSION_CONFIG_TRUNC_HMAC_BIT, session_cfg_flag );
867 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 );
872 print_if_bit( "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT, context_cfg_flag );
873 print_if_bit( "MBEDTLS_SSL_DTLS_ANTI_REPLAY", CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT, context_cfg_flag );
874 print_if_bit( "MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag );
875
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100876 CHECK_SSL_END( 4 );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100877 session_len = ( (uint32_t) ssl[0] << 24 ) |
878 ( (uint32_t) ssl[1] << 16 ) |
879 ( (uint32_t) ssl[2] << 8 ) |
880 ( (uint32_t) ssl[3] );
881 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100882 printf_dbg( "Session length %u\n", session_len );
Piotr Nowicki6b2baf92020-03-17 15:36:52 +0100883
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100884 CHECK_SSL_END( session_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100885 print_deserialized_ssl_session( ssl, session_len, session_cfg_flag );
886 ssl += session_len;
887
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100888 printf( "\nRandom bytes:\n\t");
889
890 CHECK_SSL_END( TRANSFORM_RANDBYTE_LEN );
891 print_hex( ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100892 ssl += TRANSFORM_RANDBYTE_LEN;
893
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100894 printf( "\nContext others:\n" );
895
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100896 if( CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag )
897 {
898 uint8_t cid_len;
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100899
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100900 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100901 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100902 printf_dbg( "In CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100903
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100904 printf( "\tin CID : " );
905 if( cid_len > 0 )
906 {
907 CHECK_SSL_END( cid_len );
908 print_hex( ssl, cid_len, 20, "\t" );
909 ssl += cid_len;
910 }
911 else
912 {
913 printf( "none\n" );
914 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100915
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100916 CHECK_SSL_END( 1 );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100917 cid_len = *ssl++;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100918 printf_dbg( "Out CID length %u\n", (uint32_t) cid_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100919
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100920 printf( "\tout CID : " );
921 if( cid_len > 0 )
922 {
923 CHECK_SSL_END( cid_len );
924 print_hex( ssl, cid_len, 20, "\t" );
925 ssl += cid_len;
926 }
927 else
928 {
929 printf( "none\n" );
930 }
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100931 }
932
933 if( CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag )
934 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100935 uint32_t badmac_seen;
936
937 CHECK_SSL_END( 4 );
938 badmac_seen = ( (uint32_t) ssl[0] << 24 ) |
939 ( (uint32_t) ssl[1] << 16 ) |
940 ( (uint32_t) ssl[2] << 8 ) |
941 ( (uint32_t) ssl[3] );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100942 ssl += 4;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100943 printf( "\tbad MAC seen number : %u\n", badmac_seen );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100944
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100945 /* value 'in_window_top' from mbedtls_ssl_context */
946 printf( "\tlast validated record sequence no. : " );
947 CHECK_SSL_END( 8 );
948 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100949 ssl += 8;
950
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100951 /* value 'in_window' from mbedtls_ssl_context */
952 printf( "\tbitmask for replay detection : " );
953 CHECK_SSL_END( 8 );
954 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100955 ssl += 8;
956 }
957
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100958 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100959 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100960 CHECK_SSL_END( 1 );
961 printf( "\tDTLS datagram packing : %s\n",
962 get_enabled_str( ! ( *ssl++ ) ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100963 }
964
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100965 /* value 'cur_out_ctr' from mbedtls_ssl_context */
966 printf( "\toutgoing record sequence no. : ");
967 CHECK_SSL_END( 8 );
968 print_hex( ssl, 8, 20, "" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100969 ssl += 8;
970
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100971 if( conf_dtls_proto )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100972 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100973 uint16_t mtu;
974 CHECK_SSL_END( 2 );
975 mtu = ( ssl[0] << 8 ) | ssl[1];
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100976 ssl += 2;
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100977 printf( "\tMTU : %u\n", mtu );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100978 }
979
980
981 if( CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag )
982 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100983 uint8_t alpn_len;
984
985 CHECK_SSL_END( 1 );
986 alpn_len = *ssl++;
987 printf_dbg( "ALPN length %u\n", (uint32_t) alpn_len );
988
989 printf( "\tALPN negotiation : " );
990 CHECK_SSL_END( alpn_len );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100991 if( alpn_len > 0 )
992 {
993 if( strlen( (const char*) ssl ) == alpn_len )
994 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100995 printf( "%s\n", ssl );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +0100996 }
997 else
998 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +0100999 printf( "\n" );
1000 printf_err( "\tALPN negotiation is incorrect\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001001 }
1002 ssl += alpn_len;
1003 }
1004 else
1005 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001006 printf( "not selected\n" );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001007 }
1008 }
1009
Piotr Nowicki4e192002020-03-18 17:27:29 +01001010 if( 0 != ( end - ssl ) )
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001011 {
Piotr Nowicki4e192002020-03-18 17:27:29 +01001012 printf_err( "%i bytes left to analyze from context\n", (int32_t)( end - ssl ) );
Piotr Nowickiab3ecd82020-03-18 15:12:41 +01001013 }
Piotr Nowicki6b2baf92020-03-17 15:36:52 +01001014 printf( "\n" );
1015}
1016
Piotr Nowicki9370f902020-03-13 14:43:22 +01001017int main( int argc, char *argv[] )
1018{
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001019 enum { SSL_INIT_LEN = 4096 };
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001020
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001021 uint32_t b64_counter = 0;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001022 uint8_t *b64_buf = NULL;
1023 uint8_t *ssl_buf = NULL;
1024 size_t b64_max_len = SSL_INIT_LEN;
1025 size_t ssl_max_len = SSL_INIT_LEN;
1026 size_t ssl_len = 0;
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001027
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001028 /* The 'b64_file' is opened when parsing arguments to check that the
1029 * file name is correct */
Piotr Nowicki88ebbbf2020-03-13 16:26:08 +01001030 parse_arguments( argc, argv );
Piotr Nowicki9370f902020-03-13 14:43:22 +01001031
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001032 if( NULL != b64_file )
1033 {
1034 b64_buf = malloc( SSL_INIT_LEN );
1035 ssl_buf = malloc( SSL_INIT_LEN );
1036
1037 if( NULL == b64_buf || NULL == ssl_buf )
1038 {
1039 printf_err( alloc_err );
1040 fclose( b64_file );
1041 b64_file = NULL;
1042 }
1043 }
1044
Piotr Nowicki14d31052020-03-16 14:05:22 +01001045 while( NULL != b64_file )
1046 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001047 size_t b64_len = read_next_b64_code( &b64_buf, &b64_max_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001048 if( b64_len > 0)
Piotr Nowicki14d31052020-03-16 14:05:22 +01001049 {
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001050 int ret;
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001051 size_t ssl_required_len = b64_len * 3 / 4 + 1;
1052
1053 /* Allocate more memory if necessary. */
1054 if( ssl_required_len > ssl_max_len )
1055 {
1056 void *ptr = realloc( ssl_buf, ssl_required_len );
1057 if( NULL == ptr )
1058 {
1059 printf_err( alloc_err );
1060 fclose( b64_file );
1061 b64_file = NULL;
1062 break;
1063 }
1064 ssl_buf = ptr;
1065 ssl_max_len = ssl_required_len;
1066 }
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001067
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001068 printf( "\nDeserializing number %u:\n", ++b64_counter );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001069
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001070 printf( "\nBase64 code:\n" );
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001071 print_b64( b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001072
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001073 ret = mbedtls_base64_decode( ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001074 if( ret != 0)
1075 {
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001076 mbedtls_strerror( ret, (char*) b64_buf, b64_max_len );
1077 printf_err( "base64 code cannot be decoded - %s\n", b64_buf );
Piotr Nowickic7d681c2020-03-17 09:51:31 +01001078 continue;
1079 }
1080
1081 if( debug )
1082 {
Piotr Nowickie5fa8b72020-03-20 12:16:33 +01001083 printf( "\nDecoded data in hex:\n\t");
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001084 print_hex( ssl_buf, ssl_len, 25, "\t" );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001085 }
Piotr Nowicki14d31052020-03-16 14:05:22 +01001086
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001087 print_deserialized_ssl_context( ssl_buf, ssl_len );
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001088
Piotr Nowicki14d31052020-03-16 14:05:22 +01001089 }
1090 else
1091 {
1092 fclose( b64_file );
1093 b64_file = NULL;
1094 }
1095 }
1096
Piotr Nowicki02cc3fb2020-03-30 17:09:33 +02001097 free( b64_buf );
1098 free( ssl_buf );
1099
1100 if( b64_counter > 0 )
1101 {
1102 printf_dbg( "Finished. Found %u base64 codes\n", b64_counter );
1103 }
1104 else
1105 {
1106 printf( "Finished. No valid base64 code found\n" );
1107 }
Piotr Nowicki6842c9b2020-03-16 17:52:56 +01001108
Piotr Nowicki9370f902020-03-13 14:43:22 +01001109 return 0;
1110}
Piotr Nowicki97dcb1c2020-04-09 17:00:57 +02001111
1112#endif /* MBEDTLS_X509_CRT_PARSE_C */