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