A local copy of OpenSSL from GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.0 KiB

  1. /*
  2. * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <openssl/pem.h>
  12. #include <openssl/err.h>
  13. #include <openssl/pkcs12.h>
  14. /* Simple PKCS#12 file reader */
  15. static char *find_friendly_name(PKCS12 *p12)
  16. {
  17. STACK_OF(PKCS7) *safes;
  18. int n, m;
  19. char *name = NULL;
  20. PKCS7 *safe;
  21. STACK_OF(PKCS12_SAFEBAG) *bags;
  22. PKCS12_SAFEBAG *bag;
  23. if ((safes = PKCS12_unpack_authsafes(p12)) == NULL)
  24. return NULL;
  25. for (n = 0; n < sk_PKCS7_num(safes) && name == NULL; n++) {
  26. safe = sk_PKCS7_value(safes, n);
  27. if (OBJ_obj2nid(safe->type) != NID_pkcs7_data
  28. || (bags = PKCS12_unpack_p7data(safe)) == NULL)
  29. continue;
  30. for (m = 0; m < sk_PKCS12_SAFEBAG_num(bags) && name == NULL; m++) {
  31. bag = sk_PKCS12_SAFEBAG_value(bags, m);
  32. name = PKCS12_get_friendlyname(bag);
  33. }
  34. sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
  35. }
  36. sk_PKCS7_pop_free(safes, PKCS7_free);
  37. return name;
  38. }
  39. int main(int argc, char **argv)
  40. {
  41. FILE *fp;
  42. EVP_PKEY *pkey = NULL;
  43. X509 *cert = NULL;
  44. STACK_OF(X509) *ca = NULL;
  45. PKCS12 *p12 = NULL;
  46. char *name = NULL;
  47. int i, ret = EXIT_FAILURE;
  48. if (argc != 4) {
  49. fprintf(stderr, "Usage: pkread p12file password opfile\n");
  50. exit(EXIT_FAILURE);
  51. }
  52. if ((fp = fopen(argv[1], "rb")) == NULL) {
  53. fprintf(stderr, "Error opening file %s\n", argv[1]);
  54. exit(EXIT_FAILURE);
  55. }
  56. p12 = d2i_PKCS12_fp(fp, NULL);
  57. fclose(fp);
  58. if (p12 == NULL) {
  59. fprintf(stderr, "Error reading PKCS#12 file\n");
  60. ERR_print_errors_fp(stderr);
  61. goto err;
  62. }
  63. if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) {
  64. fprintf(stderr, "Error parsing PKCS#12 file\n");
  65. ERR_print_errors_fp(stderr);
  66. goto err;
  67. }
  68. name = find_friendly_name(p12);
  69. PKCS12_free(p12);
  70. if ((fp = fopen(argv[3], "w")) == NULL) {
  71. fprintf(stderr, "Error opening file %s\n", argv[3]);
  72. goto err;
  73. }
  74. if (name != NULL)
  75. fprintf(fp, "***Friendly Name***\n%s\n", name);
  76. if (pkey != NULL) {
  77. fprintf(fp, "***Private Key***\n");
  78. PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
  79. }
  80. if (cert != NULL) {
  81. fprintf(fp, "***User Certificate***\n");
  82. PEM_write_X509_AUX(fp, cert);
  83. }
  84. if (ca != NULL && sk_X509_num(ca) > 0) {
  85. fprintf(fp, "***Other Certificates***\n");
  86. for (i = 0; i < sk_X509_num(ca); i++)
  87. PEM_write_X509_AUX(fp, sk_X509_value(ca, i));
  88. }
  89. fclose(fp);
  90. ret = EXIT_SUCCESS;
  91. err:
  92. OPENSSL_free(name);
  93. X509_free(cert);
  94. EVP_PKEY_free(pkey);
  95. sk_X509_pop_free(ca, X509_free);
  96. return ret;
  97. }