pki: Edited keyid parameter use in various pki man pages and usage outputs
[strongswan.git] / src / pki / commands / req.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2009-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 <time.h>
18 #include <errno.h>
19
20 #include "pki.h"
21
22 #include <collections/linked_list.h>
23 #include <credentials/certificates/certificate.h>
24
25 /**
26 * Create a self-signed PKCS#10 certificate requesst.
27 */
28 static int req()
29 {
30 cred_encoding_type_t form = CERT_ASN1_DER;
31 key_type_t type = KEY_ANY;
32 hash_algorithm_t digest = HASH_UNKNOWN;
33 certificate_t *cert = NULL;
34 private_key_t *private = NULL;
35 char *file = NULL, *keyid = NULL, *dn = NULL, *error = NULL;
36 identification_t *id = NULL;
37 linked_list_t *san;
38 chunk_t encoding = chunk_empty;
39 chunk_t challenge_password = chunk_empty;
40 char *arg;
41
42 san = linked_list_create();
43
44 while (TRUE)
45 {
46 switch (command_getopt(&arg))
47 {
48 case 'h':
49 goto usage;
50 case 't':
51 if (streq(arg, "rsa"))
52 {
53 type = KEY_RSA;
54 }
55 else if (streq(arg, "ecdsa"))
56 {
57 type = KEY_ECDSA;
58 }
59 else if (streq(arg, "bliss"))
60 {
61 type = KEY_BLISS;
62 }
63 else if (streq(arg, "priv"))
64 {
65 type = KEY_ANY;
66 }
67 else
68 {
69 error = "invalid input type";
70 goto usage;
71 }
72 continue;
73 case 'g':
74 if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
75 {
76 error = "invalid --digest type";
77 goto usage;
78 }
79 continue;
80 case 'i':
81 file = arg;
82 continue;
83 case 'd':
84 dn = arg;
85 continue;
86 case 'a':
87 san->insert_last(san, identification_create_from_string(arg));
88 continue;
89 case 'p':
90 challenge_password = chunk_create(arg, strlen(arg));
91 continue;
92 case 'f':
93 if (!get_form(arg, &form, CRED_CERTIFICATE))
94 {
95 error = "invalid output format";
96 goto usage;
97 }
98 continue;
99 case 'x':
100 keyid = arg;
101 continue;
102 case EOF:
103 break;
104 default:
105 error = "invalid --req option";
106 goto usage;
107 }
108 break;
109 }
110
111 if (!dn)
112 {
113 error = "--dn is required";
114 goto usage;
115 }
116 id = identification_create_from_string(dn);
117 if (id->get_type(id) != ID_DER_ASN1_DN)
118 {
119 error = "supplied --dn is not a distinguished name";
120 goto end;
121 }
122 if (file)
123 {
124 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
125 BUILD_FROM_FILE, file, BUILD_END);
126 }
127 else if (keyid)
128 {
129 chunk_t chunk;
130
131 chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
132 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
133 BUILD_PKCS11_KEYID, chunk, BUILD_END);
134 free(chunk.ptr);
135 }
136 else
137 {
138 chunk_t chunk;
139
140 set_file_mode(stdin, CERT_ASN1_DER);
141 if (!chunk_from_fd(0, &chunk))
142 {
143 fprintf(stderr, "reading private key failed: %s\n", strerror(errno));
144 error = "";
145 goto end;
146 }
147 private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
148 BUILD_BLOB, chunk, BUILD_END);
149 free(chunk.ptr);
150 }
151 if (!private)
152 {
153 error = "parsing private key failed";
154 goto end;
155 }
156 if (digest == HASH_UNKNOWN)
157 {
158 digest = get_default_digest(private);
159 }
160 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PKCS10_REQUEST,
161 BUILD_SIGNING_KEY, private,
162 BUILD_SUBJECT, id,
163 BUILD_SUBJECT_ALTNAMES, san,
164 BUILD_CHALLENGE_PWD, challenge_password,
165 BUILD_DIGEST_ALG, digest,
166 BUILD_END);
167 if (!cert)
168 {
169 error = "generating certificate request failed";
170 goto end;
171 }
172 if (!cert->get_encoding(cert, form, &encoding))
173 {
174 error = "encoding certificate request failed";
175 goto end;
176 }
177 set_file_mode(stdout, form);
178 if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
179 {
180 error = "writing certificate request failed";
181 goto end;
182 }
183
184 end:
185 DESTROY_IF(id);
186 DESTROY_IF(cert);
187 DESTROY_IF(private);
188 san->destroy_offset(san, offsetof(identification_t, destroy));
189 free(encoding.ptr);
190
191 if (error)
192 {
193 fprintf(stderr, "%s\n", error);
194 return 1;
195 }
196 return 0;
197
198 usage:
199 san->destroy_offset(san, offsetof(identification_t, destroy));
200 return command_usage(error);
201 }
202
203 /**
204 * Register the command.
205 */
206 static void __attribute__ ((constructor))reg()
207 {
208 command_register((command_t) {
209 req, 'r', "req",
210 "create a PKCS#10 certificate request",
211 {" [--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv] --dn distinguished-name",
212 "[--san subjectAltName]+ [--password challengePassword]",
213 "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]",
214 "[--outform der|pem]"},
215 {
216 {"help", 'h', 0, "show usage information"},
217 {"in", 'i', 1, "private key input file, default: stdin"},
218 {"keyid", 'x', 1, "smartcard or TPM private key object handle"},
219 {"type", 't', 1, "type of input key, default: priv"},
220 {"dn", 'd', 1, "subject distinguished name"},
221 {"san", 'a', 1, "subjectAltName to include in cert request"},
222 {"password",'p', 1, "challengePassword to include in cert request"},
223 {"digest", 'g', 1, "digest for signature creation, default: key-specific"},
224 {"outform", 'f', 1, "encoding of generated request, default: der"},
225 }
226 });
227 }