13089Swyllys /*
23089Swyllys * CDDL HEADER START
33089Swyllys *
43089Swyllys * The contents of this file are subject to the terms of the
53089Swyllys * Common Development and Distribution License (the "License").
63089Swyllys * You may not use this file except in compliance with the License.
73089Swyllys *
83089Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93089Swyllys * or http://www.opensolaris.org/os/licensing.
103089Swyllys * See the License for the specific language governing permissions
113089Swyllys * and limitations under the License.
123089Swyllys *
133089Swyllys * When distributing Covered Code, include this CDDL HEADER in each
143089Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153089Swyllys * If applicable, add the following below this CDDL HEADER, with the
163089Swyllys * fields enclosed by brackets "[]" replaced with your own identifying
173089Swyllys * information: Portions Copyright [yyyy] [name of copyright owner]
183089Swyllys *
193089Swyllys * CDDL HEADER END
203089Swyllys *
21*12234Swyllys.ingersoll@sun.com * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
223089Swyllys */
233089Swyllys
243089Swyllys #include <stdio.h>
253089Swyllys #include <string.h>
263089Swyllys #include <ctype.h>
273089Swyllys #include <malloc.h>
283089Swyllys #include <libgen.h>
293089Swyllys #include <errno.h>
303089Swyllys #include <cryptoutil.h>
313089Swyllys #include <security/cryptoki.h>
323089Swyllys #include "common.h"
333089Swyllys
343089Swyllys #include <kmfapi.h>
353089Swyllys
363089Swyllys #define SET_VALUE(f, s) \
373089Swyllys kmfrv = f; \
383089Swyllys if (kmfrv != KMF_OK) { \
393089Swyllys cryptoerror(LOG_STDERR, \
403089Swyllys gettext("Failed to %s: 0x%02\n"), \
413089Swyllys s, kmfrv); \
423089Swyllys goto cleanup; \
433089Swyllys }
443089Swyllys
453089Swyllys 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)463089Swyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
473089Swyllys char *token, char *subject, char *altname,
483089Swyllys KMF_GENERALNAMECHOICES alttype, int altcrit,
493089Swyllys char *certlabel, KMF_KEY_ALG keyAlg,
506051Swyllys int keylen, uint16_t kubits, int kucrit,
513089Swyllys KMF_ENCODE_FORMAT fmt, char *csrfile,
5211973Swyllys.ingersoll@sun.com KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
5311973Swyllys.ingersoll@sun.com KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
543089Swyllys {
553089Swyllys KMF_RETURN kmfrv = KMF_OK;
563089Swyllys KMF_KEY_HANDLE pubk, prik;
573089Swyllys KMF_X509_NAME csrSubject;
583089Swyllys KMF_CSR_DATA csr;
593089Swyllys KMF_DATA signedCsr = {NULL, 0};
603089Swyllys
615051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
625051Swyllys int numattr = 0;
635051Swyllys KMF_ATTRIBUTE attrlist[16];
645051Swyllys
653089Swyllys (void) memset(&csr, 0, sizeof (csr));
663089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject));
673089Swyllys
683089Swyllys /* If the subject name cannot be parsed, flag it now and exit */
6911973Swyllys.ingersoll@sun.com if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK)
703089Swyllys return (kmfrv);
713089Swyllys
723089Swyllys /* Select a PKCS11 token */
733089Swyllys kmfrv = select_token(kmfhandle, token, FALSE);
7411973Swyllys.ingersoll@sun.com if (kmfrv != KMF_OK)
753089Swyllys return (kmfrv);
7611973Swyllys.ingersoll@sun.com /*
7711973Swyllys.ingersoll@sun.com * Share the "genkeypair" routine for creating the keypair.
7811973Swyllys.ingersoll@sun.com */
7911973Swyllys.ingersoll@sun.com kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
8011973Swyllys.ingersoll@sun.com keyAlg, keylen, tokencred, curveoid, &prik, &pubk);
8111973Swyllys.ingersoll@sun.com if (kmfrv != KMF_OK)
823089Swyllys return (kmfrv);
833089Swyllys
845051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
853089Swyllys
865051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
873089Swyllys
885051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
893089Swyllys
905051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
915051Swyllys "SignatureAlgorithm");
923089Swyllys
933089Swyllys if (altname != NULL) {
945051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
955051Swyllys alttype), "SetCSRSubjectAltName");
963089Swyllys }
973089Swyllys
983089Swyllys if (kubits != 0) {
995051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
1005051Swyllys "SetCSRKeyUsage");
1013089Swyllys }
1026051Swyllys if (ekulist != NULL) {
1036051Swyllys int i;
1046051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
1056051Swyllys SET_VALUE(kmf_add_csr_eku(&csr,
1066051Swyllys &ekulist->ekulist[i],
1076051Swyllys ekulist->critlist[i]),
1086051Swyllys "Extended Key Usage");
1096051Swyllys }
1106051Swyllys }
1115051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
1125051Swyllys KMF_OK) {
1135051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
1143089Swyllys }
1153089Swyllys
1163089Swyllys cleanup:
1175051Swyllys (void) kmf_free_data(&signedCsr);
1189145SHuie-Ying.Lee@Sun.COM (void) kmf_free_signed_csr(&csr);
1199145SHuie-Ying.Lee@Sun.COM
1209145SHuie-Ying.Lee@Sun.COM /* delete the public key */
1215051Swyllys numattr = 0;
1225051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
1235051Swyllys &kstype, sizeof (kstype));
1245051Swyllys numattr++;
1255051Swyllys
1265051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
1275051Swyllys &pubk, sizeof (KMF_KEY_HANDLE));
1285051Swyllys numattr++;
1295051Swyllys
1309145SHuie-Ying.Lee@Sun.COM if (tokencred != NULL && tokencred->cred != NULL) {
1319145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
1329145SHuie-Ying.Lee@Sun.COM tokencred, sizeof (KMF_CREDENTIAL));
1339145SHuie-Ying.Lee@Sun.COM numattr++;
1349145SHuie-Ying.Lee@Sun.COM }
1359145SHuie-Ying.Lee@Sun.COM
1365051Swyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
1375051Swyllys
1389145SHuie-Ying.Lee@Sun.COM /*
1399145SHuie-Ying.Lee@Sun.COM * If there is an error, then we need to remove the private key
1409145SHuie-Ying.Lee@Sun.COM * from the token.
1419145SHuie-Ying.Lee@Sun.COM */
1429145SHuie-Ying.Lee@Sun.COM if (kmfrv != KMF_OK) {
1439145SHuie-Ying.Lee@Sun.COM numattr = 0;
1449145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr,
1459145SHuie-Ying.Lee@Sun.COM KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
1469145SHuie-Ying.Lee@Sun.COM numattr++;
1473089Swyllys
1489145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr,
1499145SHuie-Ying.Lee@Sun.COM KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
1509145SHuie-Ying.Lee@Sun.COM numattr++;
1519145SHuie-Ying.Lee@Sun.COM
1529145SHuie-Ying.Lee@Sun.COM if (tokencred != NULL && tokencred->cred != NULL) {
1539145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr,
1549145SHuie-Ying.Lee@Sun.COM KMF_CREDENTIAL_ATTR, tokencred,
1559145SHuie-Ying.Lee@Sun.COM sizeof (KMF_CREDENTIAL));
1569145SHuie-Ying.Lee@Sun.COM numattr++;
1579145SHuie-Ying.Lee@Sun.COM }
1589145SHuie-Ying.Lee@Sun.COM
1599145SHuie-Ying.Lee@Sun.COM (void) kmf_delete_key_from_keystore(kmfhandle, numattr,
1609145SHuie-Ying.Lee@Sun.COM attrlist);
1619145SHuie-Ying.Lee@Sun.COM }
1629145SHuie-Ying.Lee@Sun.COM
1639145SHuie-Ying.Lee@Sun.COM (void) kmf_free_kmf_key(kmfhandle, &prik);
1643089Swyllys return (kmfrv);
1653089Swyllys }
1663089Swyllys
1673089Swyllys 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)1683089Swyllys gencsr_file(KMF_HANDLE_T kmfhandle,
1693089Swyllys KMF_KEY_ALG keyAlg,
1703089Swyllys int keylen, KMF_ENCODE_FORMAT fmt,
1713089Swyllys char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
1723089Swyllys int altcrit, uint16_t kubits, int kucrit,
17311973Swyllys.ingersoll@sun.com char *outcsr, char *outkey, EKU_LIST *ekulist,
17411973Swyllys.ingersoll@sun.com KMF_ALGORITHM_INDEX sigAlg)
1753089Swyllys {
1763089Swyllys KMF_RETURN kmfrv;
1773089Swyllys KMF_KEY_HANDLE pubk, prik;
1783089Swyllys KMF_X509_NAME csrSubject;
1793089Swyllys KMF_CSR_DATA csr;
1803089Swyllys KMF_DATA signedCsr = {NULL, 0};
1813089Swyllys char *fullcsrpath = NULL;
1823089Swyllys char *fullkeypath = NULL;
1833089Swyllys
1845051Swyllys
1853089Swyllys (void) memset(&csr, 0, sizeof (csr));
1863089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject));
1873089Swyllys
1883089Swyllys if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
1893089Swyllys cryptoerror(LOG_STDERR,
1905051Swyllys gettext("No output file was specified for "
1915051Swyllys "the csr or key\n"));
1923089Swyllys return (KMF_ERR_BAD_PARAMETER);
1933089Swyllys }
1946669Swyllys fullcsrpath = strdup(outcsr);
1953089Swyllys if (verify_file(fullcsrpath)) {
1963089Swyllys cryptoerror(LOG_STDERR,
1975051Swyllys gettext("Cannot write the indicated output "
1985051Swyllys "certificate file (%s).\n"), fullcsrpath);
1993089Swyllys free(fullcsrpath);
2003089Swyllys return (PK_ERR_USAGE);
2013089Swyllys }
2026669Swyllys
2033089Swyllys /* If the subject name cannot be parsed, flag it now and exit */
2045051Swyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
2053089Swyllys return (kmfrv);
2063089Swyllys }
20711973Swyllys.ingersoll@sun.com /*
20811973Swyllys.ingersoll@sun.com * Share the "genkeypair" routine for creating the keypair.
20911973Swyllys.ingersoll@sun.com */
21011973Swyllys.ingersoll@sun.com kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
21111973Swyllys.ingersoll@sun.com fmt, outkey, &prik, &pubk);
21211973Swyllys.ingersoll@sun.com if (kmfrv != KMF_OK)
21311973Swyllys.ingersoll@sun.com return (kmfrv);
2143089Swyllys
2155051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
2165051Swyllys "SetCSRPubKey");
2173089Swyllys
2185051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
2193089Swyllys
2205051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
2215051Swyllys "kmf_set_csr_subject");
2223089Swyllys
2235051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
2243089Swyllys
2253089Swyllys if (altname != NULL) {
2265051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
2275051Swyllys alttype), "kmf_set_csr_subject_altname");
2283089Swyllys }
2293089Swyllys if (kubits != NULL) {
2305051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
2315051Swyllys "kmf_set_csr_ku");
2323089Swyllys }
2336051Swyllys if (ekulist != NULL) {
2346051Swyllys int i;
2356051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
2366051Swyllys SET_VALUE(kmf_add_csr_eku(&csr,
2376051Swyllys &ekulist->ekulist[i],
2386051Swyllys ekulist->critlist[i]),
2396051Swyllys "Extended Key Usage");
2406051Swyllys }
2416051Swyllys }
2425051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
2435051Swyllys KMF_OK) {
2445051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
2453089Swyllys }
2463089Swyllys
2473089Swyllys cleanup:
2483089Swyllys if (fullkeypath)
2493089Swyllys free(fullkeypath);
2503089Swyllys if (fullcsrpath)
2513089Swyllys free(fullcsrpath);
2523089Swyllys
2535051Swyllys kmf_free_data(&signedCsr);
2545051Swyllys kmf_free_kmf_key(kmfhandle, &prik);
2555051Swyllys kmf_free_signed_csr(&csr);
2563089Swyllys
2573089Swyllys return (kmfrv);
2583089Swyllys }
2593089Swyllys
2603089Swyllys 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)2613089Swyllys gencsr_nss(KMF_HANDLE_T kmfhandle,
2623089Swyllys char *token, char *subject, char *altname,
2633089Swyllys KMF_GENERALNAMECHOICES alttype, int altcrit,
2643089Swyllys char *nickname, char *dir, char *prefix,
2653089Swyllys KMF_KEY_ALG keyAlg, int keylen,
2663089Swyllys uint16_t kubits, int kucrit,
2673089Swyllys KMF_ENCODE_FORMAT fmt, char *csrfile,
26811973Swyllys.ingersoll@sun.com KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
26911973Swyllys.ingersoll@sun.com KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
2703089Swyllys {
2713089Swyllys KMF_RETURN kmfrv;
2723089Swyllys KMF_KEY_HANDLE pubk, prik;
2733089Swyllys KMF_X509_NAME csrSubject;
2743089Swyllys KMF_CSR_DATA csr;
2753089Swyllys KMF_DATA signedCsr = {NULL, 0};
2765051Swyllys
2775051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
2785051Swyllys int numattr = 0;
2795051Swyllys KMF_ATTRIBUTE attrlist[16];
2803089Swyllys
2813089Swyllys if (token == NULL)
2823089Swyllys token = DEFAULT_NSS_TOKEN;
2833089Swyllys
2843089Swyllys kmfrv = configure_nss(kmfhandle, dir, prefix);
2853089Swyllys if (kmfrv != KMF_OK)
2863089Swyllys return (kmfrv);
2873089Swyllys
2883089Swyllys (void) memset(&csr, 0, sizeof (csr));
2893089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject));
2906669Swyllys (void) memset(&pubk, 0, sizeof (pubk));
2916669Swyllys (void) memset(&prik, 0, sizeof (prik));
2923089Swyllys
2933089Swyllys /* If the subject name cannot be parsed, flag it now and exit */
2945051Swyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
2953089Swyllys return (kmfrv);
2963089Swyllys }
2973089Swyllys
29811973Swyllys.ingersoll@sun.com kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
29911973Swyllys.ingersoll@sun.com prefix, keyAlg, keylen, tokencred, curveoid,
30011973Swyllys.ingersoll@sun.com &prik, &pubk);
30111973Swyllys.ingersoll@sun.com if (kmfrv != KMF_OK)
30211973Swyllys.ingersoll@sun.com return (kmfrv);
3033089Swyllys
3045051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
3055051Swyllys "kmf_set_csr_pubkey");
3065051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
3075051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
3085051Swyllys "kmf_set_csr_subject");
3095051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
3103089Swyllys
3113089Swyllys if (altname != NULL) {
3125051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
3135051Swyllys alttype), "kmf_set_csr_subject_altname");
3143089Swyllys }
3153089Swyllys if (kubits != NULL) {
3165051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
3175051Swyllys "kmf_set_csr_ku");
3183089Swyllys }
3196051Swyllys if (ekulist != NULL) {
3206051Swyllys int i;
3216051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
3226051Swyllys SET_VALUE(kmf_add_csr_eku(&csr,
3236051Swyllys &ekulist->ekulist[i],
3246051Swyllys ekulist->critlist[i]),
3256051Swyllys "Extended Key Usage");
3266051Swyllys }
3276051Swyllys }
3285051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
3295051Swyllys KMF_OK) {
3305051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
3313089Swyllys }
3323089Swyllys
3333089Swyllys cleanup:
3345051Swyllys (void) kmf_free_data(&signedCsr);
3355051Swyllys (void) kmf_free_kmf_key(kmfhandle, &prik);
3365051Swyllys
3373089Swyllys /* delete the key */
3385051Swyllys numattr = 0;
3395051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3405051Swyllys &kstype, sizeof (kstype));
3415051Swyllys numattr++;
3425051Swyllys
3435051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
3445051Swyllys &pubk, sizeof (KMF_KEY_HANDLE));
3455051Swyllys numattr++;
3465051Swyllys
3475051Swyllys if (tokencred != NULL && tokencred->credlen > 0) {
3485051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
3495051Swyllys tokencred, sizeof (KMF_CREDENTIAL));
3505051Swyllys numattr++;
3515051Swyllys }
3525051Swyllys
3535051Swyllys if (token && strlen(token)) {
3545051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
3555051Swyllys token, strlen(token));
3565051Swyllys numattr++;
3575051Swyllys }
3585051Swyllys
3595051Swyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
3605051Swyllys
3615051Swyllys (void) kmf_free_signed_csr(&csr);
3623089Swyllys
3633089Swyllys return (kmfrv);
3643089Swyllys }
3653089Swyllys
3663089Swyllys int
pk_gencsr(int argc,char * argv[])3673089Swyllys pk_gencsr(int argc, char *argv[])
3683089Swyllys {
3693089Swyllys KMF_RETURN rv;
3703089Swyllys int opt;
3713089Swyllys extern int optind_av;
3723089Swyllys extern char *optarg_av;
3733089Swyllys KMF_KEYSTORE_TYPE kstype = 0;
3743089Swyllys char *subject = NULL;
3753089Swyllys char *tokenname = NULL;
3763089Swyllys char *dir = NULL;
3773089Swyllys char *prefix = NULL;
3783089Swyllys int keylen = PK_DEFAULT_KEYLENGTH;
3793089Swyllys char *certlabel = NULL;
3803089Swyllys char *outcsr = NULL;
3813089Swyllys char *outkey = NULL;
3823089Swyllys char *format = NULL;
3833089Swyllys char *altname = NULL;
3843089Swyllys char *kustr = NULL;
3856051Swyllys char *ekustr = NULL;
38611973Swyllys.ingersoll@sun.com char *hashname = NULL;
3873089Swyllys uint16_t kubits = 0;
3883089Swyllys char *keytype = PK_DEFAULT_KEYTYPE;
3893089Swyllys KMF_HANDLE_T kmfhandle = NULL;
3903089Swyllys KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
3913089Swyllys KMF_KEY_ALG keyAlg = KMF_RSA;
39210744Swyllys.ingersoll@sun.com KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
3933089Swyllys boolean_t interactive = B_FALSE;
3943089Swyllys char *subname = NULL;
3953089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0};
3963089Swyllys KMF_GENERALNAMECHOICES alttype = 0;
3973089Swyllys int altcrit = 0, kucrit = 0;
3986051Swyllys EKU_LIST *ekulist = NULL;
39911973Swyllys.ingersoll@sun.com KMF_OID *curveoid = NULL; /* ECC */
40011973Swyllys.ingersoll@sun.com KMF_OID *hashoid = NULL;
40111973Swyllys.ingersoll@sun.com int y_flag = 0;
4023089Swyllys
4033089Swyllys while ((opt = getopt_av(argc, argv,
4045051Swyllys "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
4055051Swyllys "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
40611973Swyllys.ingersoll@sun.com "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
40711973Swyllys.ingersoll@sun.com "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {
4083089Swyllys
4093089Swyllys switch (opt) {
4103089Swyllys case 'A':
4113089Swyllys altname = optarg_av;
4123089Swyllys break;
4133089Swyllys case 'i':
41410241Swyllys.ingersoll@sun.com if (interactive)
4153089Swyllys return (PK_ERR_USAGE);
41610241Swyllys.ingersoll@sun.com else if (subject) {
41710241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
41810241Swyllys.ingersoll@sun.com gettext("Interactive (-i) and "
41910241Swyllys.ingersoll@sun.com "subject options are mutually "
42010241Swyllys.ingersoll@sun.com "exclusive.\n"));
42110241Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
42210241Swyllys.ingersoll@sun.com } else
4233089Swyllys interactive = B_TRUE;
4243089Swyllys break;
4253089Swyllys case 'k':
4263089Swyllys kstype = KS2Int(optarg_av);
4273089Swyllys if (kstype == 0)
4283089Swyllys return (PK_ERR_USAGE);
4293089Swyllys break;
4303089Swyllys case 's':
43110241Swyllys.ingersoll@sun.com if (subject)
4323089Swyllys return (PK_ERR_USAGE);
43310241Swyllys.ingersoll@sun.com else if (interactive) {
43410241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
43510241Swyllys.ingersoll@sun.com gettext("Interactive (-i) and "
43610241Swyllys.ingersoll@sun.com "subject options are mutually "
43710241Swyllys.ingersoll@sun.com "exclusive.\n"));
43810241Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
43910241Swyllys.ingersoll@sun.com } else
4403089Swyllys subject = optarg_av;
4413089Swyllys break;
4423089Swyllys case 'l':
4433089Swyllys case 'n':
4443089Swyllys if (certlabel)
4453089Swyllys return (PK_ERR_USAGE);
4463089Swyllys certlabel = optarg_av;
4473089Swyllys break;
4483089Swyllys case 'T':
4493089Swyllys if (tokenname)
4503089Swyllys return (PK_ERR_USAGE);
4513089Swyllys tokenname = optarg_av;
4523089Swyllys break;
4533089Swyllys case 'd':
4543089Swyllys dir = optarg_av;
4553089Swyllys break;
4563089Swyllys case 'p':
4573089Swyllys if (prefix)
4583089Swyllys return (PK_ERR_USAGE);
4593089Swyllys prefix = optarg_av;
4603089Swyllys break;
4613089Swyllys case 't':
4623089Swyllys keytype = optarg_av;
4633089Swyllys break;
4643089Swyllys case 'u':
4653089Swyllys kustr = optarg_av;
4663089Swyllys break;
4673089Swyllys case 'y':
4683089Swyllys if (sscanf(optarg_av, "%d",
4695051Swyllys &keylen) != 1) {
4703089Swyllys cryptoerror(LOG_STDERR,
4715051Swyllys gettext("Unrecognized "
4725051Swyllys "key length (%s)\n"), optarg_av);
4733089Swyllys return (PK_ERR_USAGE);
4743089Swyllys }
47511973Swyllys.ingersoll@sun.com y_flag++;
4763089Swyllys break;
4773089Swyllys case 'c':
4783089Swyllys if (outcsr)
4793089Swyllys return (PK_ERR_USAGE);
4803089Swyllys outcsr = optarg_av;
4813089Swyllys break;
4823089Swyllys case 'K':
4833089Swyllys if (outkey)
4843089Swyllys return (PK_ERR_USAGE);
4853089Swyllys outkey = optarg_av;
4863089Swyllys break;
4873089Swyllys case 'F':
4883089Swyllys if (format)
4893089Swyllys return (PK_ERR_USAGE);
4903089Swyllys format = optarg_av;
4913089Swyllys break;
4926051Swyllys case 'e':
4936051Swyllys ekustr = optarg_av;
4946051Swyllys break;
49511973Swyllys.ingersoll@sun.com case 'C':
49611973Swyllys.ingersoll@sun.com curveoid = ecc_name_to_oid(optarg_av);
49711973Swyllys.ingersoll@sun.com if (curveoid == NULL) {
49811973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
49911973Swyllys.ingersoll@sun.com gettext("Unrecognized ECC "
50011973Swyllys.ingersoll@sun.com "curve.\n"));
50111973Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
50211973Swyllys.ingersoll@sun.com }
50311973Swyllys.ingersoll@sun.com break;
50411973Swyllys.ingersoll@sun.com case 'E':
50511973Swyllys.ingersoll@sun.com /*
50611973Swyllys.ingersoll@sun.com * This argument is only to be used
50711973Swyllys.ingersoll@sun.com * by itself, no other options should
50811973Swyllys.ingersoll@sun.com * be present.
50911973Swyllys.ingersoll@sun.com */
51011973Swyllys.ingersoll@sun.com if (argc != 2) {
51111973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
51211973Swyllys.ingersoll@sun.com gettext("listcurves has no other "
51311973Swyllys.ingersoll@sun.com "options.\n"));
51411973Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
51511973Swyllys.ingersoll@sun.com }
51611973Swyllys.ingersoll@sun.com show_ecc_curves();
51711973Swyllys.ingersoll@sun.com return (0);
51811973Swyllys.ingersoll@sun.com case 'h':
51911973Swyllys.ingersoll@sun.com hashname = optarg_av;
52011973Swyllys.ingersoll@sun.com hashoid = ecc_name_to_oid(optarg_av);
52111973Swyllys.ingersoll@sun.com if (hashoid == NULL) {
52211973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
52311973Swyllys.ingersoll@sun.com gettext("Unrecognized hash.\n"));
52411973Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
52511973Swyllys.ingersoll@sun.com }
52611973Swyllys.ingersoll@sun.com break;
5273089Swyllys default:
5283089Swyllys cryptoerror(LOG_STDERR, gettext(
5295051Swyllys "unrecognized gencsr option '%s'\n"),
5305051Swyllys argv[optind_av]);
5313089Swyllys return (PK_ERR_USAGE);
5323089Swyllys }
5333089Swyllys }
5343089Swyllys /* No additional args allowed. */
5353089Swyllys argc -= optind_av;
5363089Swyllys argv += optind_av;
5373089Swyllys if (argc) {
5383089Swyllys return (PK_ERR_USAGE);
5393089Swyllys }
5403089Swyllys
5413089Swyllys /* Assume keystore = PKCS#11 if not specified. */
5423089Swyllys if (kstype == 0)
5433089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN;
5443089Swyllys
5456884Swyllys DIR_OPTION_CHECK(kstype, dir);
5466884Swyllys
5475221Swyllys if (EMPTYSTRING(outcsr) && interactive) {
5485221Swyllys (void) get_filename("CSR", &outcsr);
5495221Swyllys }
5503089Swyllys if (EMPTYSTRING(outcsr)) {
5513089Swyllys (void) printf(gettext("A filename must be specified to hold"
5525051Swyllys "the final certificate request data.\n"));
5533089Swyllys return (PK_ERR_USAGE);
5545221Swyllys }
5555221Swyllys /*
5565221Swyllys * verify that the outcsr file does not already exist
5575221Swyllys * and that it can be created.
5585221Swyllys */
5595221Swyllys rv = verify_file(outcsr);
560*12234Swyllys.ingersoll@sun.com if (rv == KMF_ERR_OPEN_FILE) {
561*12234Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
562*12234Swyllys.ingersoll@sun.com gettext("Warning: file \"%s\" exists, "
563*12234Swyllys.ingersoll@sun.com "will be overwritten."), outcsr);
564*12234Swyllys.ingersoll@sun.com if (yesno(gettext("Continue with gencsr? "),
565*12234Swyllys.ingersoll@sun.com gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
566*12234Swyllys.ingersoll@sun.com return (0);
567*12234Swyllys.ingersoll@sun.com } else {
568*12234Swyllys.ingersoll@sun.com /* remove the file */
569*12234Swyllys.ingersoll@sun.com (void) unlink(outcsr);
570*12234Swyllys.ingersoll@sun.com }
571*12234Swyllys.ingersoll@sun.com } else if (rv != KMF_OK) {
572*12234Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
573*12234Swyllys.ingersoll@sun.com gettext("Warning: error accessing \"%s\""), outcsr);
574*12234Swyllys.ingersoll@sun.com return (rv);
5755221Swyllys }
5765221Swyllys
5775221Swyllys if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
5785221Swyllys if (EMPTYSTRING(certlabel) && interactive)
5795221Swyllys (void) get_certlabel(&certlabel);
5805221Swyllys
5815221Swyllys if (EMPTYSTRING(certlabel)) {
5825221Swyllys cryptoerror(LOG_STDERR, gettext("A label must be "
5835221Swyllys "specified to create a certificate request.\n"));
5843089Swyllys return (PK_ERR_USAGE);
5853089Swyllys }
5865221Swyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) {
5875221Swyllys if (EMPTYSTRING(outkey) && interactive)
5885221Swyllys (void) get_filename("private key", &outkey);
5893089Swyllys
5905221Swyllys if (EMPTYSTRING(outkey)) {
5915221Swyllys cryptoerror(LOG_STDERR, gettext("A key filename "
5925221Swyllys "must be specified to create a certificate "
5935221Swyllys "request.\n"));
5945221Swyllys return (PK_ERR_USAGE);
5955221Swyllys }
5963089Swyllys }
5973089Swyllys
5983089Swyllys if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
5993089Swyllys cryptoerror(LOG_STDERR,
6005051Swyllys gettext("Error parsing format string (%s).\n"), format);
6013089Swyllys return (PK_ERR_USAGE);
6023089Swyllys }
6033089Swyllys if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
6043089Swyllys cryptoerror(LOG_STDERR,
6055051Swyllys gettext("CSR must be DER or PEM format.\n"));
6063089Swyllys return (PK_ERR_USAGE);
6073089Swyllys }
6083089Swyllys
6093089Swyllys /*
6103089Swyllys * Check the subject name.
6113089Swyllys * If interactive is true, get it now interactively.
6123089Swyllys */
6133089Swyllys if (interactive) {
6143089Swyllys if (get_subname(&subname) != KMF_OK) {
6153089Swyllys cryptoerror(LOG_STDERR, gettext("Failed to get the "
6163089Swyllys "subject name interactively.\n"));
6173089Swyllys return (PK_ERR_USAGE);
6183089Swyllys }
6193089Swyllys } else {
6203089Swyllys if (EMPTYSTRING(subject)) {
6213089Swyllys cryptoerror(LOG_STDERR, gettext("A subject name or "
6223089Swyllys "-i must be specified to create a certificate "
6233089Swyllys "request.\n"));
6243089Swyllys return (PK_ERR_USAGE);
6253089Swyllys } else {
6263089Swyllys subname = strdup(subject);
6273089Swyllys if (subname == NULL) {
6283089Swyllys cryptoerror(LOG_STDERR,
6293089Swyllys gettext("Out of memory.\n"));
6303089Swyllys return (PK_ERR_SYSTEM);
6313089Swyllys }
6323089Swyllys }
6333089Swyllys }
6343089Swyllys if (altname != NULL) {
6353089Swyllys rv = verify_altname(altname, &alttype, &altcrit);
6363089Swyllys if (rv != KMF_OK) {
6373089Swyllys cryptoerror(LOG_STDERR, gettext("Subject AltName "
6385051Swyllys "must be specified as a name=value pair. "
6395051Swyllys "See the man page for details."));
6403089Swyllys goto end;
6413089Swyllys } else {
6423089Swyllys /* advance the altname past the '=' sign */
6433089Swyllys char *p = strchr(altname, '=');
6443089Swyllys if (p != NULL)
6453089Swyllys altname = p + 1;
6463089Swyllys }
6473089Swyllys }
6483089Swyllys
6493089Swyllys if (kustr != NULL) {
6503089Swyllys rv = verify_keyusage(kustr, &kubits, &kucrit);
6513089Swyllys if (rv != KMF_OK) {
6523089Swyllys cryptoerror(LOG_STDERR, gettext("KeyUsage "
6535051Swyllys "must be specified as a comma-separated list. "
6545051Swyllys "See the man page for details."));
6553089Swyllys goto end;
6563089Swyllys }
6573089Swyllys }
6586051Swyllys if (ekustr != NULL) {
6596051Swyllys rv = verify_ekunames(ekustr, &ekulist);
6606051Swyllys if (rv != KMF_OK) {
6616051Swyllys (void) fprintf(stderr, gettext("EKUs must "
6626051Swyllys "be specified as a comma-separated list. "
6636051Swyllys "See the man page for details.\n"));
6646051Swyllys rv = PK_ERR_USAGE;
6656051Swyllys goto end;
6666051Swyllys }
6676051Swyllys }
66811973Swyllys.ingersoll@sun.com if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
66911973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR,
67011973Swyllys.ingersoll@sun.com gettext("Unsupported key/hash combination (%s/%s).\n"),
67111973Swyllys.ingersoll@sun.com keytype, (hashname ? hashname : "none"));
6723089Swyllys goto end;
6733089Swyllys }
67411973Swyllys.ingersoll@sun.com if (curveoid != NULL && keyAlg != KMF_ECDSA) {
67511973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, gettext("EC curves are only "
67611973Swyllys.ingersoll@sun.com "valid for EC keytypes.\n"));
67711973Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
67811973Swyllys.ingersoll@sun.com }
67911973Swyllys.ingersoll@sun.com if (keyAlg == KMF_ECDSA && curveoid == NULL) {
68011973Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, gettext("A curve must be "
68111973Swyllys.ingersoll@sun.com "specifed when using EC keys.\n"));
68211973Swyllys.ingersoll@sun.com return (PK_ERR_USAGE);
68311973Swyllys.ingersoll@sun.com }
68411973Swyllys.ingersoll@sun.com if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
68511973Swyllys.ingersoll@sun.com (void) fprintf(stderr, gettext("ECC certificates are"
68611973Swyllys.ingersoll@sun.com "only supported with the pkcs11 and nss keystores\n"));
68711973Swyllys.ingersoll@sun.com rv = PK_ERR_USAGE;
68811973Swyllys.ingersoll@sun.com goto end;
68911973Swyllys.ingersoll@sun.com }
69011973Swyllys.ingersoll@sun.com
69111973Swyllys.ingersoll@sun.com /* Adjust default keylength for NSS and DSA */
69211973Swyllys.ingersoll@sun.com if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
69311973Swyllys.ingersoll@sun.com keylen = 1024;
6943089Swyllys
6953089Swyllys if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
6963089Swyllys if (tokenname == NULL || !strlen(tokenname)) {
6973089Swyllys if (kstype == KMF_KEYSTORE_NSS) {
6983089Swyllys tokenname = "internal";
6993089Swyllys } else {
7003089Swyllys tokenname = PK_DEFAULT_PK11TOKEN;
7013089Swyllys }
7023089Swyllys }
7033089Swyllys
7043089Swyllys (void) get_token_password(kstype, tokenname, &tokencred);
7053089Swyllys }
7063089Swyllys
7076884Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7086884Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
7096884Swyllys return (PK_ERR_USAGE);
7106884Swyllys }
7116884Swyllys
7126884Swyllys
7133089Swyllys if (kstype == KMF_KEYSTORE_NSS) {
7143089Swyllys if (dir == NULL)
7153089Swyllys dir = PK_DEFAULT_DIRECTORY;
7163089Swyllys
7173089Swyllys rv = gencsr_nss(kmfhandle,
7185051Swyllys tokenname, subname, altname, alttype, altcrit,
7195051Swyllys certlabel, dir, prefix,
7205051Swyllys keyAlg, keylen, kubits, kucrit,
72111973Swyllys.ingersoll@sun.com fmt, outcsr, &tokencred, ekulist,
72211973Swyllys.ingersoll@sun.com sigAlg, curveoid);
7233089Swyllys
7243089Swyllys } else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
7253089Swyllys rv = gencsr_pkcs11(kmfhandle,
7265051Swyllys tokenname, subname, altname, alttype, altcrit,
7275051Swyllys certlabel, keyAlg, keylen,
72811973Swyllys.ingersoll@sun.com kubits, kucrit, fmt, outcsr, &tokencred,
72911973Swyllys.ingersoll@sun.com ekulist, sigAlg, curveoid);
7303089Swyllys
7313089Swyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) {
7323089Swyllys rv = gencsr_file(kmfhandle,
7335051Swyllys keyAlg, keylen, fmt, subname, altname,
7345051Swyllys alttype, altcrit, kubits, kucrit,
73511973Swyllys.ingersoll@sun.com outcsr, outkey, ekulist, sigAlg);
7363089Swyllys }
7373089Swyllys
7383089Swyllys end:
73910241Swyllys.ingersoll@sun.com if (rv != KMF_OK) {
7403089Swyllys display_error(kmfhandle, rv,
7415051Swyllys gettext("Error creating CSR or keypair"));
7423089Swyllys
74310241Swyllys.ingersoll@sun.com if (rv == KMF_ERR_RDN_PARSER) {
74410241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, gettext("subject or "
74510241Swyllys.ingersoll@sun.com "issuer name must be in proper DN format.\n"));
74610241Swyllys.ingersoll@sun.com }
74710241Swyllys.ingersoll@sun.com }
74810241Swyllys.ingersoll@sun.com
7496051Swyllys if (ekulist != NULL)
7506051Swyllys free_eku_list(ekulist);
7516051Swyllys
7523089Swyllys if (subname)
7533089Swyllys free(subname);
7543089Swyllys
7553089Swyllys if (tokencred.cred != NULL)
7563089Swyllys free(tokencred.cred);
7573089Swyllys
7585051Swyllys (void) kmf_finalize(kmfhandle);
7593089Swyllys if (rv != KMF_OK)
7603089Swyllys return (PK_ERR_USAGE);
7613089Swyllys
7623089Swyllys return (0);
7633089Swyllys }
764