quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ssl_context_info.c (32257B)


      1 /*
      2  *  Mbed TLS SSL context deserializer from base64 code
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 
      8 #include "mbedtls/build_info.h"
      9 #include "mbedtls/debug.h"
     10 #include "mbedtls/platform.h"
     11 
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 
     15 #if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
     16     !defined(MBEDTLS_SSL_TLS_C)
     17 int main(void)
     18 {
     19     printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
     20            "MBEDTLS_SSL_TLS_C not defined.\n");
     21     return 0;
     22 }
     23 #else
     24 
     25 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
     26 #define _CRT_SECURE_NO_DEPRECATE 1
     27 #endif
     28 
     29 #include <stdint.h>
     30 #include <stdarg.h>
     31 #include <string.h>
     32 #if defined(MBEDTLS_HAVE_TIME)
     33 #include <time.h>
     34 #endif
     35 #include "mbedtls/ssl.h"
     36 #include "mbedtls/error.h"
     37 #include "mbedtls/base64.h"
     38 #include "mbedtls/md.h"
     39 #include "mbedtls/x509_crt.h"
     40 #include "mbedtls/ssl_ciphersuites.h"
     41 
     42 /*
     43  * This program version
     44  */
     45 #define PROG_NAME "ssl_context_info"
     46 #define VER_MAJOR 0
     47 #define VER_MINOR 1
     48 
     49 /*
     50  * Flags copied from the Mbed TLS library.
     51  */
     52 #define SESSION_CONFIG_TIME_BIT          (1 << 0)
     53 #define SESSION_CONFIG_CRT_BIT           (1 << 1)
     54 #define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
     55 #define SESSION_CONFIG_MFL_BIT           (1 << 3)
     56 #define SESSION_CONFIG_TRUNC_HMAC_BIT    (1 << 4)
     57 #define SESSION_CONFIG_ETM_BIT           (1 << 5)
     58 #define SESSION_CONFIG_TICKET_BIT        (1 << 6)
     59 
     60 #define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT    (1 << 0)
     61 #define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT     (1 << 1)
     62 #define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT      (1 << 2)
     63 #define CONTEXT_CONFIG_ALPN_BIT                  (1 << 3)
     64 
     65 #define TRANSFORM_RANDBYTE_LEN  64
     66 
     67 /*
     68  * Minimum and maximum number of bytes for specific data: context, sessions,
     69  * certificates, tickets and buffers in the program. The context and session
     70  * size values have been calculated based on the 'print_deserialized_ssl_context()'
     71  * and 'print_deserialized_ssl_session()' content.
     72  */
     73 #define MIN_CONTEXT_LEN     84
     74 #define MIN_SESSION_LEN     88
     75 
     76 #define MAX_CONTEXT_LEN     875     /* without session data */
     77 #define MAX_SESSION_LEN     109     /* without certificate and ticket data */
     78 #define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
     79 #define MAX_TICKET_LEN      ((1 << 24) - 1)
     80 
     81 #define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
     82 #define MAX_SERIALIZED_DATA (MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
     83                              MAX_CERTIFICATE_LEN + MAX_TICKET_LEN)
     84 
     85 #define MIN_BASE64_LEN      (MIN_SERIALIZED_DATA * 4 / 3)
     86 #define MAX_BASE64_LEN      (MAX_SERIALIZED_DATA * 4 / 3 + 3)
     87 
     88 /*
     89  * A macro that prevents from reading out of the ssl buffer range.
     90  */
     91 #define CHECK_SSL_END(LEN)            \
     92     do                                      \
     93     {                                       \
     94         if (end - ssl < (int) (LEN))      \
     95         {                                   \
     96             printf_err("%s", buf_ln_err); \
     97             return;                         \
     98         }                                   \
     99     } while (0)
    100 
    101 /*
    102  * Global values
    103  */
    104 FILE *b64_file = NULL;                  /* file with base64 codes to deserialize */
    105 char conf_keep_peer_certificate = 1;    /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
    106 char conf_dtls_proto = 1;               /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
    107 char debug = 0;                         /* flag for debug messages */
    108 const char alloc_err[] = "Cannot allocate memory\n";
    109 const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
    110 
    111 /*
    112  * Basic printing functions
    113  */
    114 static void print_version(void)
    115 {
    116     printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
    117 }
    118 
    119 static void print_usage(void)
    120 {
    121     print_version();
    122     printf("\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
    123            "in the text file. The program can deserialize many codes from one file, but they must be\n"
    124            "separated, e.g. by a newline.\n\n");
    125     printf(
    126         "Usage:\n"
    127         "\t-f path            - Path to the file with base64 code\n"
    128         "\t-v                 - Show version\n"
    129         "\t-h                 - Show this usage\n"
    130         "\t-d                 - Print more information\n"
    131         "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
    132         "\t                     has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
    133         "\t                     flag. You can also use it if there are some problems with reading\n"
    134         "\t                     the information about certificate\n"
    135         "\t--dtls-protocol=0  - Use this option if you know that the Mbed TLS library\n"
    136         "\t                     has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
    137         "\n"
    138         );
    139 }
    140 
    141 static void printf_dbg(const char *str, ...)
    142 {
    143     if (debug) {
    144         va_list args;
    145         va_start(args, str);
    146         printf("debug: ");
    147         vprintf(str, args);
    148         fflush(stdout);
    149         va_end(args);
    150     }
    151 }
    152 
    153 MBEDTLS_PRINTF_ATTRIBUTE(1, 2)
    154 static void printf_err(const char *str, ...)
    155 {
    156     va_list args;
    157     va_start(args, str);
    158     fflush(stdout);
    159     fprintf(stderr, "ERROR: ");
    160     vfprintf(stderr, str, args);
    161     fflush(stderr);
    162     va_end(args);
    163 }
    164 
    165 /*
    166  * Exit from the program in case of error
    167  */
    168 static void error_exit(void)
    169 {
    170     if (NULL != b64_file) {
    171         fclose(b64_file);
    172     }
    173     exit(-1);
    174 }
    175 
    176 /*
    177  * This function takes the input arguments of this program
    178  */
    179 static void parse_arguments(int argc, char *argv[])
    180 {
    181     int i = 1;
    182 
    183     if (argc < 2) {
    184         print_usage();
    185         error_exit();
    186     }
    187 
    188     while (i < argc) {
    189         if (strcmp(argv[i], "-d") == 0) {
    190             debug = 1;
    191         } else if (strcmp(argv[i], "-h") == 0) {
    192             print_usage();
    193         } else if (strcmp(argv[i], "-v") == 0) {
    194             print_version();
    195         } else if (strcmp(argv[i], "-f") == 0) {
    196             if (++i >= argc) {
    197                 printf_err("File path is empty\n");
    198                 error_exit();
    199             }
    200 
    201             if (NULL != b64_file) {
    202                 printf_err("Cannot specify more than one file with -f\n");
    203                 error_exit();
    204             }
    205 
    206             if ((b64_file = fopen(argv[i], "r")) == NULL) {
    207                 printf_err("Cannot find file \"%s\"\n", argv[i]);
    208                 error_exit();
    209             }
    210         } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
    211             conf_keep_peer_certificate = 0;
    212         } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
    213             conf_dtls_proto = 0;
    214         } else {
    215             print_usage();
    216             error_exit();
    217         }
    218 
    219         i++;
    220     }
    221 }
    222 
    223 /*
    224  * This function prints base64 code to the stdout
    225  */
    226 static void print_b64(const uint8_t *b, size_t len)
    227 {
    228     size_t i = 0;
    229     const uint8_t *end = b + len;
    230     printf("\t");
    231     while (b < end) {
    232         if (++i > 75) {
    233             printf("\n\t");
    234             i = 0;
    235         }
    236         printf("%c", *b++);
    237     }
    238     printf("\n");
    239     fflush(stdout);
    240 }
    241 
    242 /*
    243  * This function prints hex code from the buffer to the stdout.
    244  *
    245  * /p b         buffer with data to print
    246  * /p len       number of bytes to print
    247  * /p in_line   number of bytes in one line
    248  * /p prefix    prefix for the new lines
    249  */
    250 static void print_hex(const uint8_t *b, size_t len,
    251                       const size_t in_line, const char *prefix)
    252 {
    253     size_t i = 0;
    254     const uint8_t *end = b + len;
    255 
    256     if (prefix == NULL) {
    257         prefix = "";
    258     }
    259 
    260     while (b < end) {
    261         if (++i > in_line) {
    262             printf("\n%s", prefix);
    263             i = 1;
    264         }
    265         printf("%02X ", (uint8_t) *b++);
    266     }
    267     printf("\n");
    268     fflush(stdout);
    269 }
    270 
    271 /*
    272  *  Print the value of time_t in format e.g. 2020-01-23 13:05:59
    273  */
    274 static void print_time(const uint64_t *time)
    275 {
    276 #if defined(MBEDTLS_HAVE_TIME)
    277     char buf[20];
    278     struct tm *t = gmtime((time_t *) time);
    279     static const char format[] = "%Y-%m-%d %H:%M:%S";
    280     if (NULL != t) {
    281         strftime(buf, sizeof(buf), format, t);
    282         printf("%s\n", buf);
    283     } else {
    284         printf("unknown\n");
    285     }
    286 #else
    287     (void) time;
    288     printf("not supported\n");
    289 #endif
    290 }
    291 
    292 /*
    293  * Print the input string if the bit is set in the value
    294  */
    295 static void print_if_bit(const char *str, int bit, int val)
    296 {
    297     if (bit & val) {
    298         printf("\t%s\n", str);
    299     }
    300 }
    301 
    302 /*
    303  * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
    304  */
    305 static const char *get_enabled_str(int is_en)
    306 {
    307     return (is_en) ? "enabled" : "disabled";
    308 }
    309 
    310 /*
    311  * Return pointer to hardcoded MFL string value depending on the MFL code at the input
    312  */
    313 static const char *get_mfl_str(int mfl_code)
    314 {
    315     switch (mfl_code) {
    316         case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
    317             return "none";
    318         case MBEDTLS_SSL_MAX_FRAG_LEN_512:
    319             return "512";
    320         case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
    321             return "1024";
    322         case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
    323             return "2048";
    324         case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
    325             return "4096";
    326         default:
    327             return "error";
    328     }
    329 }
    330 
    331 /*
    332  * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
    333  * previously. After each call to this function, the internal file position
    334  * indicator of the global b64_file is advanced.
    335  *
    336  * Note - This function checks the size of the input buffer and if necessary,
    337  *        increases it to the maximum MAX_BASE64_LEN
    338  *
    339  * /p b64       pointer to the pointer of the buffer for input data
    340  * /p max_len   pointer to the current buffer capacity. It can be changed if
    341  *              the buffer needs to be increased
    342  *
    343  * \retval      number of bytes written in to the b64 buffer or 0 in case no more
    344  *              data was found
    345  */
    346 static size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
    347 {
    348     int valid_balance = 0;  /* balance between valid and invalid characters */
    349     size_t len = 0;
    350     char pad = 0;
    351     int c = 0;
    352 
    353     while (EOF != c) {
    354         char c_valid = 0;
    355 
    356         c = fgetc(b64_file);
    357 
    358         if (pad > 0) {
    359             if (c == '=' && pad == 1) {
    360                 c_valid = 1;
    361                 pad = 2;
    362             }
    363         } else if ((c >= 'A' && c <= 'Z') ||
    364                    (c >= 'a' && c <= 'z') ||
    365                    (c >= '0' && c <= '9') ||
    366                    c == '+' || c == '/') {
    367             c_valid = 1;
    368         } else if (c == '=') {
    369             c_valid = 1;
    370             pad = 1;
    371         } else if (c == '-') {
    372             c = '+';
    373             c_valid = 1;
    374         } else if (c == '_') {
    375             c = '/';
    376             c_valid = 1;
    377         }
    378 
    379         if (c_valid) {
    380             /* A string of characters that could be a base64 code. */
    381             valid_balance++;
    382 
    383             if (len < *max_len) {
    384                 (*b64)[len++] = c;
    385             } else if (*max_len < MAX_BASE64_LEN) {
    386                 /* Current buffer is too small, but can be resized. */
    387                 void *ptr;
    388                 size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
    389                                   *max_len + 4096 : MAX_BASE64_LEN;
    390 
    391                 ptr = realloc(*b64, new_size);
    392                 if (NULL == ptr) {
    393                     printf_err(alloc_err);
    394                     return 0;
    395                 }
    396                 *b64 = ptr;
    397                 *max_len = new_size;
    398                 (*b64)[len++] = c;
    399             } else {
    400                 /* Too much data so it will be treated as invalid */
    401                 len++;
    402             }
    403         } else if (len > 0) {
    404             /* End of a string that could be a base64 code, but need to check
    405              * that the length of the characters is correct. */
    406 
    407             valid_balance--;
    408 
    409             if (len < MIN_CONTEXT_LEN) {
    410                 printf_dbg("The code found is too small to be a SSL context.\n");
    411                 len = pad = 0;
    412             } else if (len > *max_len) {
    413                 printf_err("The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
    414                            len - *max_len);
    415                 len = pad = 0;
    416             } else if (len % 4 != 0) {
    417                 printf_err("The length of the base64 code found should be a multiple of 4.\n");
    418                 len = pad = 0;
    419             } else {
    420                 /* Base64 code with valid character length. */
    421                 return len;
    422             }
    423         } else {
    424             valid_balance--;
    425         }
    426 
    427         /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
    428         if (valid_balance < -100) {
    429             printf_err("Too many bad symbols detected. File check aborted.\n");
    430             return 0;
    431         }
    432     }
    433 
    434     printf_dbg("End of file\n");
    435     return 0;
    436 }
    437 
    438 #if !defined(MBEDTLS_X509_REMOVE_INFO)
    439 /*
    440  * This function deserializes and prints to the stdout all obtained information
    441  * about the certificates from provided data.
    442  *
    443  * /p ssl   pointer to serialized certificate
    444  * /p len   number of bytes in the buffer
    445  */
    446 static void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
    447 {
    448     enum { STRLEN = 4096 };
    449     mbedtls_x509_crt crt;
    450     int ret;
    451     char str[STRLEN];
    452 
    453     printf("\nCertificate:\n");
    454 
    455     mbedtls_x509_crt_init(&crt);
    456     ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
    457     if (0 != ret) {
    458         mbedtls_strerror(ret, str, STRLEN);
    459         printf_err("Invalid format of X.509 - %s\n", str);
    460         printf("Cannot deserialize:\n\t");
    461         print_hex(ssl, len, 25, "\t");
    462     } else {
    463         mbedtls_x509_crt *current = &crt;
    464 
    465         while (current != NULL) {
    466             ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
    467             if (0 > ret) {
    468                 mbedtls_strerror(ret, str, STRLEN);
    469                 printf_err("Cannot write to the output - %s\n", str);
    470             } else {
    471                 printf("%s", str);
    472             }
    473 
    474             current = current->next;
    475 
    476             if (current) {
    477                 printf("\n");
    478             }
    479 
    480         }
    481     }
    482 
    483     mbedtls_x509_crt_free(&crt);
    484 }
    485 #endif /* !MBEDTLS_X509_REMOVE_INFO */
    486 
    487 /*
    488  * This function deserializes and prints to the stdout all obtained information
    489  * about the session from provided data. This function was built based on
    490  * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
    491  * due to dependencies on the mbedTLS configuration.
    492  *
    493  * The data structure in the buffer:
    494  *  uint64 start_time;
    495  *  uint8 ciphersuite[2];        // defined by the standard
    496  *  uint8 compression;           // 0 or 1
    497  *  uint8 session_id_len;        // at most 32
    498  *  opaque session_id[32];
    499  *  opaque master[48];           // fixed length in the standard
    500  *  uint32 verify_result;
    501  *  opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
    502  *  opaque ticket<0..2^24-1>;    // length 0 means no ticket
    503  *  uint32 ticket_lifetime;
    504  *  uint8 mfl_code;              // up to 255 according to standard
    505  *  uint8 trunc_hmac;            // 0 or 1
    506  *  uint8 encrypt_then_mac;      // 0 or 1
    507  *
    508  * /p ssl               pointer to serialized session
    509  * /p len               number of bytes in the buffer
    510  * /p session_cfg_flag  session configuration flags
    511  */
    512 static void print_deserialized_ssl_session(const uint8_t *ssl, uint32_t len,
    513                                            int session_cfg_flag)
    514 {
    515     const struct mbedtls_ssl_ciphersuite_t *ciphersuite_info;
    516     int ciphersuite_id;
    517     uint32_t cert_len, ticket_len;
    518     uint32_t verify_result, ticket_lifetime;
    519     const uint8_t *end = ssl + len;
    520 
    521     printf("\nSession info:\n");
    522 
    523     if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
    524         uint64_t start;
    525         CHECK_SSL_END(8);
    526         start = ((uint64_t) ssl[0] << 56) |
    527                 ((uint64_t) ssl[1] << 48) |
    528                 ((uint64_t) ssl[2] << 40) |
    529                 ((uint64_t) ssl[3] << 32) |
    530                 ((uint64_t) ssl[4] << 24) |
    531                 ((uint64_t) ssl[5] << 16) |
    532                 ((uint64_t) ssl[6] <<  8) |
    533                 ((uint64_t) ssl[7]);
    534         ssl += 8;
    535         printf("\tstart time     : ");
    536         print_time(&start);
    537     }
    538 
    539     CHECK_SSL_END(2);
    540     ciphersuite_id = ((int) ssl[0] << 8) | (int) ssl[1];
    541     printf_dbg("Ciphersuite ID: %d\n", ciphersuite_id);
    542     ssl += 2;
    543 
    544     ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
    545     if (ciphersuite_info == NULL) {
    546         printf_err("Cannot find ciphersuite info\n");
    547     } else {
    548 #if defined(MBEDTLS_MD_C)
    549         const mbedtls_md_info_t *md_info;
    550 #endif
    551 
    552         printf("\tciphersuite    : %s\n", mbedtls_ssl_ciphersuite_get_name(ciphersuite_info));
    553         printf("\tcipher flags   : 0x%02X\n", ciphersuite_info->MBEDTLS_PRIVATE(flags));
    554 
    555 #if defined(MBEDTLS_CIPHER_C)
    556         const mbedtls_cipher_info_t *cipher_info;
    557         cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher));
    558         if (cipher_info == NULL) {
    559             printf_err("Cannot find cipher info\n");
    560         } else {
    561             printf("\tcipher         : %s\n", mbedtls_cipher_info_get_name(cipher_info));
    562         }
    563 #else /* MBEDTLS_CIPHER_C */
    564         printf("\tcipher type     : %d\n", ciphersuite_info->MBEDTLS_PRIVATE(cipher));
    565 #endif /* MBEDTLS_CIPHER_C */
    566 
    567 #if defined(MBEDTLS_MD_C)
    568         md_info = mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac));
    569         if (md_info == NULL) {
    570             printf_err("Cannot find Message-Digest info\n");
    571         } else {
    572             printf("\tMessage-Digest : %s\n", mbedtls_md_get_name(md_info));
    573         }
    574 #endif /* MBEDTLS_MD_C */
    575     }
    576 
    577     CHECK_SSL_END(1);
    578     printf("\tcompression    : %s\n", get_enabled_str(*ssl++));
    579 
    580     /* Note - Here we can get session ID length from serialized data, but we
    581      * use hardcoded 32-bytes length. This approach was taken from
    582      * 'mbedtls_ssl_session_load()'. */
    583     CHECK_SSL_END(1 + 32);
    584     printf_dbg("Session id length: %u\n", (uint32_t) *ssl++);
    585     printf("\tsession ID     : ");
    586     print_hex(ssl, 32, 16, "\t                 ");
    587     ssl += 32;
    588 
    589     printf("\tmaster secret  : ");
    590     CHECK_SSL_END(48);
    591     print_hex(ssl, 48, 16, "\t                 ");
    592     ssl += 48;
    593 
    594     CHECK_SSL_END(4);
    595     verify_result = ((uint32_t) ssl[0] << 24) |
    596                     ((uint32_t) ssl[1] << 16) |
    597                     ((uint32_t) ssl[2] <<  8) |
    598                     ((uint32_t) ssl[3]);
    599     ssl += 4;
    600     printf("\tverify result  : 0x%08X\n", verify_result);
    601 
    602     if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
    603         if (conf_keep_peer_certificate) {
    604             CHECK_SSL_END(3);
    605             cert_len = ((uint32_t) ssl[0] << 16) |
    606                        ((uint32_t) ssl[1] <<  8) |
    607                        ((uint32_t) ssl[2]);
    608             ssl += 3;
    609             printf_dbg("Certificate length: %u\n", cert_len);
    610 
    611             if (cert_len > 0) {
    612                 CHECK_SSL_END(cert_len);
    613 #if !defined(MBEDTLS_X509_REMOVE_INFO)
    614                 print_deserialized_ssl_cert(ssl, cert_len);
    615 #endif
    616                 ssl += cert_len;
    617             }
    618         } else {
    619             printf("\tPeer digest    : ");
    620 
    621             CHECK_SSL_END(1);
    622             switch ((mbedtls_md_type_t) *ssl++) {
    623                 case MBEDTLS_MD_NONE:
    624                     printf("none\n");
    625                     break;
    626                 case MBEDTLS_MD_MD5:
    627                     printf("MD5\n");
    628                     break;
    629                 case MBEDTLS_MD_SHA1:
    630                     printf("SHA1\n");
    631                     break;
    632                 case MBEDTLS_MD_SHA224:
    633                     printf("SHA224\n");
    634                     break;
    635                 case MBEDTLS_MD_SHA256:
    636                     printf("SHA256\n");
    637                     break;
    638                 case MBEDTLS_MD_SHA384:
    639                     printf("SHA384\n");
    640                     break;
    641                 case MBEDTLS_MD_SHA512:
    642                     printf("SHA512\n");
    643                     break;
    644                 case MBEDTLS_MD_RIPEMD160:
    645                     printf("RIPEMD160\n");
    646                     break;
    647                 default:
    648                     printf("undefined or erroneous\n");
    649                     break;
    650             }
    651 
    652             CHECK_SSL_END(1);
    653             cert_len  = (uint32_t) *ssl++;
    654             printf_dbg("Message-Digest length: %u\n", cert_len);
    655 
    656             if (cert_len > 0) {
    657                 printf("\tPeer digest cert : ");
    658                 CHECK_SSL_END(cert_len);
    659                 print_hex(ssl, cert_len, 16, "\t                   ");
    660                 ssl += cert_len;
    661             }
    662         }
    663     }
    664 
    665     if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
    666         printf("\nTicket:\n");
    667 
    668         CHECK_SSL_END(3);
    669         ticket_len = ((uint32_t) ssl[0] << 16) |
    670                      ((uint32_t) ssl[1] <<  8) |
    671                      ((uint32_t) ssl[2]);
    672         ssl += 3;
    673         printf_dbg("Ticket length: %u\n", ticket_len);
    674 
    675         if (ticket_len > 0) {
    676             printf("\t");
    677             CHECK_SSL_END(ticket_len);
    678             print_hex(ssl, ticket_len, 22, "\t");
    679             ssl += ticket_len;
    680             printf("\n");
    681         }
    682 
    683         CHECK_SSL_END(4);
    684         ticket_lifetime = ((uint32_t) ssl[0] << 24) |
    685                           ((uint32_t) ssl[1] << 16) |
    686                           ((uint32_t) ssl[2] <<  8) |
    687                           ((uint32_t) ssl[3]);
    688         ssl += 4;
    689         printf("\tlifetime : %u sec.\n", ticket_lifetime);
    690     }
    691 
    692     if (ssl < end) {
    693         printf("\nSession others:\n");
    694     }
    695 
    696     if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
    697         CHECK_SSL_END(1);
    698         printf("\tMFL                      : %s\n", get_mfl_str(*ssl++));
    699     }
    700 
    701     if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
    702         CHECK_SSL_END(1);
    703         printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
    704     }
    705 
    706     if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
    707         CHECK_SSL_END(1);
    708         printf("\tEncrypt-then-MAC         : %s\n", get_enabled_str(*ssl++));
    709     }
    710 
    711     if (0 != (end - ssl)) {
    712         printf_err("%i bytes left to analyze from session\n", (int32_t) (end - ssl));
    713     }
    714 }
    715 
    716 /*
    717  * This function deserializes and prints to the stdout all obtained information
    718  * about the context from provided data. This function was built based on
    719  * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
    720  * due to dependencies on the mbedTLS configuration and the configuration of
    721  * the context when serialization was created.
    722  *
    723  * The data structure in the buffer:
    724  *  // header
    725  *  uint8 version[3];
    726  *  uint8 configuration[5];
    727  *  // session sub-structure
    728  *  uint32_t session_len;
    729  *  opaque session<1..2^32-1>;  // see mbedtls_ssl_session_save()
    730  *  // transform sub-structure
    731  *  uint8 random[64];           // ServerHello.random+ClientHello.random
    732  *  uint8 in_cid_len;
    733  *  uint8 in_cid<0..2^8-1>      // Connection ID: expected incoming value
    734  *  uint8 out_cid_len;
    735  *  uint8 out_cid<0..2^8-1>     // Connection ID: outgoing value to use
    736  *  // fields from ssl_context
    737  *  uint32 badmac_seen;         // DTLS: number of records with failing MAC
    738  *  uint64 in_window_top;       // DTLS: last validated record seq_num
    739  *  uint64 in_window;           // DTLS: bitmask for replay protection
    740  *  uint8 disable_datagram_packing; // DTLS: only one record per datagram
    741  *  uint64 cur_out_ctr;         // Record layer: outgoing sequence number
    742  *  uint16 mtu;                 // DTLS: path mtu (max outgoing fragment size)
    743  *  uint8 alpn_chosen_len;
    744  *  uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
    745  *
    746  * Note: In the mbedtls_ssl_context structure, badmac_seen is called
    747  * badmac_seen_or_in_hsfraglen since Mbed TLS 3.6.2. The field contains
    748  * the badmac_seen value in DTLS, and a handshake parsing intermediate
    749  * value in non-DTLS TLS. The value is only meaningful for DTLS and should
    750  * not be saved in non-DTLS TLS, so in this program, the context info file
    751  * filed remains badmac_seen.
    752  *
    753  * /p ssl   pointer to serialized session
    754  * /p len   number of bytes in the buffer
    755  */
    756 static void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
    757 {
    758     const uint8_t *end = ssl + len;
    759     uint32_t session_len;
    760     int session_cfg_flag;
    761     int context_cfg_flag;
    762 
    763     printf("\nMbed TLS version:\n");
    764 
    765     CHECK_SSL_END(3 + 2 + 3);
    766 
    767     printf("\tmajor    %u\n", (uint32_t) *ssl++);
    768     printf("\tminor    %u\n", (uint32_t) *ssl++);
    769     printf("\tpath     %u\n", (uint32_t) *ssl++);
    770 
    771     printf("\nEnabled session and context configuration:\n");
    772 
    773     session_cfg_flag = ((int) ssl[0] << 8) | ((int) ssl[1]);
    774     ssl += 2;
    775 
    776     context_cfg_flag = ((int) ssl[0] << 16) |
    777                        ((int) ssl[1] <<  8) |
    778                        ((int) ssl[2]);
    779     ssl += 3;
    780 
    781     printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
    782     printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
    783 
    784     print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag);
    785     print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag);
    786     print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag);
    787     print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag);
    788     print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag);
    789     print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
    790                  SESSION_CONFIG_CLIENT_TICKET_BIT,
    791                  session_cfg_flag);
    792 
    793     print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
    794                  CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT,
    795                  context_cfg_flag);
    796     print_if_bit("MBEDTLS_SSL_DTLS_ANTI_REPLAY",
    797                  CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT,
    798                  context_cfg_flag);
    799     print_if_bit("MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag);
    800 
    801     CHECK_SSL_END(4);
    802     session_len = ((uint32_t) ssl[0] << 24) |
    803                   ((uint32_t) ssl[1] << 16) |
    804                   ((uint32_t) ssl[2] <<  8) |
    805                   ((uint32_t) ssl[3]);
    806     ssl += 4;
    807     printf_dbg("Session length %u\n", session_len);
    808 
    809     CHECK_SSL_END(session_len);
    810     print_deserialized_ssl_session(ssl, session_len, session_cfg_flag);
    811     ssl += session_len;
    812 
    813     printf("\nRandom bytes:\n\t");
    814 
    815     CHECK_SSL_END(TRANSFORM_RANDBYTE_LEN);
    816     print_hex(ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t");
    817     ssl += TRANSFORM_RANDBYTE_LEN;
    818 
    819     printf("\nContext others:\n");
    820 
    821     if (CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag) {
    822         uint8_t cid_len;
    823 
    824         CHECK_SSL_END(1);
    825         cid_len = *ssl++;
    826         printf_dbg("In CID length %u\n", (uint32_t) cid_len);
    827 
    828         printf("\tin CID                             : ");
    829         if (cid_len > 0) {
    830             CHECK_SSL_END(cid_len);
    831             print_hex(ssl, cid_len, 20, "\t");
    832             ssl += cid_len;
    833         } else {
    834             printf("none\n");
    835         }
    836 
    837         CHECK_SSL_END(1);
    838         cid_len = *ssl++;
    839         printf_dbg("Out CID length %u\n", (uint32_t) cid_len);
    840 
    841         printf("\tout CID                            : ");
    842         if (cid_len > 0) {
    843             CHECK_SSL_END(cid_len);
    844             print_hex(ssl, cid_len, 20, "\t");
    845             ssl += cid_len;
    846         } else {
    847             printf("none\n");
    848         }
    849     }
    850 
    851     if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
    852         uint32_t badmac_seen;
    853 
    854         CHECK_SSL_END(4);
    855         badmac_seen = ((uint32_t) ssl[0] << 24) |
    856                       ((uint32_t) ssl[1] << 16) |
    857                       ((uint32_t) ssl[2] <<  8) |
    858                       ((uint32_t) ssl[3]);
    859         ssl += 4;
    860         printf("\tbad MAC seen number                : %u\n", badmac_seen);
    861 
    862         /* value 'in_window_top' from mbedtls_ssl_context */
    863         printf("\tlast validated record sequence no. : ");
    864         CHECK_SSL_END(8);
    865         print_hex(ssl, 8, 20, "");
    866         ssl += 8;
    867 
    868         /* value 'in_window' from mbedtls_ssl_context */
    869         printf("\tbitmask for replay detection       : ");
    870         CHECK_SSL_END(8);
    871         print_hex(ssl, 8, 20, "");
    872         ssl += 8;
    873     }
    874 
    875     if (conf_dtls_proto) {
    876         CHECK_SSL_END(1);
    877         printf("\tDTLS datagram packing              : %s\n",
    878                get_enabled_str(!(*ssl++)));
    879     }
    880 
    881     /* value 'cur_out_ctr' from mbedtls_ssl_context */
    882     printf("\toutgoing record sequence no.       : ");
    883     CHECK_SSL_END(8);
    884     print_hex(ssl, 8, 20, "");
    885     ssl += 8;
    886 
    887     if (conf_dtls_proto) {
    888         uint16_t mtu;
    889         CHECK_SSL_END(2);
    890         mtu = (ssl[0] << 8) | ssl[1];
    891         ssl += 2;
    892         printf("\tMTU                                : %u\n", mtu);
    893     }
    894 
    895 
    896     if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
    897         uint8_t alpn_len;
    898 
    899         CHECK_SSL_END(1);
    900         alpn_len = *ssl++;
    901         printf_dbg("ALPN length %u\n", (uint32_t) alpn_len);
    902 
    903         printf("\tALPN negotiation                   : ");
    904         CHECK_SSL_END(alpn_len);
    905         if (alpn_len > 0) {
    906             if (strlen((const char *) ssl) == alpn_len) {
    907                 printf("%s\n", ssl);
    908             } else {
    909                 printf("\n");
    910                 printf_err("\tALPN negotiation is incorrect\n");
    911             }
    912             ssl += alpn_len;
    913         } else {
    914             printf("not selected\n");
    915         }
    916     }
    917 
    918     if (0 != (end - ssl)) {
    919         printf_err("%i bytes left to analyze from context\n", (int32_t) (end - ssl));
    920     }
    921     printf("\n");
    922 }
    923 
    924 int main(int argc, char *argv[])
    925 {
    926     enum { SSL_INIT_LEN = 4096 };
    927 
    928     uint32_t b64_counter = 0;
    929     uint8_t *b64_buf = NULL;
    930     uint8_t *ssl_buf = NULL;
    931     size_t b64_max_len = SSL_INIT_LEN;
    932     size_t ssl_max_len = SSL_INIT_LEN;
    933     size_t ssl_len = 0;
    934 
    935 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    936     psa_status_t status = psa_crypto_init();
    937     if (status != PSA_SUCCESS) {
    938         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
    939                         (int) status);
    940         return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
    941     }
    942 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    943 
    944     /* The 'b64_file' is opened when parsing arguments to check that the
    945      * file name is correct */
    946     parse_arguments(argc, argv);
    947 
    948     if (NULL != b64_file) {
    949         b64_buf = malloc(SSL_INIT_LEN);
    950         ssl_buf = malloc(SSL_INIT_LEN);
    951 
    952         if (NULL == b64_buf || NULL == ssl_buf) {
    953             printf_err(alloc_err);
    954             fclose(b64_file);
    955             b64_file = NULL;
    956         }
    957     }
    958 
    959     while (NULL != b64_file) {
    960         size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
    961         if (b64_len > 0) {
    962             int ret;
    963             size_t ssl_required_len = b64_len * 3 / 4 + 1;
    964 
    965             /* Allocate more memory if necessary. */
    966             if (ssl_required_len > ssl_max_len) {
    967                 void *ptr = realloc(ssl_buf, ssl_required_len);
    968                 if (NULL == ptr) {
    969                     printf_err(alloc_err);
    970                     fclose(b64_file);
    971                     b64_file = NULL;
    972                     break;
    973                 }
    974                 ssl_buf = ptr;
    975                 ssl_max_len = ssl_required_len;
    976             }
    977 
    978             printf("\nDeserializing number %u:\n",  ++b64_counter);
    979 
    980             printf("\nBase64 code:\n");
    981             print_b64(b64_buf, b64_len);
    982 
    983             ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len);
    984             if (ret != 0) {
    985                 mbedtls_strerror(ret, (char *) b64_buf, b64_max_len);
    986                 printf_err("base64 code cannot be decoded - %s\n", b64_buf);
    987                 continue;
    988             }
    989 
    990             if (debug) {
    991                 printf("\nDecoded data in hex:\n\t");
    992                 print_hex(ssl_buf, ssl_len, 25, "\t");
    993             }
    994 
    995             print_deserialized_ssl_context(ssl_buf, ssl_len);
    996 
    997         } else {
    998             fclose(b64_file);
    999             b64_file = NULL;
   1000         }
   1001     }
   1002 
   1003     free(b64_buf);
   1004     free(ssl_buf);
   1005 
   1006     if (b64_counter > 0) {
   1007         printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
   1008     } else {
   1009         printf("Finished. No valid base64 code found\n");
   1010     }
   1011 
   1012 #if defined(MBEDTLS_USE_PSA_CRYPTO)
   1013     mbedtls_psa_crypto_free();
   1014 #endif /* MBEDTLS_USE_PSA_CRYPTO */
   1015 
   1016     return 0;
   1017 }
   1018 
   1019 #endif /* MBEDTLS_X509_CRT_PARSE_C */