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