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