1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <malloc.h>
28 #include <libgen.h>
29 #include <errno.h>
30 #include <cryptoutil.h>
31 #include <security/cryptoki.h>
32 #include "common.h"
33
34 #include <kmfapi.h>
35
36 #define SET_VALUE(f, s) \
37 kmfrv = f; \
38 if (kmfrv != KMF_OK) { \
39 cryptoerror(LOG_STDERR, \
40 gettext("Failed to %s: 0x%02\n"), \
41 s, kmfrv); \
42 goto cleanup; \
43 }
44
45 static KMF_RETURN
gencsr_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * certlabel,KMF_KEY_ALG keyAlg,int keylen,uint16_t kubits,int kucrit,KMF_ENCODE_FORMAT fmt,char * csrfile,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg,KMF_OID * curveoid)46 gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
47 char *token, char *subject, char *altname,
48 KMF_GENERALNAMECHOICES alttype, int altcrit,
49 char *certlabel, KMF_KEY_ALG keyAlg,
50 int keylen, uint16_t kubits, int kucrit,
51 KMF_ENCODE_FORMAT fmt, char *csrfile,
52 KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
53 KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
54 {
55 KMF_RETURN kmfrv = KMF_OK;
56 KMF_KEY_HANDLE pubk, prik;
57 KMF_X509_NAME csrSubject;
58 KMF_CSR_DATA csr;
59 KMF_DATA signedCsr = { 0, NULL };
60
61 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
62 int numattr = 0;
63 KMF_ATTRIBUTE attrlist[16];
64
65 (void) memset(&csr, 0, sizeof (csr));
66 (void) memset(&csrSubject, 0, sizeof (csrSubject));
67
68 /* If the subject name cannot be parsed, flag it now and exit */
69 if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK)
70 return (kmfrv);
71
72 /* Select a PKCS11 token */
73 kmfrv = select_token(kmfhandle, token, FALSE);
74 if (kmfrv != KMF_OK)
75 return (kmfrv);
76 /*
77 * Share the "genkeypair" routine for creating the keypair.
78 */
79 kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
80 keyAlg, keylen, tokencred, curveoid, &prik, &pubk);
81 if (kmfrv != KMF_OK)
82 return (kmfrv);
83
84 SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
85
86 SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
87
88 SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
89
90 SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
91 "SignatureAlgorithm");
92
93 if (altname != NULL) {
94 SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
95 alttype), "SetCSRSubjectAltName");
96 }
97
98 if (kubits != 0) {
99 SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
100 "SetCSRKeyUsage");
101 }
102 if (ekulist != NULL) {
103 int i;
104 for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
105 SET_VALUE(kmf_add_csr_eku(&csr,
106 &ekulist->ekulist[i],
107 ekulist->critlist[i]),
108 "Extended Key Usage");
109 }
110 }
111 if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
112 KMF_OK) {
113 kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
114 }
115
116 cleanup:
117 (void) kmf_free_data(&signedCsr);
118 (void) kmf_free_signed_csr(&csr);
119
120 /* delete the public key */
121 numattr = 0;
122 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
123 &kstype, sizeof (kstype));
124 numattr++;
125
126 kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
127 &pubk, sizeof (KMF_KEY_HANDLE));
128 numattr++;
129
130 if (tokencred != NULL && tokencred->cred != NULL) {
131 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
132 tokencred, sizeof (KMF_CREDENTIAL));
133 numattr++;
134 }
135
136 (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
137
138 /*
139 * If there is an error, then we need to remove the private key
140 * from the token.
141 */
142 if (kmfrv != KMF_OK) {
143 numattr = 0;
144 kmf_set_attr_at_index(attrlist, numattr,
145 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
146 numattr++;
147
148 kmf_set_attr_at_index(attrlist, numattr,
149 KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
150 numattr++;
151
152 if (tokencred != NULL && tokencred->cred != NULL) {
153 kmf_set_attr_at_index(attrlist, numattr,
154 KMF_CREDENTIAL_ATTR, tokencred,
155 sizeof (KMF_CREDENTIAL));
156 numattr++;
157 }
158
159 (void) kmf_delete_key_from_keystore(kmfhandle, numattr,
160 attrlist);
161 }
162
163 (void) kmf_free_kmf_key(kmfhandle, &prik);
164 return (kmfrv);
165 }
166
167 static KMF_RETURN
gencsr_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,int keylen,KMF_ENCODE_FORMAT fmt,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,uint16_t kubits,int kucrit,char * outcsr,char * outkey,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg)168 gencsr_file(KMF_HANDLE_T kmfhandle,
169 KMF_KEY_ALG keyAlg,
170 int keylen, KMF_ENCODE_FORMAT fmt,
171 char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
172 int altcrit, uint16_t kubits, int kucrit,
173 char *outcsr, char *outkey, EKU_LIST *ekulist,
174 KMF_ALGORITHM_INDEX sigAlg)
175 {
176 KMF_RETURN kmfrv;
177 KMF_KEY_HANDLE pubk, prik;
178 KMF_X509_NAME csrSubject;
179 KMF_CSR_DATA csr;
180 KMF_DATA signedCsr = { 0, NULL };
181 char *fullcsrpath = NULL;
182 char *fullkeypath = NULL;
183
184
185 (void) memset(&csr, 0, sizeof (csr));
186 (void) memset(&csrSubject, 0, sizeof (csrSubject));
187
188 if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
189 cryptoerror(LOG_STDERR,
190 gettext("No output file was specified for "
191 "the csr or key\n"));
192 return (KMF_ERR_BAD_PARAMETER);
193 }
194 fullcsrpath = strdup(outcsr);
195 if (verify_file(fullcsrpath)) {
196 cryptoerror(LOG_STDERR,
197 gettext("Cannot write the indicated output "
198 "certificate file (%s).\n"), fullcsrpath);
199 free(fullcsrpath);
200 return (PK_ERR_USAGE);
201 }
202
203 /* If the subject name cannot be parsed, flag it now and exit */
204 if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
205 return (kmfrv);
206 }
207 /*
208 * Share the "genkeypair" routine for creating the keypair.
209 */
210 kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
211 fmt, outkey, &prik, &pubk);
212 if (kmfrv != KMF_OK)
213 return (kmfrv);
214
215 SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
216 "SetCSRPubKey");
217
218 SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
219
220 SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
221 "kmf_set_csr_subject");
222
223 SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
224
225 if (altname != NULL) {
226 SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
227 alttype), "kmf_set_csr_subject_altname");
228 }
229 if (kubits != NULL) {
230 SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
231 "kmf_set_csr_ku");
232 }
233 if (ekulist != NULL) {
234 int i;
235 for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
236 SET_VALUE(kmf_add_csr_eku(&csr,
237 &ekulist->ekulist[i],
238 ekulist->critlist[i]),
239 "Extended Key Usage");
240 }
241 }
242 if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
243 KMF_OK) {
244 kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
245 }
246
247 cleanup:
248 if (fullkeypath)
249 free(fullkeypath);
250 if (fullcsrpath)
251 free(fullcsrpath);
252
253 kmf_free_data(&signedCsr);
254 kmf_free_kmf_key(kmfhandle, &prik);
255 kmf_free_signed_csr(&csr);
256
257 return (kmfrv);
258 }
259
260 static KMF_RETURN
gencsr_nss(KMF_HANDLE_T kmfhandle,char * token,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,char * nickname,char * dir,char * prefix,KMF_KEY_ALG keyAlg,int keylen,uint16_t kubits,int kucrit,KMF_ENCODE_FORMAT fmt,char * csrfile,KMF_CREDENTIAL * tokencred,EKU_LIST * ekulist,KMF_ALGORITHM_INDEX sigAlg,KMF_OID * curveoid)261 gencsr_nss(KMF_HANDLE_T kmfhandle,
262 char *token, char *subject, char *altname,
263 KMF_GENERALNAMECHOICES alttype, int altcrit,
264 char *nickname, char *dir, char *prefix,
265 KMF_KEY_ALG keyAlg, int keylen,
266 uint16_t kubits, int kucrit,
267 KMF_ENCODE_FORMAT fmt, char *csrfile,
268 KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
269 KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
270 {
271 KMF_RETURN kmfrv;
272 KMF_KEY_HANDLE pubk, prik;
273 KMF_X509_NAME csrSubject;
274 KMF_CSR_DATA csr;
275 KMF_DATA signedCsr = { 0, NULL };
276
277 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
278 int numattr = 0;
279 KMF_ATTRIBUTE attrlist[16];
280
281 if (token == NULL)
282 token = DEFAULT_NSS_TOKEN;
283
284 kmfrv = configure_nss(kmfhandle, dir, prefix);
285 if (kmfrv != KMF_OK)
286 return (kmfrv);
287
288 (void) memset(&csr, 0, sizeof (csr));
289 (void) memset(&csrSubject, 0, sizeof (csrSubject));
290 (void) memset(&pubk, 0, sizeof (pubk));
291 (void) memset(&prik, 0, sizeof (prik));
292
293 /* If the subject name cannot be parsed, flag it now and exit */
294 if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
295 return (kmfrv);
296 }
297
298 kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
299 prefix, keyAlg, keylen, tokencred, curveoid,
300 &prik, &pubk);
301 if (kmfrv != KMF_OK)
302 return (kmfrv);
303
304 SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
305 "kmf_set_csr_pubkey");
306 SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
307 SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
308 "kmf_set_csr_subject");
309 SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
310
311 if (altname != NULL) {
312 SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
313 alttype), "kmf_set_csr_subject_altname");
314 }
315 if (kubits != NULL) {
316 SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
317 "kmf_set_csr_ku");
318 }
319 if (ekulist != NULL) {
320 int i;
321 for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
322 SET_VALUE(kmf_add_csr_eku(&csr,
323 &ekulist->ekulist[i],
324 ekulist->critlist[i]),
325 "Extended Key Usage");
326 }
327 }
328 if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
329 KMF_OK) {
330 kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
331 }
332
333 cleanup:
334 (void) kmf_free_data(&signedCsr);
335 (void) kmf_free_kmf_key(kmfhandle, &prik);
336
337 /* delete the key */
338 numattr = 0;
339 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
340 &kstype, sizeof (kstype));
341 numattr++;
342
343 kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
344 &pubk, sizeof (KMF_KEY_HANDLE));
345 numattr++;
346
347 if (tokencred != NULL && tokencred->credlen > 0) {
348 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
349 tokencred, sizeof (KMF_CREDENTIAL));
350 numattr++;
351 }
352
353 if (token && strlen(token)) {
354 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
355 token, strlen(token));
356 numattr++;
357 }
358
359 (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
360
361 (void) kmf_free_signed_csr(&csr);
362
363 return (kmfrv);
364 }
365
366 int
pk_gencsr(int argc,char * argv[])367 pk_gencsr(int argc, char *argv[])
368 {
369 KMF_RETURN rv;
370 int opt;
371 extern int optind_av;
372 extern char *optarg_av;
373 KMF_KEYSTORE_TYPE kstype = 0;
374 char *subject = NULL;
375 char *tokenname = NULL;
376 char *dir = NULL;
377 char *prefix = NULL;
378 int keylen = PK_DEFAULT_KEYLENGTH;
379 char *certlabel = NULL;
380 char *outcsr = NULL;
381 char *outkey = NULL;
382 char *format = NULL;
383 char *altname = NULL;
384 char *kustr = NULL;
385 char *ekustr = NULL;
386 char *hashname = NULL;
387 uint16_t kubits = 0;
388 char *keytype = PK_DEFAULT_KEYTYPE;
389 KMF_HANDLE_T kmfhandle = NULL;
390 KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
391 KMF_KEY_ALG keyAlg = KMF_RSA;
392 KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
393 boolean_t interactive = B_FALSE;
394 char *subname = NULL;
395 KMF_CREDENTIAL tokencred = { NULL, 0 };
396 KMF_GENERALNAMECHOICES alttype = 0;
397 int altcrit = 0, kucrit = 0;
398 EKU_LIST *ekulist = NULL;
399 KMF_OID *curveoid = NULL; /* ECC */
400 KMF_OID *hashoid = NULL;
401 int y_flag = 0;
402
403 while ((opt = getopt_av(argc, argv,
404 "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
405 "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
406 "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
407 "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {
408
409 switch (opt) {
410 case 'A':
411 altname = optarg_av;
412 break;
413 case 'i':
414 if (interactive)
415 return (PK_ERR_USAGE);
416 else if (subject) {
417 cryptoerror(LOG_STDERR,
418 gettext("Interactive (-i) and "
419 "subject options are mutually "
420 "exclusive.\n"));
421 return (PK_ERR_USAGE);
422 } else
423 interactive = B_TRUE;
424 break;
425 case 'k':
426 kstype = KS2Int(optarg_av);
427 if (kstype == 0)
428 return (PK_ERR_USAGE);
429 break;
430 case 's':
431 if (subject)
432 return (PK_ERR_USAGE);
433 else if (interactive) {
434 cryptoerror(LOG_STDERR,
435 gettext("Interactive (-i) and "
436 "subject options are mutually "
437 "exclusive.\n"));
438 return (PK_ERR_USAGE);
439 } else
440 subject = optarg_av;
441 break;
442 case 'l':
443 case 'n':
444 if (certlabel)
445 return (PK_ERR_USAGE);
446 certlabel = optarg_av;
447 break;
448 case 'T':
449 if (tokenname)
450 return (PK_ERR_USAGE);
451 tokenname = optarg_av;
452 break;
453 case 'd':
454 dir = optarg_av;
455 break;
456 case 'p':
457 if (prefix)
458 return (PK_ERR_USAGE);
459 prefix = optarg_av;
460 break;
461 case 't':
462 keytype = optarg_av;
463 break;
464 case 'u':
465 kustr = optarg_av;
466 break;
467 case 'y':
468 if (sscanf(optarg_av, "%d",
469 &keylen) != 1) {
470 cryptoerror(LOG_STDERR,
471 gettext("Unrecognized "
472 "key length (%s)\n"), optarg_av);
473 return (PK_ERR_USAGE);
474 }
475 y_flag++;
476 break;
477 case 'c':
478 if (outcsr)
479 return (PK_ERR_USAGE);
480 outcsr = optarg_av;
481 break;
482 case 'K':
483 if (outkey)
484 return (PK_ERR_USAGE);
485 outkey = optarg_av;
486 break;
487 case 'F':
488 if (format)
489 return (PK_ERR_USAGE);
490 format = optarg_av;
491 break;
492 case 'e':
493 ekustr = optarg_av;
494 break;
495 case 'C':
496 curveoid = ecc_name_to_oid(optarg_av);
497 if (curveoid == NULL) {
498 cryptoerror(LOG_STDERR,
499 gettext("Unrecognized ECC "
500 "curve.\n"));
501 return (PK_ERR_USAGE);
502 }
503 break;
504 case 'E':
505 /*
506 * This argument is only to be used
507 * by itself, no other options should
508 * be present.
509 */
510 if (argc != 2) {
511 cryptoerror(LOG_STDERR,
512 gettext("listcurves has no other "
513 "options.\n"));
514 return (PK_ERR_USAGE);
515 }
516 show_ecc_curves();
517 return (0);
518 case 'h':
519 hashname = optarg_av;
520 hashoid = ecc_name_to_oid(optarg_av);
521 if (hashoid == NULL) {
522 cryptoerror(LOG_STDERR,
523 gettext("Unrecognized hash.\n"));
524 return (PK_ERR_USAGE);
525 }
526 break;
527 default:
528 cryptoerror(LOG_STDERR, gettext(
529 "unrecognized gencsr option '%s'\n"),
530 argv[optind_av]);
531 return (PK_ERR_USAGE);
532 }
533 }
534 /* No additional args allowed. */
535 argc -= optind_av;
536 argv += optind_av;
537 if (argc) {
538 return (PK_ERR_USAGE);
539 }
540
541 /* Assume keystore = PKCS#11 if not specified. */
542 if (kstype == 0)
543 kstype = KMF_KEYSTORE_PK11TOKEN;
544
545 DIR_OPTION_CHECK(kstype, dir);
546
547 if (EMPTYSTRING(outcsr) && interactive) {
548 (void) get_filename("CSR", &outcsr);
549 }
550 if (EMPTYSTRING(outcsr)) {
551 (void) printf(gettext("A filename must be specified to hold"
552 "the final certificate request data.\n"));
553 return (PK_ERR_USAGE);
554 }
555 /*
556 * verify that the outcsr file does not already exist
557 * and that it can be created.
558 */
559 rv = verify_file(outcsr);
560 if (rv == KMF_ERR_OPEN_FILE) {
561 cryptoerror(LOG_STDERR,
562 gettext("Warning: file \"%s\" exists, "
563 "will be overwritten."), outcsr);
564 if (yesno(gettext("Continue with gencsr? "),
565 gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
566 return (0);
567 } else {
568 /* remove the file */
569 (void) unlink(outcsr);
570 }
571 } else if (rv != KMF_OK) {
572 cryptoerror(LOG_STDERR,
573 gettext("Warning: error accessing \"%s\""), outcsr);
574 return (rv);
575 }
576
577 if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
578 if (EMPTYSTRING(certlabel) && interactive)
579 (void) get_certlabel(&certlabel);
580
581 if (EMPTYSTRING(certlabel)) {
582 cryptoerror(LOG_STDERR, gettext("A label must be "
583 "specified to create a certificate request.\n"));
584 return (PK_ERR_USAGE);
585 }
586 } else if (kstype == KMF_KEYSTORE_OPENSSL) {
587 if (EMPTYSTRING(outkey) && interactive)
588 (void) get_filename("private key", &outkey);
589
590 if (EMPTYSTRING(outkey)) {
591 cryptoerror(LOG_STDERR, gettext("A key filename "
592 "must be specified to create a certificate "
593 "request.\n"));
594 return (PK_ERR_USAGE);
595 }
596 }
597
598 if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
599 cryptoerror(LOG_STDERR,
600 gettext("Error parsing format string (%s).\n"), format);
601 return (PK_ERR_USAGE);
602 }
603 if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
604 cryptoerror(LOG_STDERR,
605 gettext("CSR must be DER or PEM format.\n"));
606 return (PK_ERR_USAGE);
607 }
608
609 /*
610 * Check the subject name.
611 * If interactive is true, get it now interactively.
612 */
613 if (interactive) {
614 if (get_subname(&subname) != KMF_OK) {
615 cryptoerror(LOG_STDERR, gettext("Failed to get the "
616 "subject name interactively.\n"));
617 return (PK_ERR_USAGE);
618 }
619 } else {
620 if (EMPTYSTRING(subject)) {
621 cryptoerror(LOG_STDERR, gettext("A subject name or "
622 "-i must be specified to create a certificate "
623 "request.\n"));
624 return (PK_ERR_USAGE);
625 } else {
626 subname = strdup(subject);
627 if (subname == NULL) {
628 cryptoerror(LOG_STDERR,
629 gettext("Out of memory.\n"));
630 return (PK_ERR_SYSTEM);
631 }
632 }
633 }
634 if (altname != NULL) {
635 rv = verify_altname(altname, &alttype, &altcrit);
636 if (rv != KMF_OK) {
637 cryptoerror(LOG_STDERR, gettext("Subject AltName "
638 "must be specified as a name=value pair. "
639 "See the man page for details."));
640 goto end;
641 } else {
642 /* advance the altname past the '=' sign */
643 char *p = strchr(altname, '=');
644 if (p != NULL)
645 altname = p + 1;
646 }
647 }
648
649 if (kustr != NULL) {
650 rv = verify_keyusage(kustr, &kubits, &kucrit);
651 if (rv != KMF_OK) {
652 cryptoerror(LOG_STDERR, gettext("KeyUsage "
653 "must be specified as a comma-separated list. "
654 "See the man page for details."));
655 goto end;
656 }
657 }
658 if (ekustr != NULL) {
659 rv = verify_ekunames(ekustr, &ekulist);
660 if (rv != KMF_OK) {
661 (void) fprintf(stderr, gettext("EKUs must "
662 "be specified as a comma-separated list. "
663 "See the man page for details.\n"));
664 rv = PK_ERR_USAGE;
665 goto end;
666 }
667 }
668 if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
669 cryptoerror(LOG_STDERR,
670 gettext("Unsupported key/hash combination (%s/%s).\n"),
671 keytype, (hashname ? hashname : "none"));
672 goto end;
673 }
674 if (curveoid != NULL && keyAlg != KMF_ECDSA) {
675 cryptoerror(LOG_STDERR, gettext("EC curves are only "
676 "valid for EC keytypes.\n"));
677 return (PK_ERR_USAGE);
678 }
679 if (keyAlg == KMF_ECDSA && curveoid == NULL) {
680 cryptoerror(LOG_STDERR, gettext("A curve must be "
681 "specifed when using EC keys.\n"));
682 return (PK_ERR_USAGE);
683 }
684 if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
685 (void) fprintf(stderr, gettext("ECC certificates are"
686 "only supported with the pkcs11 and nss keystores\n"));
687 rv = PK_ERR_USAGE;
688 goto end;
689 }
690
691 /* Adjust default keylength for NSS and DSA */
692 if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
693 keylen = 1024;
694
695 if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
696 if (tokenname == NULL || !strlen(tokenname)) {
697 if (kstype == KMF_KEYSTORE_NSS) {
698 tokenname = "internal";
699 } else {
700 tokenname = PK_DEFAULT_PK11TOKEN;
701 }
702 }
703
704 (void) get_token_password(kstype, tokenname, &tokencred);
705 }
706
707 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
708 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
709 return (PK_ERR_USAGE);
710 }
711
712
713 if (kstype == KMF_KEYSTORE_NSS) {
714 if (dir == NULL)
715 dir = PK_DEFAULT_DIRECTORY;
716
717 rv = gencsr_nss(kmfhandle,
718 tokenname, subname, altname, alttype, altcrit,
719 certlabel, dir, prefix,
720 keyAlg, keylen, kubits, kucrit,
721 fmt, outcsr, &tokencred, ekulist,
722 sigAlg, curveoid);
723
724 } else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
725 rv = gencsr_pkcs11(kmfhandle,
726 tokenname, subname, altname, alttype, altcrit,
727 certlabel, keyAlg, keylen,
728 kubits, kucrit, fmt, outcsr, &tokencred,
729 ekulist, sigAlg, curveoid);
730
731 } else if (kstype == KMF_KEYSTORE_OPENSSL) {
732 rv = gencsr_file(kmfhandle,
733 keyAlg, keylen, fmt, subname, altname,
734 alttype, altcrit, kubits, kucrit,
735 outcsr, outkey, ekulist, sigAlg);
736 }
737
738 end:
739 if (rv != KMF_OK) {
740 display_error(kmfhandle, rv,
741 gettext("Error creating CSR or keypair"));
742
743 if (rv == KMF_ERR_RDN_PARSER) {
744 cryptoerror(LOG_STDERR, gettext("subject or "
745 "issuer name must be in proper DN format.\n"));
746 }
747 }
748
749 if (ekulist != NULL)
750 free_eku_list(ekulist);
751
752 if (subname)
753 free(subname);
754
755 if (tokencred.cred != NULL)
756 free(tokencred.cred);
757
758 (void) kmf_finalize(kmfhandle);
759 if (rv != KMF_OK)
760 return (PK_ERR_USAGE);
761
762 return (0);
763 }
764