1/* 2 * Key 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_BIGNUM_C) && \ 13 defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \ 14 defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C) 15#include "mbedtls/error.h" 16#include "mbedtls/rsa.h" 17#include "mbedtls/pk.h" 18#include "mbedtls/entropy.h" 19#include "mbedtls/ctr_drbg.h" 20 21#include <string.h> 22#endif 23 24#define MODE_NONE 0 25#define MODE_PRIVATE 1 26#define MODE_PUBLIC 2 27 28#define DFL_MODE MODE_NONE 29#define DFL_FILENAME "keyfile.key" 30#define DFL_PASSWORD "" 31#define DFL_PASSWORD_FILE "" 32#define DFL_DEBUG_LEVEL 0 33 34#define USAGE \ 35 "\n usage: key_app param=<>...\n" \ 36 "\n acceptable parameters:\n" \ 37 " mode=private|public default: none\n" \ 38 " filename=%%s default: keyfile.key\n" \ 39 " password=%%s default: \"\"\n" \ 40 " password_file=%%s default: \"\"\n" \ 41 "\n" 42 43#if !defined(MBEDTLS_BIGNUM_C) || \ 44 !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ 45 !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) 46int main(void) 47{ 48 mbedtls_printf("MBEDTLS_BIGNUM_C and/or " 49 "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or " 50 "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined.\n"); 51 mbedtls_exit(0); 52} 53#else 54 55 56#if defined(MBEDTLS_ECP_C) 57static int show_ecp_key(const mbedtls_ecp_keypair *ecp, int has_private) 58{ 59 int ret = 0; 60 61 const mbedtls_ecp_curve_info *curve_info = 62 mbedtls_ecp_curve_info_from_grp_id( 63 mbedtls_ecp_keypair_get_group_id(ecp)); 64 mbedtls_printf("curve: %s\n", curve_info->name); 65 66 mbedtls_ecp_group grp; 67 mbedtls_ecp_group_init(&grp); 68 mbedtls_mpi D; 69 mbedtls_mpi_init(&D); 70 mbedtls_ecp_point pt; 71 mbedtls_ecp_point_init(&pt); 72 mbedtls_mpi X, Y; 73 mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); 74 75 MBEDTLS_MPI_CHK(mbedtls_ecp_export(ecp, &grp, 76 (has_private ? &D : NULL), 77 &pt)); 78 79 unsigned char point_bin[MBEDTLS_ECP_MAX_PT_LEN]; 80 size_t len = 0; 81 MBEDTLS_MPI_CHK(mbedtls_ecp_point_write_binary( 82 &grp, &pt, MBEDTLS_ECP_PF_UNCOMPRESSED, 83 &len, point_bin, sizeof(point_bin))); 84 switch (mbedtls_ecp_get_type(&grp)) { 85 case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS: 86 if ((len & 1) == 0 || point_bin[0] != 0x04) { 87 /* Point in an unxepected format. This shouldn't happen. */ 88 ret = -1; 89 goto cleanup; 90 } 91 MBEDTLS_MPI_CHK( 92 mbedtls_mpi_read_binary(&X, point_bin + 1, len / 2)); 93 MBEDTLS_MPI_CHK( 94 mbedtls_mpi_read_binary(&Y, point_bin + 1 + len / 2, len / 2)); 95 mbedtls_mpi_write_file("X_Q: ", &X, 16, NULL); 96 mbedtls_mpi_write_file("Y_Q: ", &Y, 16, NULL); 97 break; 98 case MBEDTLS_ECP_TYPE_MONTGOMERY: 99 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, point_bin, len)); 100 mbedtls_mpi_write_file("X_Q: ", &X, 16, NULL); 101 break; 102 default: 103 mbedtls_printf( 104 "This program does not yet support listing coordinates for this curve type.\n"); 105 break; 106 } 107 108 if (has_private) { 109 mbedtls_mpi_write_file("D: ", &D, 16, NULL); 110 } 111 112cleanup: 113 mbedtls_ecp_group_free(&grp); 114 mbedtls_mpi_free(&D); 115 mbedtls_ecp_point_free(&pt); 116 mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); 117 return ret; 118} 119#endif 120 121/* 122 * global options 123 */ 124struct options { 125 int mode; /* the mode to run the application in */ 126 const char *filename; /* filename of the key file */ 127 const char *password; /* password for the private key */ 128 const char *password_file; /* password_file for the private key */ 129} opt; 130 131int main(int argc, char *argv[]) 132{ 133 int ret = 1; 134 int exit_code = MBEDTLS_EXIT_FAILURE; 135 char buf[1024]; 136 int i; 137 char *p, *q; 138 139 const char *pers = "pkey/key_app"; 140 mbedtls_entropy_context entropy; 141 mbedtls_ctr_drbg_context ctr_drbg; 142 143 mbedtls_pk_context pk; 144 mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; 145 146 /* 147 * Set to sane values 148 */ 149 mbedtls_entropy_init(&entropy); 150 mbedtls_ctr_drbg_init(&ctr_drbg); 151 152 mbedtls_pk_init(&pk); 153 memset(buf, 0, sizeof(buf)); 154 155#if defined(MBEDTLS_USE_PSA_CRYPTO) 156 psa_status_t status = psa_crypto_init(); 157 if (status != PSA_SUCCESS) { 158 mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n", 159 (int) status); 160 goto cleanup; 161 } 162#endif /* MBEDTLS_USE_PSA_CRYPTO */ 163 164 mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q); 165 mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP); 166 mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP); 167 168 if (argc < 2) { 169usage: 170 mbedtls_printf(USAGE); 171 goto cleanup; 172 } 173 174 opt.mode = DFL_MODE; 175 opt.filename = DFL_FILENAME; 176 opt.password = DFL_PASSWORD; 177 opt.password_file = DFL_PASSWORD_FILE; 178 179 for (i = 1; i < argc; i++) { 180 p = argv[i]; 181 if ((q = strchr(p, '=')) == NULL) { 182 goto usage; 183 } 184 *q++ = '\0'; 185 186 if (strcmp(p, "mode") == 0) { 187 if (strcmp(q, "private") == 0) { 188 opt.mode = MODE_PRIVATE; 189 } else if (strcmp(q, "public") == 0) { 190 opt.mode = MODE_PUBLIC; 191 } else { 192 goto usage; 193 } 194 } else if (strcmp(p, "filename") == 0) { 195 opt.filename = q; 196 } else if (strcmp(p, "password") == 0) { 197 opt.password = q; 198 } else if (strcmp(p, "password_file") == 0) { 199 opt.password_file = q; 200 } else { 201 goto usage; 202 } 203 } 204 205 if (opt.mode == MODE_PRIVATE) { 206 if (strlen(opt.password) && strlen(opt.password_file)) { 207 mbedtls_printf("Error: cannot have both password and password_file\n"); 208 goto usage; 209 } 210 211 if (strlen(opt.password_file)) { 212 FILE *f; 213 214 mbedtls_printf("\n . Loading the password file ..."); 215 if ((f = fopen(opt.password_file, "rb")) == NULL) { 216 mbedtls_printf(" failed\n ! fopen returned NULL\n"); 217 goto cleanup; 218 } 219 if (fgets(buf, sizeof(buf), f) == NULL) { 220 fclose(f); 221 mbedtls_printf("Error: fgets() failed to retrieve password\n"); 222 goto cleanup; 223 } 224 fclose(f); 225 226 i = (int) strlen(buf); 227 if (buf[i - 1] == '\n') { 228 buf[i - 1] = '\0'; 229 } 230 if (buf[i - 2] == '\r') { 231 buf[i - 2] = '\0'; 232 } 233 opt.password = buf; 234 } 235 236 /* 237 * 1.1. Load the key 238 */ 239 mbedtls_printf("\n . Loading the private key ..."); 240 fflush(stdout); 241 242 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 243 (const unsigned char *) pers, 244 strlen(pers))) != 0) { 245 mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", 246 (unsigned int) -ret); 247 goto cleanup; 248 } 249 250 ret = mbedtls_pk_parse_keyfile(&pk, opt.filename, opt.password, 251 mbedtls_ctr_drbg_random, &ctr_drbg); 252 253 if (ret != 0) { 254 mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", 255 (unsigned int) -ret); 256 goto cleanup; 257 } 258 259 mbedtls_printf(" ok\n"); 260 261 /* 262 * 1.2 Print the key 263 */ 264 mbedtls_printf(" . Key information ...\n"); 265#if defined(MBEDTLS_RSA_C) 266 if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) { 267 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk); 268 269 if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 || 270 (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP)) != 0) { 271 mbedtls_printf(" failed\n ! could not export RSA parameters\n\n"); 272 goto cleanup; 273 } 274 275 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N: ", &N, 16, NULL)); 276 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E: ", &E, 16, NULL)); 277 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("D: ", &D, 16, NULL)); 278 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("P: ", &P, 16, NULL)); 279 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("Q: ", &Q, 16, NULL)); 280 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DP: ", &DP, 16, NULL)); 281 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("DQ: ", &DQ, 16, NULL)); 282 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("QP: ", &QP, 16, NULL)); 283 } else 284#endif 285#if defined(MBEDTLS_ECP_C) 286 if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) { 287 if (show_ecp_key(mbedtls_pk_ec(pk), 1) != 0) { 288 mbedtls_printf(" failed\n ! could not export ECC parameters\n\n"); 289 goto cleanup; 290 } 291 } else 292#endif 293 { 294 mbedtls_printf("Do not know how to print key information for this type\n"); 295 goto cleanup; 296 } 297 } else if (opt.mode == MODE_PUBLIC) { 298 /* 299 * 1.1. Load the key 300 */ 301 mbedtls_printf("\n . Loading the public key ..."); 302 fflush(stdout); 303 304 ret = mbedtls_pk_parse_public_keyfile(&pk, opt.filename); 305 306 if (ret != 0) { 307 mbedtls_printf(" failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", 308 (unsigned int) -ret); 309 goto cleanup; 310 } 311 312 mbedtls_printf(" ok\n"); 313 314 mbedtls_printf(" . Key information ...\n"); 315#if defined(MBEDTLS_RSA_C) 316 if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) { 317 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk); 318 319 if ((ret = mbedtls_rsa_export(rsa, &N, NULL, NULL, 320 NULL, &E)) != 0) { 321 mbedtls_printf(" failed\n ! could not export RSA parameters\n\n"); 322 goto cleanup; 323 } 324 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("N: ", &N, 16, NULL)); 325 MBEDTLS_MPI_CHK(mbedtls_mpi_write_file("E: ", &E, 16, NULL)); 326 } else 327#endif 328#if defined(MBEDTLS_ECP_C) 329 if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY) { 330 if (show_ecp_key(mbedtls_pk_ec(pk), 0) != 0) { 331 mbedtls_printf(" failed\n ! could not export ECC parameters\n\n"); 332 goto cleanup; 333 } 334 } else 335#endif 336 { 337 mbedtls_printf("Do not know how to print key information for this type\n"); 338 goto cleanup; 339 } 340 } else { 341 goto usage; 342 } 343 344 exit_code = MBEDTLS_EXIT_SUCCESS; 345 346cleanup: 347 348#if defined(MBEDTLS_ERROR_C) 349 if (exit_code != MBEDTLS_EXIT_SUCCESS) { 350 mbedtls_strerror(ret, buf, sizeof(buf)); 351 mbedtls_printf(" ! Last error was: %s\n", buf); 352 } 353#endif 354 355 mbedtls_ctr_drbg_free(&ctr_drbg); 356 mbedtls_entropy_free(&entropy); 357 mbedtls_pk_free(&pk); 358#if defined(MBEDTLS_USE_PSA_CRYPTO) 359 mbedtls_psa_crypto_free(); 360#endif /* MBEDTLS_USE_PSA_CRYPTO */ 361 mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q); 362 mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP); 363 mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP); 364 365 mbedtls_exit(exit_code); 366} 367#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && 368 MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ 369