1 /* 2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <stdint.h> 29 #include <errno.h> 30 31 #include "brssl.h" 32 #include "bearssl.h" 33 34 typedef struct { 35 int print_text; 36 int print_C; 37 const char *rawder; 38 const char *rawpem; 39 const char *pk8der; 40 const char *pk8pem; 41 } outspec; 42 43 static void 44 print_int_text(const char *name, const unsigned char *buf, size_t len) 45 { 46 size_t u; 47 48 printf("%s = ", name); 49 for (u = 0; u < len; u ++) { 50 printf("%02X", buf[u]); 51 } 52 printf("\n"); 53 } 54 55 static void 56 print_int_C(const char *name, const unsigned char *buf, size_t len) 57 { 58 size_t u; 59 60 printf("\nstatic const unsigned char %s[] = {", name); 61 for (u = 0; u < len; u ++) { 62 if (u != 0) { 63 printf(","); 64 } 65 if (u % 12 == 0) { 66 printf("\n\t"); 67 } else { 68 printf(" "); 69 } 70 printf("0x%02X", buf[u]); 71 } 72 printf("\n};\n"); 73 } 74 75 static int 76 write_to_file(const char *name, const void *data, size_t len) 77 { 78 FILE *f; 79 80 f = fopen(name, "wb"); 81 if (f == NULL) { 82 fprintf(stderr, 83 "ERROR: cannot open file '%s' for writing\n", 84 name); 85 return 0; 86 } 87 if (fwrite(data, 1, len, f) != len) { 88 fclose(f); 89 fprintf(stderr, 90 "ERROR: cannot write to file '%s'\n", 91 name); 92 return 0; 93 } 94 fclose(f); 95 return 1; 96 } 97 98 static int 99 write_to_pem_file(const char *name, 100 const void *data, size_t len, const char *banner) 101 { 102 void *pem; 103 size_t pemlen; 104 int r; 105 106 pemlen = br_pem_encode(NULL, NULL, len, banner, 0); 107 pem = xmalloc(pemlen + 1); 108 br_pem_encode(pem, data, len, banner, 0); 109 r = write_to_file(name, pem, pemlen); 110 xfree(pem); 111 return r; 112 } 113 114 static int 115 print_rsa(const br_rsa_private_key *sk, outspec *os) 116 { 117 int ret; 118 unsigned char *n, *d, *buf; 119 uint32_t e; 120 size_t nlen, dlen, len; 121 br_rsa_compute_modulus cm; 122 br_rsa_compute_pubexp ce; 123 br_rsa_compute_privexp cd; 124 br_rsa_public_key pk; 125 unsigned char ebuf[4]; 126 127 n = NULL; 128 d = NULL; 129 buf = NULL; 130 ret = 1; 131 if (os->print_text) { 132 print_int_text("p ", sk->p, sk->plen); 133 print_int_text("q ", sk->q, sk->qlen); 134 print_int_text("dp", sk->dp, sk->dplen); 135 print_int_text("dq", sk->dq, sk->dqlen); 136 print_int_text("iq", sk->iq, sk->iqlen); 137 } 138 if (os->print_C) { 139 print_int_C("RSA_P", sk->p, sk->plen); 140 print_int_C("RSA_Q", sk->q, sk->qlen); 141 print_int_C("RSA_DP", sk->dp, sk->dplen); 142 print_int_C("RSA_DQ", sk->dq, sk->dqlen); 143 print_int_C("RSA_IQ", sk->iq, sk->iqlen); 144 printf("\nstatic const br_rsa_private_key RSA = {\n"); 145 printf("\t%lu,\n", (unsigned long)sk->n_bitlen); 146 printf("\t(unsigned char *)RSA_P, sizeof RSA_P,\n"); 147 printf("\t(unsigned char *)RSA_Q, sizeof RSA_Q,\n"); 148 printf("\t(unsigned char *)RSA_DP, sizeof RSA_DP,\n"); 149 printf("\t(unsigned char *)RSA_DQ, sizeof RSA_DQ,\n"); 150 printf("\t(unsigned char *)RSA_IQ, sizeof RSA_IQ\n"); 151 printf("};\n"); 152 } 153 154 if (os->rawder == NULL && os->rawpem == NULL 155 && os->pk8der == NULL && os->pk8pem == NULL) 156 { 157 return ret; 158 } 159 160 cm = br_rsa_compute_modulus_get_default(); 161 ce = br_rsa_compute_pubexp_get_default(); 162 cd = br_rsa_compute_privexp_get_default(); 163 nlen = cm(NULL, sk); 164 if (nlen == 0) { 165 goto print_RSA_error; 166 } 167 n = xmalloc(nlen); 168 if (cm(n, sk) != nlen) { 169 goto print_RSA_error; 170 } 171 e = ce(sk); 172 if (e == 0) { 173 goto print_RSA_error; 174 } 175 dlen = cd(NULL, sk, e); 176 if (dlen == 0) { 177 goto print_RSA_error; 178 } 179 d = xmalloc(dlen); 180 if (cd(d, sk, e) != dlen) { 181 goto print_RSA_error; 182 } 183 ebuf[0] = e >> 24; 184 ebuf[1] = e >> 16; 185 ebuf[2] = e >> 8; 186 ebuf[3] = e; 187 pk.n = n; 188 pk.nlen = nlen; 189 pk.e = ebuf; 190 pk.elen = sizeof ebuf; 191 192 if (os->rawder != NULL || os->rawpem != NULL) { 193 len = br_encode_rsa_raw_der(NULL, sk, &pk, d, dlen); 194 if (len == 0) { 195 goto print_RSA_error; 196 } 197 buf = xmalloc(len); 198 if (br_encode_rsa_raw_der(buf, sk, &pk, d, dlen) != len) { 199 goto print_RSA_error; 200 } 201 if (os->rawder != NULL) { 202 ret &= write_to_file(os->rawder, buf, len); 203 } 204 if (os->rawpem != NULL) { 205 ret &= write_to_pem_file(os->rawpem, 206 buf, len, "RSA PRIVATE KEY"); 207 } 208 xfree(buf); 209 buf = NULL; 210 } 211 212 if (os->pk8der != NULL || os->pk8pem != NULL) { 213 len = br_encode_rsa_pkcs8_der(NULL, sk, &pk, d, dlen); 214 if (len == 0) { 215 goto print_RSA_error; 216 } 217 buf = xmalloc(len); 218 if (br_encode_rsa_pkcs8_der(buf, sk, &pk, d, dlen) != len) { 219 goto print_RSA_error; 220 } 221 if (os->pk8der != NULL) { 222 ret &= write_to_file(os->pk8der, buf, len); 223 } 224 if (os->pk8pem != NULL) { 225 ret &= write_to_pem_file(os->pk8pem, 226 buf, len, "PRIVATE KEY"); 227 } 228 xfree(buf); 229 buf = NULL; 230 } 231 232 print_RSA_exit: 233 xfree(n); 234 xfree(d); 235 xfree(buf); 236 return ret; 237 238 print_RSA_error: 239 fprintf(stderr, "ERROR: cannot encode RSA key\n"); 240 ret = 0; 241 goto print_RSA_exit; 242 } 243 244 static int 245 print_ec(const br_ec_private_key *sk, outspec *os) 246 { 247 br_ec_public_key pk; 248 unsigned kbuf[BR_EC_KBUF_PUB_MAX_SIZE]; 249 unsigned char *buf; 250 size_t len; 251 int r; 252 253 if (os->print_text) { 254 print_int_text("x", sk->x, sk->xlen); 255 } 256 if (os->print_C) { 257 print_int_C("EC_X", sk->x, sk->xlen); 258 printf("\nstatic const br_ec_private_key EC = {\n"); 259 printf("\t%d,\n", sk->curve); 260 printf("\t(unsigned char *)EC_X, sizeof EC_X\n"); 261 printf("};\n"); 262 } 263 264 if (os->rawder == NULL && os->rawpem == NULL 265 && os->pk8der == NULL && os->pk8pem == NULL) 266 { 267 return 1; 268 } 269 if (br_ec_compute_pub(br_ec_get_default(), &pk, kbuf, sk) == 0) { 270 fprintf(stderr, 271 "ERROR: cannot re-encode (unsupported curve)\n"); 272 return 0; 273 } 274 275 r = 1; 276 if (os->rawder != NULL || os->rawpem != NULL) { 277 len = br_encode_ec_raw_der(NULL, sk, &pk); 278 if (len == 0) { 279 fprintf(stderr, "ERROR: cannot re-encode" 280 " (unsupported curve)\n"); 281 return 0; 282 } 283 buf = xmalloc(len); 284 if (br_encode_ec_raw_der(buf, sk, &pk) != len) { 285 fprintf(stderr, "ERROR: re-encode failure\n"); 286 xfree(buf); 287 return 0; 288 } 289 if (os->rawder != NULL) { 290 r &= write_to_file(os->rawder, buf, len); 291 } 292 if (os->rawpem != NULL) { 293 r &= write_to_pem_file(os->rawpem, 294 buf, len, "EC PRIVATE KEY"); 295 } 296 xfree(buf); 297 } 298 if (os->pk8der != NULL || os->pk8pem != NULL) { 299 len = br_encode_ec_pkcs8_der(NULL, sk, &pk); 300 if (len == 0) { 301 fprintf(stderr, "ERROR: cannot re-encode" 302 " (unsupported curve)\n"); 303 return 0; 304 } 305 buf = xmalloc(len); 306 if (br_encode_ec_pkcs8_der(buf, sk, &pk) != len) { 307 fprintf(stderr, "ERROR: re-encode failure\n"); 308 xfree(buf); 309 return 0; 310 } 311 if (os->pk8der != NULL) { 312 r &= write_to_file(os->pk8der, buf, len); 313 } 314 if (os->pk8pem != NULL) { 315 r &= write_to_pem_file(os->pk8pem, 316 buf, len, "PRIVATE KEY"); 317 } 318 xfree(buf); 319 } 320 return r; 321 } 322 323 static int 324 parse_rsa_spec(const char *kgen_spec, unsigned *size, uint32_t *pubexp) 325 { 326 const char *p; 327 char *end; 328 unsigned long ul; 329 330 p = kgen_spec; 331 if (*p != 'r' && *p != 'R') { 332 return 0; 333 } 334 p ++; 335 if (*p != 's' && *p != 'S') { 336 return 0; 337 } 338 p ++; 339 if (*p != 'a' && *p != 'A') { 340 return 0; 341 } 342 p ++; 343 if (*p == 0) { 344 *size = 2048; 345 *pubexp = 3; 346 return 1; 347 } else if (*p != ':') { 348 return 0; 349 } 350 p ++; 351 ul = strtoul(p, &end, 10); 352 if (ul < 512 || ul > 32768) { 353 return 0; 354 } 355 *size = ul; 356 p = end; 357 if (*p == 0) { 358 *pubexp = 3; 359 return 1; 360 } else if (*p != ':') { 361 return 0; 362 } 363 p ++; 364 ul = strtoul(p, &end, 10); 365 if ((ul & 1) == 0 || ul == 1 || ((ul >> 30) >> 2) != 0) { 366 return 0; 367 } 368 *pubexp = ul; 369 if (*end != 0) { 370 return 0; 371 } 372 return 1; 373 } 374 375 static int 376 keygen_rsa(unsigned size, uint32_t pubexp, outspec *os) 377 { 378 br_hmac_drbg_context rng; 379 br_prng_seeder seeder; 380 br_rsa_keygen kg; 381 br_rsa_private_key sk; 382 unsigned char *kbuf_priv; 383 uint32_t r; 384 385 seeder = br_prng_seeder_system(NULL); 386 if (seeder == 0) { 387 fprintf(stderr, "ERROR: no system source of randomness\n"); 388 return 0; 389 } 390 br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0); 391 if (!seeder(&rng.vtable)) { 392 fprintf(stderr, "ERROR: system source of randomness failed\n"); 393 return 0; 394 } 395 kbuf_priv = xmalloc(BR_RSA_KBUF_PRIV_SIZE(size)); 396 kg = br_rsa_keygen_get_default(); 397 r = kg(&rng.vtable, &sk, kbuf_priv, NULL, NULL, size, pubexp); 398 if (!r) { 399 fprintf(stderr, "ERROR: RSA key pair generation failed\n"); 400 } else { 401 r = print_rsa(&sk, os); 402 } 403 xfree(kbuf_priv); 404 return r; 405 } 406 407 static int 408 parse_ec_spec(const char *kgen_spec, int *curve) 409 { 410 const char *p; 411 412 *curve = 0; 413 p = kgen_spec; 414 if (*p != 'e' && *p != 'E') { 415 return 0; 416 } 417 p ++; 418 if (*p != 'c' && *p != 'C') { 419 return 0; 420 } 421 p ++; 422 if (*p == 0) { 423 *curve = BR_EC_secp256r1; 424 return 1; 425 } 426 if (*p != ':') { 427 return 0; 428 } 429 *curve = get_curve_by_name(p); 430 return *curve > 0; 431 } 432 433 static int 434 keygen_ec(int curve, outspec *os) 435 { 436 br_hmac_drbg_context rng; 437 br_prng_seeder seeder; 438 const br_ec_impl *impl; 439 br_ec_private_key sk; 440 unsigned char kbuf_priv[BR_EC_KBUF_PRIV_MAX_SIZE]; 441 size_t len; 442 443 seeder = br_prng_seeder_system(NULL); 444 if (seeder == 0) { 445 fprintf(stderr, "ERROR: no system source of randomness\n"); 446 return 0; 447 } 448 br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0); 449 if (!seeder(&rng.vtable)) { 450 fprintf(stderr, "ERROR: system source of randomness failed\n"); 451 return 0; 452 } 453 impl = br_ec_get_default(); 454 len = br_ec_keygen(&rng.vtable, impl, &sk, kbuf_priv, curve); 455 if (len == 0) { 456 fprintf(stderr, "ERROR: curve is not supported\n"); 457 return 0; 458 } 459 return print_ec(&sk, os); 460 } 461 462 static int 463 decode_key(const unsigned char *buf, size_t len, outspec *os) 464 { 465 br_skey_decoder_context dc; 466 int err, ret; 467 468 br_skey_decoder_init(&dc); 469 br_skey_decoder_push(&dc, buf, len); 470 err = br_skey_decoder_last_error(&dc); 471 if (err != 0) { 472 const char *errname, *errmsg; 473 474 fprintf(stderr, "ERROR (decoding): err=%d\n", err); 475 errname = find_error_name(err, &errmsg); 476 if (errname != NULL) { 477 fprintf(stderr, " %s: %s\n", errname, errmsg); 478 } else { 479 fprintf(stderr, " (unknown)\n"); 480 } 481 return 0; 482 } 483 ret = 1; 484 switch (br_skey_decoder_key_type(&dc)) { 485 const br_rsa_private_key *rk; 486 const br_ec_private_key *ek; 487 488 case BR_KEYTYPE_RSA: 489 rk = br_skey_decoder_get_rsa(&dc); 490 printf("RSA key (%lu bits)\n", (unsigned long)rk->n_bitlen); 491 ret = print_rsa(rk, os); 492 break; 493 494 case BR_KEYTYPE_EC: 495 ek = br_skey_decoder_get_ec(&dc); 496 printf("EC key (curve = %d: %s)\n", 497 ek->curve, ec_curve_name(ek->curve)); 498 ret = print_ec(ek, os); 499 break; 500 501 default: 502 fprintf(stderr, "Unknown key type: %d\n", 503 br_skey_decoder_key_type(&dc)); 504 ret = 0; 505 break; 506 } 507 508 return ret; 509 } 510 511 static void 512 usage_skey(void) 513 { 514 fprintf(stderr, 515 "usage: brssl skey [ options ] file...\n"); 516 fprintf(stderr, 517 "options:\n"); 518 fprintf(stderr, 519 " -q suppress verbose messages\n"); 520 fprintf(stderr, 521 " -text print private key details (human-readable)\n"); 522 fprintf(stderr, 523 " -C print private key details (C code)\n"); 524 fprintf(stderr, 525 " -rawder file save private key in 'file' (raw format, DER)\n"); 526 fprintf(stderr, 527 " -rawpem file save private key in 'file' (raw format, PEM)\n"); 528 fprintf(stderr, 529 " -pk8der file save private key in 'file' (PKCS#8 format, DER)\n"); 530 fprintf(stderr, 531 " -pk8pem file save private key in 'file' (PKCS#8 format, PEM)\n"); 532 fprintf(stderr, 533 " -gen spec generate a new key using the provided key specification\n"); 534 fprintf(stderr, 535 " -list list known elliptic curve names\n"); 536 fprintf(stderr, 537 "Key specification begins with a key type, followed by optional parameters\n"); 538 fprintf(stderr, 539 "that depend on the key type, separated by colon characters:\n"); 540 fprintf(stderr, 541 " rsa[:size[:pubexep]] RSA key (defaults: size = 2048, pubexp = 3)\n"); 542 fprintf(stderr, 543 " ec[:curvename] EC key (default curve: secp256r1)\n"); 544 } 545 546 /* see brssl.h */ 547 int 548 do_skey(int argc, char *argv[]) 549 { 550 int retcode; 551 int verbose; 552 int i, num_files; 553 outspec os; 554 unsigned char *buf; 555 size_t len; 556 pem_object *pos; 557 const char *kgen_spec; 558 559 retcode = 0; 560 verbose = 1; 561 os.print_text = 0; 562 os.print_C = 0; 563 os.rawder = NULL; 564 os.rawpem = NULL; 565 os.pk8der = NULL; 566 os.pk8pem = NULL; 567 num_files = 0; 568 buf = NULL; 569 pos = NULL; 570 kgen_spec = NULL; 571 for (i = 0; i < argc; i ++) { 572 const char *arg; 573 574 arg = argv[i]; 575 if (arg[0] != '-') { 576 num_files ++; 577 continue; 578 } 579 argv[i] = NULL; 580 if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) { 581 verbose = 1; 582 } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) { 583 verbose = 0; 584 } else if (eqstr(arg, "-text")) { 585 os.print_text = 1; 586 } else if (eqstr(arg, "-C")) { 587 os.print_C = 1; 588 } else if (eqstr(arg, "-rawder")) { 589 if (++ i >= argc) { 590 fprintf(stderr, 591 "ERROR: no argument for '-rawder'\n"); 592 usage_skey(); 593 goto skey_exit_error; 594 } 595 if (os.rawder != NULL) { 596 fprintf(stderr, 597 "ERROR: multiple '-rawder' options\n"); 598 usage_skey(); 599 goto skey_exit_error; 600 } 601 os.rawder = argv[i]; 602 argv[i] = NULL; 603 } else if (eqstr(arg, "-rawpem")) { 604 if (++ i >= argc) { 605 fprintf(stderr, 606 "ERROR: no argument for '-rawpem'\n"); 607 usage_skey(); 608 goto skey_exit_error; 609 } 610 if (os.rawpem != NULL) { 611 fprintf(stderr, 612 "ERROR: multiple '-rawpem' options\n"); 613 usage_skey(); 614 goto skey_exit_error; 615 } 616 os.rawpem = argv[i]; 617 argv[i] = NULL; 618 } else if (eqstr(arg, "-pk8der")) { 619 if (++ i >= argc) { 620 fprintf(stderr, 621 "ERROR: no argument for '-pk8der'\n"); 622 usage_skey(); 623 goto skey_exit_error; 624 } 625 if (os.pk8der != NULL) { 626 fprintf(stderr, 627 "ERROR: multiple '-pk8der' options\n"); 628 usage_skey(); 629 goto skey_exit_error; 630 } 631 os.pk8der = argv[i]; 632 argv[i] = NULL; 633 } else if (eqstr(arg, "-pk8pem")) { 634 if (++ i >= argc) { 635 fprintf(stderr, 636 "ERROR: no argument for '-pk8pem'\n"); 637 usage_skey(); 638 goto skey_exit_error; 639 } 640 if (os.pk8pem != NULL) { 641 fprintf(stderr, 642 "ERROR: multiple '-pk8pem' options\n"); 643 usage_skey(); 644 goto skey_exit_error; 645 } 646 os.pk8pem = argv[i]; 647 argv[i] = NULL; 648 } else if (eqstr(arg, "-gen")) { 649 if (++ i >= argc) { 650 fprintf(stderr, 651 "ERROR: no argument for '-gen'\n"); 652 usage_skey(); 653 goto skey_exit_error; 654 } 655 if (kgen_spec != NULL) { 656 fprintf(stderr, 657 "ERROR: multiple '-gen' options\n"); 658 usage_skey(); 659 goto skey_exit_error; 660 } 661 kgen_spec = argv[i]; 662 argv[i] = NULL; 663 } else if (eqstr(arg, "-list")) { 664 list_curves(); 665 goto skey_exit; 666 } else { 667 fprintf(stderr, "ERROR: unknown option: '%s'\n", arg); 668 usage_skey(); 669 goto skey_exit_error; 670 } 671 } 672 if (kgen_spec != NULL) { 673 unsigned rsa_size; 674 uint32_t rsa_pubexp; 675 int curve; 676 677 if (num_files != 0) { 678 fprintf(stderr, 679 "ERROR: key files provided while generating\n"); 680 usage_skey(); 681 goto skey_exit_error; 682 } 683 684 if (parse_rsa_spec(kgen_spec, &rsa_size, &rsa_pubexp)) { 685 if (!keygen_rsa(rsa_size, rsa_pubexp, &os)) { 686 goto skey_exit_error; 687 } 688 } else if (parse_ec_spec(kgen_spec, &curve)) { 689 if (!keygen_ec(curve, &os)) { 690 goto skey_exit_error; 691 } 692 } else { 693 fprintf(stderr, 694 "ERROR: unknown key specification: '%s'\n", 695 kgen_spec); 696 usage_skey(); 697 goto skey_exit_error; 698 } 699 } else if (num_files == 0) { 700 fprintf(stderr, "ERROR: no private key provided\n"); 701 usage_skey(); 702 goto skey_exit_error; 703 } 704 705 for (i = 0; i < argc; i ++) { 706 const char *fname; 707 708 fname = argv[i]; 709 if (fname == NULL) { 710 continue; 711 } 712 buf = read_file(fname, &len); 713 if (buf == NULL) { 714 goto skey_exit_error; 715 } 716 if (looks_like_DER(buf, len)) { 717 if (verbose) { 718 fprintf(stderr, "File '%s': ASN.1/DER object\n", 719 fname); 720 } 721 if (!decode_key(buf, len, &os)) { 722 goto skey_exit_error; 723 } 724 } else { 725 size_t u, num; 726 727 if (verbose) { 728 fprintf(stderr, "File '%s': decoding as PEM\n", 729 fname); 730 } 731 pos = decode_pem(buf, len, &num); 732 if (pos == NULL) { 733 goto skey_exit_error; 734 } 735 for (u = 0; pos[u].name; u ++) { 736 const char *name; 737 738 name = pos[u].name; 739 if (eqstr(name, "RSA PRIVATE KEY") 740 || eqstr(name, "EC PRIVATE KEY") 741 || eqstr(name, "PRIVATE KEY")) 742 { 743 if (!decode_key(pos[u].data, 744 pos[u].data_len, &os)) 745 { 746 goto skey_exit_error; 747 } 748 } else { 749 if (verbose) { 750 fprintf(stderr, 751 "(skipping '%s')\n", 752 name); 753 } 754 } 755 } 756 for (u = 0; pos[u].name; u ++) { 757 free_pem_object_contents(&pos[u]); 758 } 759 xfree(pos); 760 pos = NULL; 761 } 762 xfree(buf); 763 buf = NULL; 764 } 765 766 /* 767 * Release allocated structures. 768 */ 769 skey_exit: 770 xfree(buf); 771 if (pos != NULL) { 772 size_t u; 773 774 for (u = 0; pos[u].name; u ++) { 775 free_pem_object_contents(&pos[u]); 776 } 777 xfree(pos); 778 } 779 return retcode; 780 781 skey_exit_error: 782 retcode = -1; 783 goto skey_exit; 784 } 785