xref: /aosp_15_r20/external/mbedtls/programs/x509/cert_app.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi  *  Certificate reading application
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 #include "mbedtls/build_info.h"
9*62c56f98SSadaf Ebrahimi 
10*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
11*62c56f98SSadaf Ebrahimi 
12*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
13*62c56f98SSadaf Ebrahimi     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
14*62c56f98SSadaf Ebrahimi     !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) ||         \
15*62c56f98SSadaf Ebrahimi     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
16*62c56f98SSadaf Ebrahimi     !defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_X509_REMOVE_INFO)
main(void)17*62c56f98SSadaf Ebrahimi int main(void)
18*62c56f98SSadaf Ebrahimi {
19*62c56f98SSadaf Ebrahimi     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
20*62c56f98SSadaf Ebrahimi                    "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
21*62c56f98SSadaf Ebrahimi                    "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
22*62c56f98SSadaf Ebrahimi                    "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
23*62c56f98SSadaf Ebrahimi                    "MBEDTLS_CTR_DRBG_C not defined and/or MBEDTLS_X509_REMOVE_INFO defined.\n");
24*62c56f98SSadaf Ebrahimi     mbedtls_exit(0);
25*62c56f98SSadaf Ebrahimi }
26*62c56f98SSadaf Ebrahimi #else
27*62c56f98SSadaf Ebrahimi 
28*62c56f98SSadaf Ebrahimi #include "mbedtls/entropy.h"
29*62c56f98SSadaf Ebrahimi #include "mbedtls/ctr_drbg.h"
30*62c56f98SSadaf Ebrahimi #include "mbedtls/net_sockets.h"
31*62c56f98SSadaf Ebrahimi #include "mbedtls/ssl.h"
32*62c56f98SSadaf Ebrahimi #include "mbedtls/x509.h"
33*62c56f98SSadaf Ebrahimi #include "mbedtls/debug.h"
34*62c56f98SSadaf Ebrahimi 
35*62c56f98SSadaf Ebrahimi #include <stdio.h>
36*62c56f98SSadaf Ebrahimi #include <stdlib.h>
37*62c56f98SSadaf Ebrahimi #include <string.h>
38*62c56f98SSadaf Ebrahimi 
39*62c56f98SSadaf Ebrahimi #define MODE_NONE               0
40*62c56f98SSadaf Ebrahimi #define MODE_FILE               1
41*62c56f98SSadaf Ebrahimi #define MODE_SSL                2
42*62c56f98SSadaf Ebrahimi 
43*62c56f98SSadaf Ebrahimi #define DFL_MODE                MODE_NONE
44*62c56f98SSadaf Ebrahimi #define DFL_FILENAME            "cert.crt"
45*62c56f98SSadaf Ebrahimi #define DFL_CA_FILE             ""
46*62c56f98SSadaf Ebrahimi #define DFL_CRL_FILE            ""
47*62c56f98SSadaf Ebrahimi #define DFL_CA_PATH             ""
48*62c56f98SSadaf Ebrahimi #define DFL_SERVER_NAME         "localhost"
49*62c56f98SSadaf Ebrahimi #define DFL_SERVER_PORT         "4433"
50*62c56f98SSadaf Ebrahimi #define DFL_DEBUG_LEVEL         0
51*62c56f98SSadaf Ebrahimi #define DFL_PERMISSIVE          0
52*62c56f98SSadaf Ebrahimi 
53*62c56f98SSadaf Ebrahimi #define USAGE_IO \
54*62c56f98SSadaf Ebrahimi     "    ca_file=%%s          The single file containing the top-level CA(s) you fully trust\n" \
55*62c56f98SSadaf Ebrahimi     "                        default: \"\" (none)\n" \
56*62c56f98SSadaf Ebrahimi     "    crl_file=%%s         The single CRL file you want to use\n" \
57*62c56f98SSadaf Ebrahimi     "                        default: \"\" (none)\n" \
58*62c56f98SSadaf Ebrahimi     "    ca_path=%%s          The path containing the top-level CA(s) you fully trust\n" \
59*62c56f98SSadaf Ebrahimi     "                        default: \"\" (none) (overrides ca_file)\n"
60*62c56f98SSadaf Ebrahimi 
61*62c56f98SSadaf Ebrahimi #define USAGE \
62*62c56f98SSadaf Ebrahimi     "\n usage: cert_app param=<>...\n"                  \
63*62c56f98SSadaf Ebrahimi     "\n acceptable parameters:\n"                       \
64*62c56f98SSadaf Ebrahimi     "    mode=file|ssl       default: none\n"           \
65*62c56f98SSadaf Ebrahimi     "    filename=%%s         default: cert.crt\n"      \
66*62c56f98SSadaf Ebrahimi     USAGE_IO                                            \
67*62c56f98SSadaf Ebrahimi     "    server_name=%%s      default: localhost\n"     \
68*62c56f98SSadaf Ebrahimi     "    server_port=%%d      default: 4433\n"          \
69*62c56f98SSadaf Ebrahimi     "    debug_level=%%d      default: 0 (disabled)\n"  \
70*62c56f98SSadaf Ebrahimi     "    permissive=%%d       default: 0 (disabled)\n"  \
71*62c56f98SSadaf Ebrahimi     "\n"
72*62c56f98SSadaf Ebrahimi 
73*62c56f98SSadaf Ebrahimi 
74*62c56f98SSadaf Ebrahimi /*
75*62c56f98SSadaf Ebrahimi  * global options
76*62c56f98SSadaf Ebrahimi  */
77*62c56f98SSadaf Ebrahimi struct options {
78*62c56f98SSadaf Ebrahimi     int mode;                   /* the mode to run the application in   */
79*62c56f98SSadaf Ebrahimi     const char *filename;       /* filename of the certificate file     */
80*62c56f98SSadaf Ebrahimi     const char *ca_file;        /* the file with the CA certificate(s)  */
81*62c56f98SSadaf Ebrahimi     const char *crl_file;       /* the file with the CRL to use         */
82*62c56f98SSadaf Ebrahimi     const char *ca_path;        /* the path with the CA certificate(s) reside */
83*62c56f98SSadaf Ebrahimi     const char *server_name;    /* hostname of the server (client only) */
84*62c56f98SSadaf Ebrahimi     const char *server_port;    /* port on which the ssl service runs   */
85*62c56f98SSadaf Ebrahimi     int debug_level;            /* level of debugging                   */
86*62c56f98SSadaf Ebrahimi     int permissive;             /* permissive parsing                   */
87*62c56f98SSadaf Ebrahimi } opt;
88*62c56f98SSadaf Ebrahimi 
my_debug(void * ctx,int level,const char * file,int line,const char * str)89*62c56f98SSadaf Ebrahimi static void my_debug(void *ctx, int level,
90*62c56f98SSadaf Ebrahimi                      const char *file, int line,
91*62c56f98SSadaf Ebrahimi                      const char *str)
92*62c56f98SSadaf Ebrahimi {
93*62c56f98SSadaf Ebrahimi     ((void) level);
94*62c56f98SSadaf Ebrahimi 
95*62c56f98SSadaf Ebrahimi     mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
96*62c56f98SSadaf Ebrahimi     fflush((FILE *) ctx);
97*62c56f98SSadaf Ebrahimi }
98*62c56f98SSadaf Ebrahimi 
my_verify(void * data,mbedtls_x509_crt * crt,int depth,uint32_t * flags)99*62c56f98SSadaf Ebrahimi static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
100*62c56f98SSadaf Ebrahimi {
101*62c56f98SSadaf Ebrahimi     char buf[1024];
102*62c56f98SSadaf Ebrahimi     ((void) data);
103*62c56f98SSadaf Ebrahimi 
104*62c56f98SSadaf Ebrahimi     mbedtls_printf("\nVerify requested for (Depth %d):\n", depth);
105*62c56f98SSadaf Ebrahimi     mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
106*62c56f98SSadaf Ebrahimi     mbedtls_printf("%s", buf);
107*62c56f98SSadaf Ebrahimi 
108*62c56f98SSadaf Ebrahimi     if ((*flags) == 0) {
109*62c56f98SSadaf Ebrahimi         mbedtls_printf("  This certificate has no flags\n");
110*62c56f98SSadaf Ebrahimi     } else {
111*62c56f98SSadaf Ebrahimi         mbedtls_x509_crt_verify_info(buf, sizeof(buf), "  ! ", *flags);
112*62c56f98SSadaf Ebrahimi         mbedtls_printf("%s\n", buf);
113*62c56f98SSadaf Ebrahimi     }
114*62c56f98SSadaf Ebrahimi 
115*62c56f98SSadaf Ebrahimi     return 0;
116*62c56f98SSadaf Ebrahimi }
117*62c56f98SSadaf Ebrahimi 
main(int argc,char * argv[])118*62c56f98SSadaf Ebrahimi int main(int argc, char *argv[])
119*62c56f98SSadaf Ebrahimi {
120*62c56f98SSadaf Ebrahimi     int ret = 1;
121*62c56f98SSadaf Ebrahimi     int exit_code = MBEDTLS_EXIT_FAILURE;
122*62c56f98SSadaf Ebrahimi     mbedtls_net_context server_fd;
123*62c56f98SSadaf Ebrahimi     unsigned char buf[1024];
124*62c56f98SSadaf Ebrahimi     mbedtls_entropy_context entropy;
125*62c56f98SSadaf Ebrahimi     mbedtls_ctr_drbg_context ctr_drbg;
126*62c56f98SSadaf Ebrahimi     mbedtls_ssl_context ssl;
127*62c56f98SSadaf Ebrahimi     mbedtls_ssl_config conf;
128*62c56f98SSadaf Ebrahimi     mbedtls_x509_crt cacert;
129*62c56f98SSadaf Ebrahimi     mbedtls_x509_crl cacrl;
130*62c56f98SSadaf Ebrahimi     int i, j;
131*62c56f98SSadaf Ebrahimi     uint32_t flags;
132*62c56f98SSadaf Ebrahimi     int verify = 0;
133*62c56f98SSadaf Ebrahimi     char *p, *q;
134*62c56f98SSadaf Ebrahimi     const char *pers = "cert_app";
135*62c56f98SSadaf Ebrahimi 
136*62c56f98SSadaf Ebrahimi     /*
137*62c56f98SSadaf Ebrahimi      * Set to sane values
138*62c56f98SSadaf Ebrahimi      */
139*62c56f98SSadaf Ebrahimi     mbedtls_net_init(&server_fd);
140*62c56f98SSadaf Ebrahimi     mbedtls_ctr_drbg_init(&ctr_drbg);
141*62c56f98SSadaf Ebrahimi     mbedtls_ssl_init(&ssl);
142*62c56f98SSadaf Ebrahimi     mbedtls_ssl_config_init(&conf);
143*62c56f98SSadaf Ebrahimi     mbedtls_x509_crt_init(&cacert);
144*62c56f98SSadaf Ebrahimi     mbedtls_entropy_init(&entropy);
145*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRL_PARSE_C)
146*62c56f98SSadaf Ebrahimi     mbedtls_x509_crl_init(&cacrl);
147*62c56f98SSadaf Ebrahimi #else
148*62c56f98SSadaf Ebrahimi     /* Zeroize structure as CRL parsing is not supported and we have to pass
149*62c56f98SSadaf Ebrahimi        it to the verify function */
150*62c56f98SSadaf Ebrahimi     memset(&cacrl, 0, sizeof(mbedtls_x509_crl));
151*62c56f98SSadaf Ebrahimi #endif
152*62c56f98SSadaf Ebrahimi 
153*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
154*62c56f98SSadaf Ebrahimi     psa_status_t status = psa_crypto_init();
155*62c56f98SSadaf Ebrahimi     if (status != PSA_SUCCESS) {
156*62c56f98SSadaf Ebrahimi         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
157*62c56f98SSadaf Ebrahimi                         (int) status);
158*62c56f98SSadaf Ebrahimi         goto exit;
159*62c56f98SSadaf Ebrahimi     }
160*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
161*62c56f98SSadaf Ebrahimi 
162*62c56f98SSadaf Ebrahimi     if (argc < 2) {
163*62c56f98SSadaf Ebrahimi usage:
164*62c56f98SSadaf Ebrahimi         mbedtls_printf(USAGE);
165*62c56f98SSadaf Ebrahimi         goto exit;
166*62c56f98SSadaf Ebrahimi     }
167*62c56f98SSadaf Ebrahimi 
168*62c56f98SSadaf Ebrahimi     opt.mode                = DFL_MODE;
169*62c56f98SSadaf Ebrahimi     opt.filename            = DFL_FILENAME;
170*62c56f98SSadaf Ebrahimi     opt.ca_file             = DFL_CA_FILE;
171*62c56f98SSadaf Ebrahimi     opt.crl_file            = DFL_CRL_FILE;
172*62c56f98SSadaf Ebrahimi     opt.ca_path             = DFL_CA_PATH;
173*62c56f98SSadaf Ebrahimi     opt.server_name         = DFL_SERVER_NAME;
174*62c56f98SSadaf Ebrahimi     opt.server_port         = DFL_SERVER_PORT;
175*62c56f98SSadaf Ebrahimi     opt.debug_level         = DFL_DEBUG_LEVEL;
176*62c56f98SSadaf Ebrahimi     opt.permissive          = DFL_PERMISSIVE;
177*62c56f98SSadaf Ebrahimi 
178*62c56f98SSadaf Ebrahimi     for (i = 1; i < argc; i++) {
179*62c56f98SSadaf Ebrahimi         p = argv[i];
180*62c56f98SSadaf Ebrahimi         if ((q = strchr(p, '=')) == NULL) {
181*62c56f98SSadaf Ebrahimi             goto usage;
182*62c56f98SSadaf Ebrahimi         }
183*62c56f98SSadaf Ebrahimi         *q++ = '\0';
184*62c56f98SSadaf Ebrahimi 
185*62c56f98SSadaf Ebrahimi         for (j = 0; p + j < q; j++) {
186*62c56f98SSadaf Ebrahimi             if (argv[i][j] >= 'A' && argv[i][j] <= 'Z') {
187*62c56f98SSadaf Ebrahimi                 argv[i][j] |= 0x20;
188*62c56f98SSadaf Ebrahimi             }
189*62c56f98SSadaf Ebrahimi         }
190*62c56f98SSadaf Ebrahimi 
191*62c56f98SSadaf Ebrahimi         if (strcmp(p, "mode") == 0) {
192*62c56f98SSadaf Ebrahimi             if (strcmp(q, "file") == 0) {
193*62c56f98SSadaf Ebrahimi                 opt.mode = MODE_FILE;
194*62c56f98SSadaf Ebrahimi             } else if (strcmp(q, "ssl") == 0) {
195*62c56f98SSadaf Ebrahimi                 opt.mode = MODE_SSL;
196*62c56f98SSadaf Ebrahimi             } else {
197*62c56f98SSadaf Ebrahimi                 goto usage;
198*62c56f98SSadaf Ebrahimi             }
199*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "filename") == 0) {
200*62c56f98SSadaf Ebrahimi             opt.filename = q;
201*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "ca_file") == 0) {
202*62c56f98SSadaf Ebrahimi             opt.ca_file = q;
203*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "crl_file") == 0) {
204*62c56f98SSadaf Ebrahimi             opt.crl_file = q;
205*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "ca_path") == 0) {
206*62c56f98SSadaf Ebrahimi             opt.ca_path = q;
207*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "server_name") == 0) {
208*62c56f98SSadaf Ebrahimi             opt.server_name = q;
209*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "server_port") == 0) {
210*62c56f98SSadaf Ebrahimi             opt.server_port = q;
211*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "debug_level") == 0) {
212*62c56f98SSadaf Ebrahimi             opt.debug_level = atoi(q);
213*62c56f98SSadaf Ebrahimi             if (opt.debug_level < 0 || opt.debug_level > 65535) {
214*62c56f98SSadaf Ebrahimi                 goto usage;
215*62c56f98SSadaf Ebrahimi             }
216*62c56f98SSadaf Ebrahimi         } else if (strcmp(p, "permissive") == 0) {
217*62c56f98SSadaf Ebrahimi             opt.permissive = atoi(q);
218*62c56f98SSadaf Ebrahimi             if (opt.permissive < 0 || opt.permissive > 1) {
219*62c56f98SSadaf Ebrahimi                 goto usage;
220*62c56f98SSadaf Ebrahimi             }
221*62c56f98SSadaf Ebrahimi         } else {
222*62c56f98SSadaf Ebrahimi             goto usage;
223*62c56f98SSadaf Ebrahimi         }
224*62c56f98SSadaf Ebrahimi     }
225*62c56f98SSadaf Ebrahimi 
226*62c56f98SSadaf Ebrahimi     /*
227*62c56f98SSadaf Ebrahimi      * 1.1. Load the trusted CA
228*62c56f98SSadaf Ebrahimi      */
229*62c56f98SSadaf Ebrahimi     mbedtls_printf("  . Loading the CA root certificate ...");
230*62c56f98SSadaf Ebrahimi     fflush(stdout);
231*62c56f98SSadaf Ebrahimi 
232*62c56f98SSadaf Ebrahimi     if (strlen(opt.ca_path)) {
233*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_x509_crt_parse_path(&cacert, opt.ca_path)) < 0) {
234*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_path returned -0x%x\n\n",
235*62c56f98SSadaf Ebrahimi                            (unsigned int) -ret);
236*62c56f98SSadaf Ebrahimi             goto exit;
237*62c56f98SSadaf Ebrahimi         }
238*62c56f98SSadaf Ebrahimi 
239*62c56f98SSadaf Ebrahimi         verify = 1;
240*62c56f98SSadaf Ebrahimi     } else if (strlen(opt.ca_file)) {
241*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_x509_crt_parse_file(&cacert, opt.ca_file)) < 0) {
242*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_file returned -0x%x\n\n",
243*62c56f98SSadaf Ebrahimi                            (unsigned int) -ret);
244*62c56f98SSadaf Ebrahimi             goto exit;
245*62c56f98SSadaf Ebrahimi         }
246*62c56f98SSadaf Ebrahimi 
247*62c56f98SSadaf Ebrahimi         verify = 1;
248*62c56f98SSadaf Ebrahimi     }
249*62c56f98SSadaf Ebrahimi 
250*62c56f98SSadaf Ebrahimi     mbedtls_printf(" ok (%d skipped)\n", ret);
251*62c56f98SSadaf Ebrahimi 
252*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRL_PARSE_C)
253*62c56f98SSadaf Ebrahimi     if (strlen(opt.crl_file)) {
254*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_x509_crl_parse_file(&cacrl, opt.crl_file)) != 0) {
255*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  !  mbedtls_x509_crl_parse returned -0x%x\n\n",
256*62c56f98SSadaf Ebrahimi                            (unsigned int) -ret);
257*62c56f98SSadaf Ebrahimi             goto exit;
258*62c56f98SSadaf Ebrahimi         }
259*62c56f98SSadaf Ebrahimi 
260*62c56f98SSadaf Ebrahimi         verify = 1;
261*62c56f98SSadaf Ebrahimi     }
262*62c56f98SSadaf Ebrahimi #endif
263*62c56f98SSadaf Ebrahimi 
264*62c56f98SSadaf Ebrahimi     if (opt.mode == MODE_FILE) {
265*62c56f98SSadaf Ebrahimi         mbedtls_x509_crt crt;
266*62c56f98SSadaf Ebrahimi         mbedtls_x509_crt *cur = &crt;
267*62c56f98SSadaf Ebrahimi         mbedtls_x509_crt_init(&crt);
268*62c56f98SSadaf Ebrahimi 
269*62c56f98SSadaf Ebrahimi         /*
270*62c56f98SSadaf Ebrahimi          * 1.1. Load the certificate(s)
271*62c56f98SSadaf Ebrahimi          */
272*62c56f98SSadaf Ebrahimi         mbedtls_printf("\n  . Loading the certificate(s) ...");
273*62c56f98SSadaf Ebrahimi         fflush(stdout);
274*62c56f98SSadaf Ebrahimi 
275*62c56f98SSadaf Ebrahimi         ret = mbedtls_x509_crt_parse_file(&crt, opt.filename);
276*62c56f98SSadaf Ebrahimi 
277*62c56f98SSadaf Ebrahimi         if (ret < 0) {
278*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret);
279*62c56f98SSadaf Ebrahimi             mbedtls_x509_crt_free(&crt);
280*62c56f98SSadaf Ebrahimi             goto exit;
281*62c56f98SSadaf Ebrahimi         }
282*62c56f98SSadaf Ebrahimi 
283*62c56f98SSadaf Ebrahimi         if (opt.permissive == 0 && ret > 0) {
284*62c56f98SSadaf Ebrahimi             mbedtls_printf(
285*62c56f98SSadaf Ebrahimi                 " failed\n  !  mbedtls_x509_crt_parse failed to parse %d certificates\n\n",
286*62c56f98SSadaf Ebrahimi                 ret);
287*62c56f98SSadaf Ebrahimi             mbedtls_x509_crt_free(&crt);
288*62c56f98SSadaf Ebrahimi             goto exit;
289*62c56f98SSadaf Ebrahimi         }
290*62c56f98SSadaf Ebrahimi 
291*62c56f98SSadaf Ebrahimi         mbedtls_printf(" ok\n");
292*62c56f98SSadaf Ebrahimi 
293*62c56f98SSadaf Ebrahimi         /*
294*62c56f98SSadaf Ebrahimi          * 1.2 Print the certificate(s)
295*62c56f98SSadaf Ebrahimi          */
296*62c56f98SSadaf Ebrahimi         while (cur != NULL) {
297*62c56f98SSadaf Ebrahimi             mbedtls_printf("  . Peer certificate information    ...\n");
298*62c56f98SSadaf Ebrahimi             ret = mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ",
299*62c56f98SSadaf Ebrahimi                                         cur);
300*62c56f98SSadaf Ebrahimi             if (ret == -1) {
301*62c56f98SSadaf Ebrahimi                 mbedtls_printf(" failed\n  !  mbedtls_x509_crt_info returned %d\n\n", ret);
302*62c56f98SSadaf Ebrahimi                 mbedtls_x509_crt_free(&crt);
303*62c56f98SSadaf Ebrahimi                 goto exit;
304*62c56f98SSadaf Ebrahimi             }
305*62c56f98SSadaf Ebrahimi 
306*62c56f98SSadaf Ebrahimi             mbedtls_printf("%s\n", buf);
307*62c56f98SSadaf Ebrahimi 
308*62c56f98SSadaf Ebrahimi             cur = cur->next;
309*62c56f98SSadaf Ebrahimi         }
310*62c56f98SSadaf Ebrahimi 
311*62c56f98SSadaf Ebrahimi         /*
312*62c56f98SSadaf Ebrahimi          * 1.3 Verify the certificate
313*62c56f98SSadaf Ebrahimi          */
314*62c56f98SSadaf Ebrahimi         if (verify) {
315*62c56f98SSadaf Ebrahimi             mbedtls_printf("  . Verifying X.509 certificate...");
316*62c56f98SSadaf Ebrahimi 
317*62c56f98SSadaf Ebrahimi             if ((ret = mbedtls_x509_crt_verify(&crt, &cacert, &cacrl, NULL, &flags,
318*62c56f98SSadaf Ebrahimi                                                my_verify, NULL)) != 0) {
319*62c56f98SSadaf Ebrahimi                 char vrfy_buf[512];
320*62c56f98SSadaf Ebrahimi 
321*62c56f98SSadaf Ebrahimi                 mbedtls_printf(" failed\n");
322*62c56f98SSadaf Ebrahimi 
323*62c56f98SSadaf Ebrahimi                 mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
324*62c56f98SSadaf Ebrahimi 
325*62c56f98SSadaf Ebrahimi                 mbedtls_printf("%s\n", vrfy_buf);
326*62c56f98SSadaf Ebrahimi             } else {
327*62c56f98SSadaf Ebrahimi                 mbedtls_printf(" ok\n");
328*62c56f98SSadaf Ebrahimi             }
329*62c56f98SSadaf Ebrahimi         }
330*62c56f98SSadaf Ebrahimi 
331*62c56f98SSadaf Ebrahimi         mbedtls_x509_crt_free(&crt);
332*62c56f98SSadaf Ebrahimi     } else if (opt.mode == MODE_SSL) {
333*62c56f98SSadaf Ebrahimi         /*
334*62c56f98SSadaf Ebrahimi          * 1. Initialize the RNG and the session data
335*62c56f98SSadaf Ebrahimi          */
336*62c56f98SSadaf Ebrahimi         mbedtls_printf("\n  . Seeding the random number generator...");
337*62c56f98SSadaf Ebrahimi         fflush(stdout);
338*62c56f98SSadaf Ebrahimi 
339*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
340*62c56f98SSadaf Ebrahimi                                          (const unsigned char *) pers,
341*62c56f98SSadaf Ebrahimi                                          strlen(pers))) != 0) {
342*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
343*62c56f98SSadaf Ebrahimi             goto ssl_exit;
344*62c56f98SSadaf Ebrahimi         }
345*62c56f98SSadaf Ebrahimi 
346*62c56f98SSadaf Ebrahimi         mbedtls_printf(" ok\n");
347*62c56f98SSadaf Ebrahimi 
348*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_DEBUG_C)
349*62c56f98SSadaf Ebrahimi         mbedtls_debug_set_threshold(opt.debug_level);
350*62c56f98SSadaf Ebrahimi #endif
351*62c56f98SSadaf Ebrahimi 
352*62c56f98SSadaf Ebrahimi         /*
353*62c56f98SSadaf Ebrahimi          * 2. Start the connection
354*62c56f98SSadaf Ebrahimi          */
355*62c56f98SSadaf Ebrahimi         mbedtls_printf("  . SSL connection to tcp/%s/%s...", opt.server_name,
356*62c56f98SSadaf Ebrahimi                        opt.server_port);
357*62c56f98SSadaf Ebrahimi         fflush(stdout);
358*62c56f98SSadaf Ebrahimi 
359*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_net_connect(&server_fd, opt.server_name,
360*62c56f98SSadaf Ebrahimi                                        opt.server_port, MBEDTLS_NET_PROTO_TCP)) != 0) {
361*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
362*62c56f98SSadaf Ebrahimi             goto ssl_exit;
363*62c56f98SSadaf Ebrahimi         }
364*62c56f98SSadaf Ebrahimi 
365*62c56f98SSadaf Ebrahimi         /*
366*62c56f98SSadaf Ebrahimi          * 3. Setup stuff
367*62c56f98SSadaf Ebrahimi          */
368*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_ssl_config_defaults(&conf,
369*62c56f98SSadaf Ebrahimi                                                MBEDTLS_SSL_IS_CLIENT,
370*62c56f98SSadaf Ebrahimi                                                MBEDTLS_SSL_TRANSPORT_STREAM,
371*62c56f98SSadaf Ebrahimi                                                MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
372*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
373*62c56f98SSadaf Ebrahimi             goto exit;
374*62c56f98SSadaf Ebrahimi         }
375*62c56f98SSadaf Ebrahimi 
376*62c56f98SSadaf Ebrahimi         if (verify) {
377*62c56f98SSadaf Ebrahimi             mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
378*62c56f98SSadaf Ebrahimi             mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
379*62c56f98SSadaf Ebrahimi             mbedtls_ssl_conf_verify(&conf, my_verify, NULL);
380*62c56f98SSadaf Ebrahimi         } else {
381*62c56f98SSadaf Ebrahimi             mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
382*62c56f98SSadaf Ebrahimi         }
383*62c56f98SSadaf Ebrahimi 
384*62c56f98SSadaf Ebrahimi         mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
385*62c56f98SSadaf Ebrahimi         mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
386*62c56f98SSadaf Ebrahimi 
387*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
388*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
389*62c56f98SSadaf Ebrahimi             goto ssl_exit;
390*62c56f98SSadaf Ebrahimi         }
391*62c56f98SSadaf Ebrahimi 
392*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_ssl_set_hostname(&ssl, opt.server_name)) != 0) {
393*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
394*62c56f98SSadaf Ebrahimi             goto ssl_exit;
395*62c56f98SSadaf Ebrahimi         }
396*62c56f98SSadaf Ebrahimi 
397*62c56f98SSadaf Ebrahimi         mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
398*62c56f98SSadaf Ebrahimi 
399*62c56f98SSadaf Ebrahimi         /*
400*62c56f98SSadaf Ebrahimi          * 4. Handshake
401*62c56f98SSadaf Ebrahimi          */
402*62c56f98SSadaf Ebrahimi         while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
403*62c56f98SSadaf Ebrahimi             if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
404*62c56f98SSadaf Ebrahimi                 mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned %d\n\n", ret);
405*62c56f98SSadaf Ebrahimi                 goto ssl_exit;
406*62c56f98SSadaf Ebrahimi             }
407*62c56f98SSadaf Ebrahimi         }
408*62c56f98SSadaf Ebrahimi 
409*62c56f98SSadaf Ebrahimi         mbedtls_printf(" ok\n");
410*62c56f98SSadaf Ebrahimi 
411*62c56f98SSadaf Ebrahimi         /*
412*62c56f98SSadaf Ebrahimi          * 5. Print the certificate
413*62c56f98SSadaf Ebrahimi          */
414*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
415*62c56f98SSadaf Ebrahimi         mbedtls_printf("  . Peer certificate information    ... skipped\n");
416*62c56f98SSadaf Ebrahimi #else
417*62c56f98SSadaf Ebrahimi         mbedtls_printf("  . Peer certificate information    ...\n");
418*62c56f98SSadaf Ebrahimi         ret = mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ",
419*62c56f98SSadaf Ebrahimi                                     mbedtls_ssl_get_peer_cert(&ssl));
420*62c56f98SSadaf Ebrahimi         if (ret == -1) {
421*62c56f98SSadaf Ebrahimi             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_info returned %d\n\n", ret);
422*62c56f98SSadaf Ebrahimi             goto ssl_exit;
423*62c56f98SSadaf Ebrahimi         }
424*62c56f98SSadaf Ebrahimi 
425*62c56f98SSadaf Ebrahimi         mbedtls_printf("%s\n", buf);
426*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
427*62c56f98SSadaf Ebrahimi 
428*62c56f98SSadaf Ebrahimi         mbedtls_ssl_close_notify(&ssl);
429*62c56f98SSadaf Ebrahimi 
430*62c56f98SSadaf Ebrahimi ssl_exit:
431*62c56f98SSadaf Ebrahimi         mbedtls_ssl_free(&ssl);
432*62c56f98SSadaf Ebrahimi         mbedtls_ssl_config_free(&conf);
433*62c56f98SSadaf Ebrahimi     } else {
434*62c56f98SSadaf Ebrahimi         goto usage;
435*62c56f98SSadaf Ebrahimi     }
436*62c56f98SSadaf Ebrahimi 
437*62c56f98SSadaf Ebrahimi     exit_code = MBEDTLS_EXIT_SUCCESS;
438*62c56f98SSadaf Ebrahimi 
439*62c56f98SSadaf Ebrahimi exit:
440*62c56f98SSadaf Ebrahimi 
441*62c56f98SSadaf Ebrahimi     mbedtls_net_free(&server_fd);
442*62c56f98SSadaf Ebrahimi     mbedtls_x509_crt_free(&cacert);
443*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRL_PARSE_C)
444*62c56f98SSadaf Ebrahimi     mbedtls_x509_crl_free(&cacrl);
445*62c56f98SSadaf Ebrahimi #endif
446*62c56f98SSadaf Ebrahimi     mbedtls_ctr_drbg_free(&ctr_drbg);
447*62c56f98SSadaf Ebrahimi     mbedtls_entropy_free(&entropy);
448*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
449*62c56f98SSadaf Ebrahimi     mbedtls_psa_crypto_free();
450*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
451*62c56f98SSadaf Ebrahimi 
452*62c56f98SSadaf Ebrahimi     mbedtls_exit(exit_code);
453*62c56f98SSadaf Ebrahimi }
454*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
455*62c56f98SSadaf Ebrahimi           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
456*62c56f98SSadaf Ebrahimi           MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
457