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:
17: #include <errno.h>
18:
19: #include "pki.h"
20:
21: #include <credentials/certificates/certificate.h>
22: #include <credentials/certificates/x509.h>
23:
24: /**
25: * Extract a public key from a private key/certificate
26: */
27: static int pub()
28: {
29: cred_encoding_type_t form = PUBKEY_SPKI_ASN1_DER;
30: credential_type_t type = CRED_PRIVATE_KEY;
31: int subtype = KEY_ANY;
32: certificate_t *cert;
33: private_key_t *private;
34: public_key_t *public;
35: chunk_t encoding;
36: char *file = NULL, *keyid = NULL;
37: void *cred;
38: char *arg;
39:
40: while (TRUE)
41: {
42: switch (command_getopt(&arg))
43: {
44: case 'h':
45: return command_usage(NULL);
46: case 't':
47: if (streq(arg, "rsa"))
48: {
49: type = CRED_PRIVATE_KEY;
50: subtype = KEY_RSA;
51: }
52: else if (streq(arg, "ecdsa"))
53: {
54: type = CRED_PRIVATE_KEY;
55: subtype = KEY_ECDSA;
56: }
57: else if (streq(arg, "bliss"))
58: {
59: type = CRED_PRIVATE_KEY;
60: subtype = KEY_BLISS;
61: }
62: else if (streq(arg, "priv"))
63: {
64: type = CRED_PRIVATE_KEY;
65: subtype = KEY_ANY;
66: }
67: else if (streq(arg, "pub"))
68: {
69: type = CRED_PUBLIC_KEY;
70: subtype = KEY_ANY;
71: }
72: else if (streq(arg, "pkcs10"))
73: {
74: type = CRED_CERTIFICATE;
75: subtype = CERT_PKCS10_REQUEST;
76: }
77: else if (streq(arg, "x509"))
78: {
79: type = CRED_CERTIFICATE;
80: subtype = CERT_X509;
81: }
82: else
83: {
84: return command_usage("invalid input type");
85: }
86: continue;
87: case 'f':
88: if (!get_form(arg, &form, CRED_PUBLIC_KEY))
89: {
90: return command_usage("invalid output format");
91: }
92: continue;
93: case 'i':
94: file = arg;
95: continue;
96: case 'x':
97: keyid = arg;
98: continue;
99: case EOF:
100: break;
101: default:
102: return command_usage("invalid --pub option");
103: }
104: break;
105: }
106: if (file)
107: {
108: cred = lib->creds->create(lib->creds, type, subtype,
109: BUILD_FROM_FILE, file, BUILD_END);
110: }
111: else if (keyid)
112: {
113: chunk_t chunk;
114:
115: chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
116: cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
117: BUILD_PKCS11_KEYID, chunk, BUILD_END);
118: free(chunk.ptr);
119: }
120: else
121: {
122: chunk_t chunk;
123:
124: set_file_mode(stdin, CERT_ASN1_DER);
125: if (!chunk_from_fd(0, &chunk))
126: {
127: fprintf(stderr, "reading input failed: %s\n", strerror(errno));
128: return 1;
129: }
130: cred = lib->creds->create(lib->creds, type, subtype,
131: BUILD_BLOB, chunk, BUILD_END);
132: free(chunk.ptr);
133: }
134:
135: if (type == CRED_PRIVATE_KEY)
136: {
137: private = cred;
138: if (!private)
139: {
140: fprintf(stderr, "parsing private key failed\n");
141: return 1;
142: }
143: public = private->get_public_key(private);
144: private->destroy(private);
145: }
146: else if (type == CRED_PUBLIC_KEY)
147: {
148: public = cred;
149: if (!public)
150: {
151: fprintf(stderr, "parsing public key failed\n");
152: return 1;
153: }
154: }
155: else
156: {
157: cert = cred;
158: if (!cert)
159: {
160: fprintf(stderr, "parsing certificate failed\n");
161: return 1;
162: }
163: public = cert->get_public_key(cert);
164: cert->destroy(cert);
165: }
166: if (!public)
167: {
168: fprintf(stderr, "extracting public key failed\n");
169: return 1;
170: }
171: if (!public->get_encoding(public, form, &encoding))
172: {
173: fprintf(stderr, "public key encoding failed\n");
174: public->destroy(public);
175: return 1;
176: }
177: public->destroy(public);
178: set_file_mode(stdout, form);
179: if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
180: {
181: fprintf(stderr, "writing public key failed\n");
182: free(encoding.ptr);
183: return 1;
184: }
185: free(encoding.ptr);
186: return 0;
187: }
188:
189: /**
190: * Register the command.
191: */
192: static void __attribute__ ((constructor))reg()
193: {
194: command_register((command_t) {
195: pub, 'p', "pub",
196: "extract the public key from a private key/certificate",
197: {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv|pub|pkcs10|x509]",
198: "[--outform der|pem|dnskey|sshkey]"},
199: {
200: {"help", 'h', 0, "show usage information"},
201: {"in", 'i', 1, "input file, default: stdin"},
202: {"keyid", 'x', 1, "smartcard or TPM private key object handle"},
203: {"type", 't', 1, "type of credential, default: priv"},
204: {"outform", 'f', 1, "encoding of extracted public key, default: der"},
205: }
206: });
207: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>