2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2009-2017 Andreas Steffen
5 * Copyright (C) secunet Security Networks AG
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>.
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
23 #include <collections/linked_list.h>
24 #include <credentials/certificates/certificate.h>
27 * Create a self-signed PKCS#10 certificate request.
31 cred_encoding_type_t form
= CERT_ASN1_DER
;
32 key_type_t type
= KEY_ANY
;
33 hash_algorithm_t digest
= HASH_UNKNOWN
;
34 signature_params_t
*scheme
= NULL
;
35 certificate_t
*cert
= NULL
;
36 private_key_t
*private = NULL
;
37 char *file
= NULL
, *keyid
= NULL
, *dn
= NULL
, *error
= NULL
;
38 identification_t
*id
= NULL
;
40 chunk_t encoding
= chunk_empty
;
41 chunk_t challenge_password
= chunk_empty
;
43 bool pss
= lib
->settings
->get_bool(lib
->settings
, "%s.rsa_pss", FALSE
,
46 san
= linked_list_create();
50 switch (command_getopt(&arg
))
55 if (streq(arg
, "rsa"))
59 else if (streq(arg
, "ecdsa"))
63 else if (streq(arg
, "bliss"))
67 else if (streq(arg
, "priv"))
73 error
= "invalid input type";
78 if (!enum_from_name(hash_algorithm_short_names
, arg
, &digest
))
80 error
= "invalid --digest type";
85 if (streq(arg
, "pss"))
89 else if (!streq(arg
, "pkcs1"))
91 error
= "invalid RSA padding";
102 san
->insert_last(san
, identification_create_from_string(arg
));
105 challenge_password
= chunk_create(arg
, strlen(arg
));
108 if (!get_form(arg
, &form
, CRED_CERTIFICATE
))
110 error
= "invalid output format";
120 error
= "invalid --req option";
128 error
= "--dn is required";
131 id
= identification_create_from_string(dn
);
132 if (id
->get_type(id
) != ID_DER_ASN1_DN
)
134 error
= "supplied --dn is not a distinguished name";
139 private = lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, type
,
140 BUILD_FROM_FILE
, file
, BUILD_END
);
146 chunk
= chunk_from_hex(chunk_create(keyid
, strlen(keyid
)), NULL
);
147 private = lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, KEY_ANY
,
148 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
155 set_file_mode(stdin
, CERT_ASN1_DER
);
156 if (!chunk_from_fd(0, &chunk
))
158 fprintf(stderr
, "reading private key failed: %s\n", strerror(errno
));
162 private = lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, type
,
163 BUILD_BLOB
, chunk
, BUILD_END
);
168 error
= "parsing private key failed";
171 scheme
= get_signature_scheme(private, digest
, pss
);
174 error
= "no signature scheme found";
178 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_PKCS10_REQUEST
,
179 BUILD_SIGNING_KEY
, private,
181 BUILD_SUBJECT_ALTNAMES
, san
,
182 BUILD_CHALLENGE_PWD
, challenge_password
,
183 BUILD_SIGNATURE_SCHEME
, scheme
,
187 error
= "generating certificate request failed";
190 if (!cert
->get_encoding(cert
, form
, &encoding
))
192 error
= "encoding certificate request failed";
195 set_file_mode(stdout
, form
);
196 if (fwrite(encoding
.ptr
, encoding
.len
, 1, stdout
) != 1)
198 error
= "writing certificate request failed";
206 san
->destroy_offset(san
, offsetof(identification_t
, destroy
));
207 signature_params_destroy(scheme
);
212 fprintf(stderr
, "%s\n", error
);
218 san
->destroy_offset(san
, offsetof(identification_t
, destroy
));
219 return command_usage(error
);
223 * Register the command.
225 static void __attribute__ ((constructor
))reg()
227 command_register((command_t
) {
229 "create a PKCS#10 certificate request",
230 {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv] --dn distinguished-name",
231 "[--san subjectAltName]+ [--password challengePassword]",
232 "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]",
233 "[--rsa-padding pkcs1|pss]",
234 "[--outform der|pem]"},
236 {"help", 'h', 0, "show usage information"},
237 {"in", 'i', 1, "private key input file, default: stdin"},
238 {"keyid", 'x', 1, "smartcard or TPM private key object handle"},
239 {"type", 't', 1, "type of input key, default: priv"},
240 {"dn", 'd', 1, "subject distinguished name"},
241 {"san", 'a', 1, "subjectAltName to include in cert request"},
242 {"password", 'p', 1, "challengePassword to include in cert request"},
243 {"digest", 'g', 1, "digest for signature creation, default: key-specific"},
244 {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"},
245 {"outform", 'f', 1, "encoding of generated request, default: der"},