pub.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Copyright (C) 2009 Martin Willi
  3. * Copyright (C) 2015-2017 Andreas Steffen
  4. * HSR Hochschule fuer Technik Rapperswil
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * for more details.
  15. */
  16. #include <errno.h>
  17. #include "pki.h"
  18. #include <credentials/certificates/certificate.h>
  19. #include <credentials/certificates/x509.h>
  20. /**
  21. * Extract a public key from a private key/certificate
  22. */
  23. static int pub()
  24. {
  25. cred_encoding_type_t form = PUBKEY_SPKI_ASN1_DER;
  26. credential_type_t type = CRED_PRIVATE_KEY;
  27. int subtype = KEY_ANY;
  28. certificate_t *cert;
  29. private_key_t *private;
  30. public_key_t *public;
  31. chunk_t encoding;
  32. char *file = NULL, *keyid = NULL;
  33. void *cred;
  34. char *arg;
  35. while (TRUE)
  36. {
  37. switch (command_getopt(&arg))
  38. {
  39. case 'h':
  40. return command_usage(NULL);
  41. case 't':
  42. if (streq(arg, "rsa"))
  43. {
  44. type = CRED_PRIVATE_KEY;
  45. subtype = KEY_RSA;
  46. }
  47. else if (streq(arg, "ecdsa"))
  48. {
  49. type = CRED_PRIVATE_KEY;
  50. subtype = KEY_ECDSA;
  51. }
  52. else if (streq(arg, "bliss"))
  53. {
  54. type = CRED_PRIVATE_KEY;
  55. subtype = KEY_BLISS;
  56. }
  57. else if (streq(arg, "priv"))
  58. {
  59. type = CRED_PRIVATE_KEY;
  60. subtype = KEY_ANY;
  61. }
  62. else if (streq(arg, "pub"))
  63. {
  64. type = CRED_PUBLIC_KEY;
  65. subtype = KEY_ANY;
  66. }
  67. else if (streq(arg, "pkcs10"))
  68. {
  69. type = CRED_CERTIFICATE;
  70. subtype = CERT_PKCS10_REQUEST;
  71. }
  72. else if (streq(arg, "x509"))
  73. {
  74. type = CRED_CERTIFICATE;
  75. subtype = CERT_X509;
  76. }
  77. else
  78. {
  79. return command_usage("invalid input type");
  80. }
  81. continue;
  82. case 'f':
  83. if (!get_form(arg, &form, CRED_PUBLIC_KEY))
  84. {
  85. return command_usage("invalid output format");
  86. }
  87. continue;
  88. case 'i':
  89. file = arg;
  90. continue;
  91. case 'x':
  92. keyid = arg;
  93. continue;
  94. case EOF:
  95. break;
  96. default:
  97. return command_usage("invalid --pub option");
  98. }
  99. break;
  100. }
  101. if (file)
  102. {
  103. cred = lib->creds->create(lib->creds, type, subtype,
  104. BUILD_FROM_FILE, file, BUILD_END);
  105. }
  106. else if (keyid)
  107. {
  108. chunk_t chunk;
  109. chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
  110. cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
  111. BUILD_PKCS11_KEYID, chunk, BUILD_END);
  112. free(chunk.ptr);
  113. }
  114. else
  115. {
  116. chunk_t chunk;
  117. set_file_mode(stdin, CERT_ASN1_DER);
  118. if (!chunk_from_fd(0, &chunk))
  119. {
  120. fprintf(stderr, "reading input failed: %s\n", strerror(errno));
  121. return 1;
  122. }
  123. cred = lib->creds->create(lib->creds, type, subtype,
  124. BUILD_BLOB, chunk, BUILD_END);
  125. free(chunk.ptr);
  126. }
  127. if (type == CRED_PRIVATE_KEY)
  128. {
  129. private = cred;
  130. if (!private)
  131. {
  132. fprintf(stderr, "parsing private key failed\n");
  133. return 1;
  134. }
  135. public = private->get_public_key(private);
  136. private->destroy(private);
  137. }
  138. else if (type == CRED_PUBLIC_KEY)
  139. {
  140. public = cred;
  141. if (!public)
  142. {
  143. fprintf(stderr, "parsing public key failed\n");
  144. return 1;
  145. }
  146. }
  147. else
  148. {
  149. cert = cred;
  150. if (!cert)
  151. {
  152. fprintf(stderr, "parsing certificate failed\n");
  153. return 1;
  154. }
  155. public = cert->get_public_key(cert);
  156. cert->destroy(cert);
  157. }
  158. if (!public)
  159. {
  160. fprintf(stderr, "extracting public key failed\n");
  161. return 1;
  162. }
  163. if (!public->get_encoding(public, form, &encoding))
  164. {
  165. fprintf(stderr, "public key encoding failed\n");
  166. public->destroy(public);
  167. return 1;
  168. }
  169. public->destroy(public);
  170. set_file_mode(stdout, form);
  171. if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
  172. {
  173. fprintf(stderr, "writing public key failed\n");
  174. free(encoding.ptr);
  175. return 1;
  176. }
  177. free(encoding.ptr);
  178. return 0;
  179. }
  180. /**
  181. * Register the command.
  182. */
  183. static void __attribute__ ((constructor))reg()
  184. {
  185. command_register((command_t) {
  186. pub, 'p', "pub",
  187. "extract the public key from a private key/certificate",
  188. {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv|pub|pkcs10|x509]",
  189. "[--outform der|pem|dnskey|sshkey]"},
  190. {
  191. {"help", 'h', 0, "show usage information"},
  192. {"in", 'i', 1, "input file, default: stdin"},
  193. {"keyid", 'x', 1, "smartcard or TPM private key object handle"},
  194. {"type", 't', 1, "type of credential, default: priv"},
  195. {"outform", 'f', 1, "encoding of extracted public key, default: der"},
  196. }
  197. });
  198. }