1 /*
2  *  Key reading application
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 
20 #include "mbedtls/build_info.h"
21 
22 #include "mbedtls/platform.h"
23 
24 #if defined(MBEDTLS_BIGNUM_C) && \
25     defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \
26     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
27 #include "mbedtls/error.h"
28 #include "mbedtls/rsa.h"
29 #include "mbedtls/pk.h"
30 #include "mbedtls/entropy.h"
31 #include "mbedtls/ctr_drbg.h"
32 
33 #include <string.h>
34 #endif
35 
36 #define MODE_NONE               0
37 #define MODE_PRIVATE            1
38 #define MODE_PUBLIC             2
39 
40 #define DFL_MODE                MODE_NONE
41 #define DFL_FILENAME            "keyfile.key"
42 #define DFL_PASSWORD            ""
43 #define DFL_PASSWORD_FILE       ""
44 #define DFL_DEBUG_LEVEL         0
45 
46 #define USAGE \
47     "\n usage: key_app param=<>...\n"                   \
48     "\n acceptable parameters:\n"                       \
49     "    mode=private|public default: none\n"           \
50     "    filename=%%s         default: keyfile.key\n"   \
51     "    password=%%s         default: \"\"\n"          \
52     "    password_file=%%s    default: \"\"\n"          \
53     "\n"
54 
55 #if !defined(MBEDTLS_BIGNUM_C) ||                                  \
56     !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
57     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
main(void)58 int main(void)
59 {
60     mbedtls_printf("MBEDTLS_BIGNUM_C and/or "
61                    "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
62                    "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined.\n");
63     mbedtls_exit(0);
64 }
65 #else
66 
67 
68 /*
69  * global options
70  */
71 struct options {
72     int mode;                   /* the mode to run the application in   */
73     const char *filename;       /* filename of the key file             */
74     const char *password;       /* password for the private key         */
75     const char *password_file;  /* password_file for the private key    */
76 } opt;
77 
main(int argc,char * argv[])78 int main(int argc, char *argv[])
79 {
80     int ret = 1;
81     int exit_code = MBEDTLS_EXIT_FAILURE;
82     char buf[1024];
83     int i;
84     char *p, *q;
85 
86     const char *pers = "pkey/key_app";
87     mbedtls_entropy_context entropy;
88     mbedtls_ctr_drbg_context ctr_drbg;
89 
90     mbedtls_pk_context pk;
91     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
92 
93     /*
94      * Set to sane values
95      */
96     mbedtls_entropy_init(&entropy);
97     mbedtls_ctr_drbg_init(&ctr_drbg);
98 
99     mbedtls_pk_init(&pk);
100     memset(buf, 0, sizeof(buf));
101 
102     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
103     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
104     mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
105 
106     if (argc < 2) {
107 usage:
108         mbedtls_printf(USAGE);
109         goto cleanup;
110     }
111 
112     opt.mode                = DFL_MODE;
113     opt.filename            = DFL_FILENAME;
114     opt.password            = DFL_PASSWORD;
115     opt.password_file       = DFL_PASSWORD_FILE;
116 
117     for (i = 1; i < argc; i++) {
118         p = argv[i];
119         if ((q = strchr(p, '=')) == NULL) {
120             goto usage;
121         }
122         *q++ = '\0';
123 
124         if (strcmp(p, "mode") == 0) {
125             if (strcmp(q, "private") == 0) {
126                 opt.mode = MODE_PRIVATE;
127             } else if (strcmp(q, "public") == 0) {
128                 opt.mode = MODE_PUBLIC;
129             } else {
130                 goto usage;
131             }
132         } else if (strcmp(p, "filename") == 0) {
133             opt.filename = q;
134         } else if (strcmp(p, "password") == 0) {
135             opt.password = q;
136         } else if (strcmp(p, "password_file") == 0) {
137             opt.password_file = q;
138         } else {
139             goto usage;
140         }
141     }
142 
143     if (opt.mode == MODE_PRIVATE) {
144         if (strlen(opt.password) && strlen(opt.password_file)) {
145             mbedtls_printf("Error: cannot have both password and password_file\n");
146             goto usage;
147         }
148 
149         if (strlen(opt.password_file)) {
150             FILE *f;
151 
152             mbedtls_printf("\n  . Loading the password file ...");
153             if ((f = fopen(opt.password_file, "rb")) == NULL) {
154                 mbedtls_printf(" failed\n  !  fopen returned NULL\n");
155                 goto cleanup;
156             }
157             if (fgets(buf, sizeof(buf), f) == NULL) {
158                 fclose(f);
159                 mbedtls_printf("Error: fgets() failed to retrieve password\n");
160                 goto cleanup;
161             }
162             fclose(f);
163 
164             i = (int) strlen(buf);
165             if (buf[i - 1] == '\n') {
166                 buf[i - 1] = '\0';
167             }
168             if (buf[i - 2] == '\r') {
169                 buf[i - 2] = '\0';
170             }
171             opt.password = buf;
172         }
173 
174         /*
175          * 1.1. Load the key
176          */
177         mbedtls_printf("\n  . Loading the private key ...");
178         fflush(stdout);
179 
180         if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
181                                          (const unsigned char *) pers,
182                                          strlen(pers))) != 0) {
183             mbedtls_printf(" failed\n  !  mbedtls_ctr_drbg_seed returned -0x%04x\n",
184                            (unsigned int) -ret);
185             goto cleanup;
186         }
187 
188         ret = mbedtls_pk_parse_keyfile(&pk, opt.filename, opt.password,
189                                        mbedtls_ctr_drbg_random, &ctr_drbg);
190 
191         if (ret != 0) {
192             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x\n",
193                            (unsigned int) -ret);
194             goto cleanup;
195         }
196 
197         mbedtls_printf(" ok\n");
198 
199         /*
200          * 1.2 Print the key
201          */
202         mbedtls_printf("  . Key information    ...\n");
203 #if defined(MBEDTLS_RSA_C)
204         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
205             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
206 
207             if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
208                 (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
209                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
210                 goto cleanup;
211             }
212 
213             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
214             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
215             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D:  ", &D, 16, NULL));
216             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("P:  ", &P, 16, NULL));
217             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q:  ", &Q, 16, NULL));
218             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DP: ", &DP, 16, NULL));
219             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL));
220             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL));
221         } else
222 #endif
223 #if defined(MBEDTLS_ECP_C)
224         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
225             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
226             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(X): ",
227                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16,
228                                                    NULL));
229             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Y): ",
230                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16,
231                                                    NULL));
232             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Z): ",
233                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16,
234                                                    NULL));
235             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D   : ", &ecp->MBEDTLS_PRIVATE(d), 16, NULL));
236         } else
237 #endif
238         {
239             mbedtls_printf("Do not know how to print key information for this type\n");
240             goto cleanup;
241         }
242     } else if (opt.mode == MODE_PUBLIC) {
243         /*
244          * 1.1. Load the key
245          */
246         mbedtls_printf("\n  . Loading the public key ...");
247         fflush(stdout);
248 
249         ret = mbedtls_pk_parse_public_keyfile(&pk, opt.filename);
250 
251         if (ret != 0) {
252             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_public_keyfile returned -0x%04x\n",
253                            (unsigned int) -ret);
254             goto cleanup;
255         }
256 
257         mbedtls_printf(" ok\n");
258 
259         mbedtls_printf("  . Key information    ...\n");
260 #if defined(MBEDTLS_RSA_C)
261         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) {
262             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
263 
264             if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL,
265                                           NULL, &E)) != 0) {
266                 mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
267                 goto cleanup;
268             }
269             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N:  ", &N, 16, NULL));
270             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E:  ", &E, 16, NULL));
271         } else
272 #endif
273 #if defined(MBEDTLS_ECP_C)
274         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) {
275             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
276             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(X): ",
277                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16,
278                                                    NULL));
279             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Y): ",
280                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16,
281                                                    NULL));
282             MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q(Z): ",
283                                                    &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16,
284                                                    NULL));
285         } else
286 #endif
287         {
288             mbedtls_printf("Do not know how to print key information for this type\n");
289             goto cleanup;
290         }
291     } else {
292         goto usage;
293     }
294 
295     exit_code = MBEDTLS_EXIT_SUCCESS;
296 
297 cleanup:
298 
299 #if defined(MBEDTLS_ERROR_C)
300     if (exit_code != MBEDTLS_EXIT_SUCCESS) {
301         mbedtls_strerror(ret, buf, sizeof(buf));
302         mbedtls_printf("  !  Last error was: %s\n", buf);
303     }
304 #endif
305 
306     mbedtls_ctr_drbg_free(&ctr_drbg);
307     mbedtls_entropy_free(&entropy);
308 
309     mbedtls_pk_free(&pk);
310     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
311     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
312     mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
313 
314     mbedtls_exit(exit_code);
315 }
316 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
317           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
318