]>
Commit | Line | Data |
---|---|---|
6be68cc1 MW |
1 | /* |
2 | * Copyright (C) 2009 Martin Willi | |
ab94f76d | 3 | * Copyright (C) 2017 Andreas Steffen |
19ef2aec TB |
4 | * |
5 | * Copyright (C) secunet Security Networks AG | |
6be68cc1 MW |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | * for more details. | |
16 | */ | |
17 | ||
1c4a3459 MW |
18 | #include <errno.h> |
19 | ||
6be68cc1 MW |
20 | #include "pki.h" |
21 | ||
22 | #include <credentials/certificates/certificate.h> | |
23 | #include <credentials/certificates/x509.h> | |
24 | ||
0c924641 TB |
25 | typedef enum { |
26 | FORMAT_PRETTY, | |
27 | FORMAT_HEX, | |
28 | FORMAT_BASE64, | |
29 | FORMAT_BINARY, | |
30 | } format_t; | |
31 | ||
32 | /** | |
33 | * Print a single keyid in the requested format | |
34 | */ | |
35 | static bool print_id(chunk_t id, format_t format, char *desc) | |
36 | { | |
37 | chunk_t chunk; | |
38 | ||
39 | switch (format) | |
40 | { | |
41 | case FORMAT_PRETTY: | |
42 | printf("%s:\n %#B\n", desc, &id); | |
43 | break; | |
44 | case FORMAT_HEX: | |
45 | chunk = chunk_to_hex(id, NULL, FALSE); | |
46 | printf("%.*s\n", (int)chunk.len, chunk.ptr); | |
47 | chunk_free(&chunk); | |
48 | break; | |
49 | case FORMAT_BASE64: | |
50 | chunk = chunk_to_base64(id, NULL); | |
51 | printf("%.*s\n", (int)chunk.len, chunk.ptr); | |
52 | chunk_free(&chunk); | |
53 | break; | |
54 | case FORMAT_BINARY: | |
55 | if (fwrite(id.ptr, id.len, 1, stdout) != 1) | |
56 | { | |
57 | fprintf(stderr, "writing %s failed\n", desc); | |
58 | return FALSE; | |
59 | } | |
60 | break; | |
61 | } | |
62 | return TRUE; | |
63 | } | |
64 | ||
6be68cc1 MW |
65 | /** |
66 | * Calculate the keyid of a key/certificate | |
67 | */ | |
ae7452e8 | 68 | static int keyid() |
6be68cc1 MW |
69 | { |
70 | credential_type_t type = CRED_PRIVATE_KEY; | |
05ccde0a | 71 | int subtype = KEY_ANY; |
6be68cc1 MW |
72 | certificate_t *cert; |
73 | private_key_t *private; | |
74 | public_key_t *public; | |
0c924641 TB |
75 | format_t format = FORMAT_PRETTY; |
76 | enum { | |
77 | ID_TYPE_ALL, | |
78 | ID_TYPE_SPK, | |
79 | ID_TYPE_SPKI, | |
2403154f | 80 | } id_type = ID_TYPE_ALL; |
ab94f76d | 81 | char *file = NULL, *keyid = NULL; |
6be68cc1 | 82 | void *cred; |
0c924641 | 83 | chunk_t id, spk = chunk_empty, spki = chunk_empty; |
ae7452e8 | 84 | char *arg; |
6be68cc1 MW |
85 | |
86 | while (TRUE) | |
87 | { | |
ae7452e8 | 88 | switch (command_getopt(&arg)) |
6be68cc1 MW |
89 | { |
90 | case 'h': | |
3ce9438b | 91 | return command_usage(NULL); |
6be68cc1 | 92 | case 't': |
1798e490 TB |
93 | if (streq(arg, "rsa") || |
94 | streq(arg, "rsa-priv")) | |
6be68cc1 MW |
95 | { |
96 | type = CRED_PRIVATE_KEY; | |
97 | subtype = KEY_RSA; | |
98 | } | |
1798e490 TB |
99 | else if (streq(arg, "ecdsa") || |
100 | streq(arg, "ecdsa-priv")) | |
6be68cc1 MW |
101 | { |
102 | type = CRED_PRIVATE_KEY; | |
103 | subtype = KEY_ECDSA; | |
104 | } | |
1798e490 TB |
105 | else if (streq(arg, "bliss") || |
106 | streq(arg, "bliss-priv")) | |
b6bb32e6 AS |
107 | { |
108 | type = CRED_PRIVATE_KEY; | |
109 | subtype = KEY_BLISS; | |
110 | } | |
05ccde0a TB |
111 | else if (streq(arg, "priv")) |
112 | { | |
113 | type = CRED_PRIVATE_KEY; | |
114 | subtype = KEY_ANY; | |
115 | } | |
ae7452e8 | 116 | else if (streq(arg, "pub")) |
6be68cc1 MW |
117 | { |
118 | type = CRED_PUBLIC_KEY; | |
119 | subtype = KEY_ANY; | |
120 | } | |
ae7452e8 | 121 | else if (streq(arg, "pkcs10")) |
622e558c AS |
122 | { |
123 | type = CRED_CERTIFICATE; | |
124 | subtype = CERT_PKCS10_REQUEST; | |
125 | } | |
ae7452e8 | 126 | else if (streq(arg, "x509")) |
6be68cc1 MW |
127 | { |
128 | type = CRED_CERTIFICATE; | |
129 | subtype = CERT_X509; | |
130 | } | |
131 | else | |
132 | { | |
3ce9438b | 133 | return command_usage( "invalid input type"); |
6be68cc1 MW |
134 | } |
135 | continue; | |
0c924641 TB |
136 | case 'I': |
137 | if (streq(arg, "spk")) | |
138 | { | |
139 | id_type = ID_TYPE_SPK; | |
140 | } | |
141 | else if (streq(arg, "spki")) | |
142 | { | |
143 | id_type = ID_TYPE_SPKI; | |
144 | } | |
145 | else if (!streq(arg, "all")) | |
146 | { | |
147 | return command_usage( "invalid id type"); | |
148 | } | |
149 | continue; | |
150 | case 'f': | |
151 | if (streq(arg, "hex")) | |
152 | { | |
153 | format = FORMAT_HEX; | |
154 | } | |
155 | else if (streq(arg, "base64")) | |
156 | { | |
157 | format = FORMAT_BASE64; | |
158 | } | |
159 | else if (streq(arg, "bin")) | |
160 | { | |
161 | format = FORMAT_BINARY; | |
162 | } | |
163 | else if (!streq(arg, "pretty")) | |
164 | { | |
165 | return command_usage( "invalid output format"); | |
166 | } | |
167 | continue; | |
6be68cc1 | 168 | case 'i': |
ae7452e8 | 169 | file = arg; |
6be68cc1 | 170 | continue; |
ab94f76d AS |
171 | case 'x': |
172 | keyid = arg; | |
173 | continue; | |
6be68cc1 MW |
174 | case EOF: |
175 | break; | |
176 | default: | |
3ce9438b | 177 | return command_usage("invalid --keyid option"); |
6be68cc1 MW |
178 | } |
179 | break; | |
180 | } | |
181 | if (file) | |
182 | { | |
183 | cred = lib->creds->create(lib->creds, type, subtype, | |
184 | BUILD_FROM_FILE, file, BUILD_END); | |
185 | } | |
ab94f76d AS |
186 | else if (keyid) |
187 | { | |
188 | chunk_t chunk; | |
189 | ||
190 | chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); | |
191 | cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, | |
192 | BUILD_PKCS11_KEYID, chunk, BUILD_END); | |
193 | free(chunk.ptr); | |
194 | } | |
6be68cc1 MW |
195 | else |
196 | { | |
71c9565a TB |
197 | chunk_t chunk; |
198 | ||
13298719 | 199 | set_file_mode(stdin, CERT_ASN1_DER); |
1c4a3459 MW |
200 | if (!chunk_from_fd(0, &chunk)) |
201 | { | |
202 | fprintf(stderr, "reading input failed: %s\n", strerror(errno)); | |
203 | return 1; | |
204 | } | |
6be68cc1 | 205 | cred = lib->creds->create(lib->creds, type, subtype, |
71c9565a TB |
206 | BUILD_BLOB, chunk, BUILD_END); |
207 | free(chunk.ptr); | |
6be68cc1 MW |
208 | } |
209 | if (!cred) | |
210 | { | |
211 | fprintf(stderr, "parsing input failed\n"); | |
212 | return 1; | |
213 | } | |
214 | ||
215 | if (type == CRED_PRIVATE_KEY) | |
216 | { | |
217 | private = cred; | |
da9724e6 | 218 | if (private->get_fingerprint(private, KEYID_PUBKEY_SHA1, &id)) |
6be68cc1 | 219 | { |
0c924641 | 220 | spk = chunk_clone(id); |
6be68cc1 | 221 | } |
da9724e6 | 222 | if (private->get_fingerprint(private, KEYID_PUBKEY_INFO_SHA1, &id)) |
6be68cc1 | 223 | { |
0c924641 | 224 | spki = chunk_clone(id); |
6be68cc1 MW |
225 | } |
226 | private->destroy(private); | |
227 | } | |
228 | else if (type == CRED_PUBLIC_KEY) | |
229 | { | |
230 | public = cred; | |
da9724e6 | 231 | if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &id)) |
6be68cc1 | 232 | { |
0c924641 | 233 | spk = chunk_clone(id); |
6be68cc1 | 234 | } |
da9724e6 | 235 | if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &id)) |
6be68cc1 | 236 | { |
0c924641 | 237 | spki = chunk_clone(id); |
6be68cc1 MW |
238 | } |
239 | public->destroy(public); | |
240 | } | |
241 | else | |
242 | { | |
243 | cert = cred; | |
244 | public = cert->get_public_key(cert); | |
245 | if (!public) | |
246 | { | |
247 | fprintf(stderr, "extracting public key from certificate failed"); | |
248 | return 1; | |
249 | } | |
da9724e6 | 250 | if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &id)) |
6be68cc1 | 251 | { |
0c924641 | 252 | spk = chunk_clone(id); |
6be68cc1 | 253 | } |
da9724e6 | 254 | if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &id)) |
6be68cc1 | 255 | { |
0c924641 | 256 | spki = chunk_clone(id); |
6be68cc1 MW |
257 | } |
258 | public->destroy(public); | |
259 | cert->destroy(cert); | |
260 | } | |
0c924641 TB |
261 | |
262 | if (id_type == ID_TYPE_ALL || id_type == ID_TYPE_SPK) | |
263 | { | |
264 | if (!spk.len || | |
265 | !print_id(spk, format, "subjkey (SHA-1 of subjectPublicKey)")) | |
266 | { | |
267 | return 1; | |
268 | } | |
269 | } | |
270 | if (id_type == ID_TYPE_ALL || id_type == ID_TYPE_SPKI) | |
271 | { | |
272 | if (!spki.len || | |
273 | !print_id(spki, format, "keyid (SHA-1 of subjectPublicKeyInfo)")) | |
274 | { | |
275 | return 1; | |
276 | } | |
277 | } | |
278 | chunk_free(&spk); | |
279 | chunk_free(&spki); | |
6be68cc1 MW |
280 | return 0; |
281 | } | |
282 | ||
283 | /** | |
284 | * Register the command. | |
285 | */ | |
286 | static void __attribute__ ((constructor))reg() | |
287 | { | |
3ce9438b | 288 | command_register((command_t) |
6be68cc1 MW |
289 | { keyid, 'k', "keyid", |
290 | "calculate key identifiers of a key/certificate", | |
0c924641 TB |
291 | {"[--in file|--keyid hex] [--type priv|rsa|ecdsa|bliss|pub|pkcs10|x509]", |
292 | "[--id all|spk|spki] [--format pretty|hex|base64|bin]"}, | |
6be68cc1 MW |
293 | { |
294 | {"help", 'h', 0, "show usage information"}, | |
295 | {"in", 'i', 1, "input file, default: stdin"}, | |
ab94f76d | 296 | {"keyid", 'x', 1, "smartcard or TPM private key object handle"}, |
05ccde0a | 297 | {"type", 't', 1, "type of key, default: priv"}, |
0c924641 TB |
298 | {"id", 'I', 1, "type of identifier, default: all"}, |
299 | {"format", 'f', 1, "output format, default: pretty"}, | |
6be68cc1 MW |
300 | } |
301 | }); | |
302 | } |