1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Root CA 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_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
13a8e1175bSopenharmony_ci    !defined(MBEDTLS_TIMING_C)
14a8e1175bSopenharmony_ciint main(void)
15a8e1175bSopenharmony_ci{
16a8e1175bSopenharmony_ci    mbedtls_printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
17a8e1175bSopenharmony_ci                   "MBEDTLS_TIMING_C not defined.\n");
18a8e1175bSopenharmony_ci    mbedtls_exit(0);
19a8e1175bSopenharmony_ci}
20a8e1175bSopenharmony_ci#else
21a8e1175bSopenharmony_ci
22a8e1175bSopenharmony_ci#include "mbedtls/error.h"
23a8e1175bSopenharmony_ci#include "mbedtls/timing.h"
24a8e1175bSopenharmony_ci#include "mbedtls/x509_crt.h"
25a8e1175bSopenharmony_ci
26a8e1175bSopenharmony_ci#include <stdio.h>
27a8e1175bSopenharmony_ci#include <stdlib.h>
28a8e1175bSopenharmony_ci#include <string.h>
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci#define DFL_ITERATIONS          1
31a8e1175bSopenharmony_ci#define DFL_PRIME_CACHE         1
32a8e1175bSopenharmony_ci
33a8e1175bSopenharmony_ci#define USAGE \
34a8e1175bSopenharmony_ci    "\n usage: load_roots param=<>... [--] FILE...\n"   \
35a8e1175bSopenharmony_ci    "\n acceptable parameters:\n"                       \
36a8e1175bSopenharmony_ci    "    iterations=%%d        Iteration count (not including cache priming); default: 1\n"  \
37a8e1175bSopenharmony_ci    "    prime=%%d             Prime the disk read cache? Default: 1 (yes)\n"  \
38a8e1175bSopenharmony_ci    "\n"
39a8e1175bSopenharmony_ci
40a8e1175bSopenharmony_ci
41a8e1175bSopenharmony_ci/*
42a8e1175bSopenharmony_ci * global options
43a8e1175bSopenharmony_ci */
44a8e1175bSopenharmony_cistruct options {
45a8e1175bSopenharmony_ci    const char **filenames;     /* NULL-terminated list of file names */
46a8e1175bSopenharmony_ci    unsigned iterations;        /* Number of iterations to time */
47a8e1175bSopenharmony_ci    int prime_cache;            /* Prime the disk read cache? */
48a8e1175bSopenharmony_ci} opt;
49a8e1175bSopenharmony_ci
50a8e1175bSopenharmony_ci
51a8e1175bSopenharmony_ciint read_certificates(const char *const *filenames)
52a8e1175bSopenharmony_ci{
53a8e1175bSopenharmony_ci    mbedtls_x509_crt cas;
54a8e1175bSopenharmony_ci    int ret = 0;
55a8e1175bSopenharmony_ci    const char *const *cur;
56a8e1175bSopenharmony_ci
57a8e1175bSopenharmony_ci    mbedtls_x509_crt_init(&cas);
58a8e1175bSopenharmony_ci
59a8e1175bSopenharmony_ci    for (cur = filenames; *cur != NULL; cur++) {
60a8e1175bSopenharmony_ci        ret = mbedtls_x509_crt_parse_file(&cas, *cur);
61a8e1175bSopenharmony_ci        if (ret != 0) {
62a8e1175bSopenharmony_ci#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
63a8e1175bSopenharmony_ci            char error_message[200];
64a8e1175bSopenharmony_ci            mbedtls_strerror(ret, error_message, sizeof(error_message));
65a8e1175bSopenharmony_ci            printf("\n%s: -0x%04x (%s)\n",
66a8e1175bSopenharmony_ci                   *cur, (unsigned) -ret, error_message);
67a8e1175bSopenharmony_ci#else
68a8e1175bSopenharmony_ci            printf("\n%s: -0x%04x\n",
69a8e1175bSopenharmony_ci                   *cur, (unsigned) -ret);
70a8e1175bSopenharmony_ci#endif
71a8e1175bSopenharmony_ci            goto exit;
72a8e1175bSopenharmony_ci        }
73a8e1175bSopenharmony_ci    }
74a8e1175bSopenharmony_ci
75a8e1175bSopenharmony_ciexit:
76a8e1175bSopenharmony_ci    mbedtls_x509_crt_free(&cas);
77a8e1175bSopenharmony_ci    return ret == 0;
78a8e1175bSopenharmony_ci}
79a8e1175bSopenharmony_ci
80a8e1175bSopenharmony_ciint main(int argc, char *argv[])
81a8e1175bSopenharmony_ci{
82a8e1175bSopenharmony_ci    int exit_code = MBEDTLS_EXIT_FAILURE;
83a8e1175bSopenharmony_ci    unsigned i, j;
84a8e1175bSopenharmony_ci    struct mbedtls_timing_hr_time timer;
85a8e1175bSopenharmony_ci    unsigned long ms;
86a8e1175bSopenharmony_ci
87a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
88a8e1175bSopenharmony_ci    psa_status_t status = psa_crypto_init();
89a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
90a8e1175bSopenharmony_ci        mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
91a8e1175bSopenharmony_ci                        (int) status);
92a8e1175bSopenharmony_ci        goto exit;
93a8e1175bSopenharmony_ci    }
94a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
95a8e1175bSopenharmony_ci
96a8e1175bSopenharmony_ci    if (argc <= 1) {
97a8e1175bSopenharmony_ci        mbedtls_printf(USAGE);
98a8e1175bSopenharmony_ci        goto exit;
99a8e1175bSopenharmony_ci    }
100a8e1175bSopenharmony_ci
101a8e1175bSopenharmony_ci    opt.filenames = NULL;
102a8e1175bSopenharmony_ci    opt.iterations = DFL_ITERATIONS;
103a8e1175bSopenharmony_ci    opt.prime_cache = DFL_PRIME_CACHE;
104a8e1175bSopenharmony_ci
105a8e1175bSopenharmony_ci    for (i = 1; i < (unsigned) argc; i++) {
106a8e1175bSopenharmony_ci        char *p = argv[i];
107a8e1175bSopenharmony_ci        char *q = NULL;
108a8e1175bSopenharmony_ci
109a8e1175bSopenharmony_ci        if (strcmp(p, "--") == 0) {
110a8e1175bSopenharmony_ci            break;
111a8e1175bSopenharmony_ci        }
112a8e1175bSopenharmony_ci        if ((q = strchr(p, '=')) == NULL) {
113a8e1175bSopenharmony_ci            break;
114a8e1175bSopenharmony_ci        }
115a8e1175bSopenharmony_ci        *q++ = '\0';
116a8e1175bSopenharmony_ci
117a8e1175bSopenharmony_ci        for (j = 0; p + j < q; j++) {
118a8e1175bSopenharmony_ci            if (argv[i][j] >= 'A' && argv[i][j] <= 'Z') {
119a8e1175bSopenharmony_ci                argv[i][j] |= 0x20;
120a8e1175bSopenharmony_ci            }
121a8e1175bSopenharmony_ci        }
122a8e1175bSopenharmony_ci
123a8e1175bSopenharmony_ci        if (strcmp(p, "iterations") == 0) {
124a8e1175bSopenharmony_ci            opt.iterations = atoi(q);
125a8e1175bSopenharmony_ci        } else if (strcmp(p, "prime") == 0) {
126a8e1175bSopenharmony_ci            opt.iterations = atoi(q) != 0;
127a8e1175bSopenharmony_ci        } else {
128a8e1175bSopenharmony_ci            mbedtls_printf("Unknown option: %s\n", p);
129a8e1175bSopenharmony_ci            mbedtls_printf(USAGE);
130a8e1175bSopenharmony_ci            goto exit;
131a8e1175bSopenharmony_ci        }
132a8e1175bSopenharmony_ci    }
133a8e1175bSopenharmony_ci
134a8e1175bSopenharmony_ci    opt.filenames = (const char **) argv + i;
135a8e1175bSopenharmony_ci    if (*opt.filenames == 0) {
136a8e1175bSopenharmony_ci        mbedtls_printf("Missing list of certificate files to parse\n");
137a8e1175bSopenharmony_ci        goto exit;
138a8e1175bSopenharmony_ci    }
139a8e1175bSopenharmony_ci
140a8e1175bSopenharmony_ci    mbedtls_printf("Parsing %u certificates", argc - i);
141a8e1175bSopenharmony_ci    if (opt.prime_cache) {
142a8e1175bSopenharmony_ci        if (!read_certificates(opt.filenames)) {
143a8e1175bSopenharmony_ci            goto exit;
144a8e1175bSopenharmony_ci        }
145a8e1175bSopenharmony_ci        mbedtls_printf(" ");
146a8e1175bSopenharmony_ci    }
147a8e1175bSopenharmony_ci
148a8e1175bSopenharmony_ci    (void) mbedtls_timing_get_timer(&timer, 1);
149a8e1175bSopenharmony_ci    for (i = 1; i <= opt.iterations; i++) {
150a8e1175bSopenharmony_ci        if (!read_certificates(opt.filenames)) {
151a8e1175bSopenharmony_ci            goto exit;
152a8e1175bSopenharmony_ci        }
153a8e1175bSopenharmony_ci        mbedtls_printf(".");
154a8e1175bSopenharmony_ci    }
155a8e1175bSopenharmony_ci    ms = mbedtls_timing_get_timer(&timer, 0);
156a8e1175bSopenharmony_ci    mbedtls_printf("\n%u iterations -> %lu ms\n", opt.iterations, ms);
157a8e1175bSopenharmony_ci    exit_code = MBEDTLS_EXIT_SUCCESS;
158a8e1175bSopenharmony_ci
159a8e1175bSopenharmony_ciexit:
160a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
161a8e1175bSopenharmony_ci    mbedtls_psa_crypto_free();
162a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
163a8e1175bSopenharmony_ci    mbedtls_exit(exit_code);
164a8e1175bSopenharmony_ci}
165a8e1175bSopenharmony_ci#endif /* necessary configuration */
166