xref: /titanic_52/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 985be8f145003c39bf82ad09a81ad394e4d7d4b6)
199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
2099ebb4caSwyllys  */
2199ebb4caSwyllys /*
22*985be8f1Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2399ebb4caSwyllys  * Use is subject to license terms.
2499ebb4caSwyllys  */
2599ebb4caSwyllys 
2699ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
2799ebb4caSwyllys 
2899ebb4caSwyllys #include <stdio.h>
2999ebb4caSwyllys #include <string.h>
3099ebb4caSwyllys #include <ctype.h>
3199ebb4caSwyllys #include <malloc.h>
3299ebb4caSwyllys #include <libgen.h>
3399ebb4caSwyllys #include <errno.h>
3499ebb4caSwyllys #include <cryptoutil.h>
3599ebb4caSwyllys #include <security/cryptoki.h>
3699ebb4caSwyllys #include "common.h"
3799ebb4caSwyllys 
3899ebb4caSwyllys #include <kmfapi.h>
3999ebb4caSwyllys 
4099ebb4caSwyllys #define	SET_VALUE(f, s) \
4199ebb4caSwyllys 	kmfrv = f; \
4299ebb4caSwyllys 	if (kmfrv != KMF_OK) { \
4399ebb4caSwyllys 		cryptoerror(LOG_STDERR, \
4499ebb4caSwyllys 			gettext("Failed to set %s: 0x%02x\n"), \
4599ebb4caSwyllys 			s, kmfrv); \
4699ebb4caSwyllys 		goto cleanup; \
4799ebb4caSwyllys 	}
4899ebb4caSwyllys 
4999ebb4caSwyllys static int
5099ebb4caSwyllys gencert_pkcs11(KMF_HANDLE_T kmfhandle,
5199ebb4caSwyllys 	char *token, char *subject, char *altname,
5299ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
5399ebb4caSwyllys 	char *certlabel, KMF_KEY_ALG keyAlg,
5499ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg,
5599ebb4caSwyllys 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
5699ebb4caSwyllys 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred)
5799ebb4caSwyllys {
5899ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
5999ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
6099ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
6199ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
6299ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
6399ebb4caSwyllys 	KMF_X509_NAME	certSubject;
6499ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
6599ebb4caSwyllys 	KMF_DATA x509DER;
6699ebb4caSwyllys 
6799ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
6899ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
6999ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
7099ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
7199ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
7299ebb4caSwyllys 
7399ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
7499ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
7599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
7699ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
7799ebb4caSwyllys 		return (PK_ERR_USAGE);
7899ebb4caSwyllys 	}
7999ebb4caSwyllys 
8099ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
8199ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
8299ebb4caSwyllys 		cryptoerror(LOG_STDERR,
8399ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
8499ebb4caSwyllys 		return (PK_ERR_USAGE);
8599ebb4caSwyllys 	}
8699ebb4caSwyllys 
8799ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
8899ebb4caSwyllys 	kp_params.keylabel = certlabel;
8999ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
9099ebb4caSwyllys 	kp_params.keytype = keyAlg;
9199ebb4caSwyllys 	kp_params.cred.cred = tokencred->cred;
9299ebb4caSwyllys 	kp_params.cred.credlen = tokencred->credlen;
9399ebb4caSwyllys 
9499ebb4caSwyllys 	/* Select a PKCS11 token */
9599ebb4caSwyllys 	kmfrv = select_token(kmfhandle, token, FALSE);
9699ebb4caSwyllys 
9799ebb4caSwyllys 	if (kmfrv != KMF_OK) {
9899ebb4caSwyllys 		return (kmfrv);
9999ebb4caSwyllys 	}
10099ebb4caSwyllys 
10199ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
10299ebb4caSwyllys 	if (kmfrv != KMF_OK) {
10399ebb4caSwyllys 		return (kmfrv);
10499ebb4caSwyllys 	}
10599ebb4caSwyllys 
10699ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
10799ebb4caSwyllys 			"keypair");
10899ebb4caSwyllys 
10999ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
11099ebb4caSwyllys 
11199ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
11299ebb4caSwyllys 			"serial number");
11399ebb4caSwyllys 
11499ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
11599ebb4caSwyllys 		"validity time");
11699ebb4caSwyllys 
11799ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
11899ebb4caSwyllys 		"signature algorithm");
11999ebb4caSwyllys 
12099ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
12199ebb4caSwyllys 		"subject name");
12299ebb4caSwyllys 
12399ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
12499ebb4caSwyllys 		"issuer name");
12599ebb4caSwyllys 
12699ebb4caSwyllys 	if (altname != NULL)
12799ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
12899ebb4caSwyllys 			alttype, altname), "subjectAltName");
12999ebb4caSwyllys 
13099ebb4caSwyllys 	if (kubits != 0)
13199ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
13299ebb4caSwyllys 			"KeyUsage");
13399ebb4caSwyllys 
13499ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
13599ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
13699ebb4caSwyllys 		goto cleanup;
13799ebb4caSwyllys 	}
13899ebb4caSwyllys 
13999ebb4caSwyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
14099ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_PK11TOKEN;
14199ebb4caSwyllys 	sc_params.certLabel = certlabel;
14299ebb4caSwyllys 
14399ebb4caSwyllys 	/*
14499ebb4caSwyllys 	 * Store the cert in the DB.
14599ebb4caSwyllys 	 */
14699ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
14799ebb4caSwyllys 
14899ebb4caSwyllys cleanup:
14999ebb4caSwyllys 	KMF_FreeData(&x509DER);
15099ebb4caSwyllys 	KMF_FreeDN(&certSubject);
15199ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
15299ebb4caSwyllys 	return (kmfrv);
15399ebb4caSwyllys }
15499ebb4caSwyllys 
15599ebb4caSwyllys static int
15699ebb4caSwyllys gencert_file(KMF_HANDLE_T kmfhandle,
15799ebb4caSwyllys 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
15899ebb4caSwyllys 	int keylen, KMF_ENCODE_FORMAT fmt,
15999ebb4caSwyllys 	uint32_t ltime, char *subject, char *altname,
16099ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
16199ebb4caSwyllys 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
16299ebb4caSwyllys 	char *dir, char *outcert, char *outkey)
16399ebb4caSwyllys {
16499ebb4caSwyllys 	KMF_RETURN kmfrv;
16599ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
16699ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
16799ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
16899ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
16999ebb4caSwyllys 	KMF_X509_NAME	certSubject;
17099ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
17199ebb4caSwyllys 	KMF_DATA x509DER;
17299ebb4caSwyllys 	char *fullcertpath = NULL;
17399ebb4caSwyllys 	char *fullkeypath = NULL;
17499ebb4caSwyllys 
17599ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
17699ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
17799ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
17899ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
17999ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
18099ebb4caSwyllys 	(void) memset(&sc_params, 0, sizeof (sc_params));
18199ebb4caSwyllys 
18299ebb4caSwyllys 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
18399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
18499ebb4caSwyllys 			gettext("No output file was specified for "
18599ebb4caSwyllys 				"the cert or key\n"));
18699ebb4caSwyllys 		return (PK_ERR_USAGE);
18799ebb4caSwyllys 	}
18899ebb4caSwyllys 	if (dir != NULL) {
18999ebb4caSwyllys 		fullcertpath = get_fullpath(dir, outcert);
19099ebb4caSwyllys 		if (fullcertpath == NULL) {
19199ebb4caSwyllys 			cryptoerror(LOG_STDERR,
19299ebb4caSwyllys 				gettext("Cannot create file %s in "
19399ebb4caSwyllys 					"directory %s\n"), dir, outcert);
19499ebb4caSwyllys 			return (PK_ERR_USAGE);
19599ebb4caSwyllys 		}
19699ebb4caSwyllys 	} else {
19799ebb4caSwyllys 		fullcertpath = strdup(outcert);
19899ebb4caSwyllys 	}
19999ebb4caSwyllys 	if (verify_file(fullcertpath)) {
20099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
20199ebb4caSwyllys 			gettext("Cannot write the indicated output "
20299ebb4caSwyllys 				"certificate file (%s).\n"),
20399ebb4caSwyllys 				fullcertpath);
20499ebb4caSwyllys 		free(fullcertpath);
20599ebb4caSwyllys 		return (PK_ERR_USAGE);
20699ebb4caSwyllys 	}
20799ebb4caSwyllys 	if (dir != NULL) {
20899ebb4caSwyllys 		fullkeypath = get_fullpath(dir, outkey);
20999ebb4caSwyllys 		if (fullkeypath == NULL) {
21099ebb4caSwyllys 			cryptoerror(LOG_STDERR,
21199ebb4caSwyllys 				gettext("Cannot create file %s in "
21299ebb4caSwyllys 					"directory %s\n"), dir, outkey);
21399ebb4caSwyllys 			free(fullcertpath);
21499ebb4caSwyllys 			return (PK_ERR_USAGE);
21599ebb4caSwyllys 		}
21699ebb4caSwyllys 	} else {
21799ebb4caSwyllys 		fullkeypath = strdup(outkey);
21899ebb4caSwyllys 	}
21999ebb4caSwyllys 	if (verify_file(fullkeypath)) {
22099ebb4caSwyllys 		cryptoerror(LOG_STDERR,
22199ebb4caSwyllys 			gettext("Cannot write the indicated output "
22299ebb4caSwyllys 				"key file (%s).\n"),
22399ebb4caSwyllys 				fullkeypath);
22499ebb4caSwyllys 		free(fullkeypath);
22599ebb4caSwyllys 		free(fullcertpath);
22699ebb4caSwyllys 		return (PK_ERR_USAGE);
22799ebb4caSwyllys 	}
22899ebb4caSwyllys 
22999ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
23099ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
23199ebb4caSwyllys 		cryptoerror(LOG_STDERR,
23299ebb4caSwyllys 			gettext("Subject name cannot be parsed (%s)\n"),
23399ebb4caSwyllys 			subject);
23499ebb4caSwyllys 		return (PK_ERR_USAGE);
23599ebb4caSwyllys 	}
23699ebb4caSwyllys 
23799ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
23899ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
23999ebb4caSwyllys 		cryptoerror(LOG_STDERR,
24099ebb4caSwyllys 			gettext("Subject name cannot be parsed (%s)\n"),
24199ebb4caSwyllys 			subject);
24299ebb4caSwyllys 		KMF_FreeDN(&certSubject);
24399ebb4caSwyllys 		return (PK_ERR_USAGE);
24499ebb4caSwyllys 	}
24599ebb4caSwyllys 
24699ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_OPENSSL;
24799ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
24899ebb4caSwyllys 	kp_params.keytype = keyAlg;
24999ebb4caSwyllys 
25099ebb4caSwyllys 	kp_params.sslparms.keyfile = fullkeypath;
25199ebb4caSwyllys 	kp_params.sslparms.format = fmt;
25299ebb4caSwyllys 
25399ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
25499ebb4caSwyllys 	if (kmfrv != KMF_OK) {
25599ebb4caSwyllys 		goto cleanup;
25699ebb4caSwyllys 	}
25799ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
25899ebb4caSwyllys 		"keypair");
25999ebb4caSwyllys 
26099ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
26199ebb4caSwyllys 
26299ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
26399ebb4caSwyllys 		"serial number");
26499ebb4caSwyllys 
26599ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
26699ebb4caSwyllys 		"validity time");
26799ebb4caSwyllys 
26899ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
26999ebb4caSwyllys 		"signature algorithm");
27099ebb4caSwyllys 
27199ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
27299ebb4caSwyllys 		"subject name");
27399ebb4caSwyllys 
27499ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
27599ebb4caSwyllys 		"issuer name");
27699ebb4caSwyllys 
27799ebb4caSwyllys 	if (altname != NULL)
27899ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
27999ebb4caSwyllys 			alttype, altname), "subjectAltName");
28099ebb4caSwyllys 
28199ebb4caSwyllys 	if (kubits != 0)
28299ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
28399ebb4caSwyllys 			"KeyUsage");
28499ebb4caSwyllys 
28599ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
28699ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
28799ebb4caSwyllys 		goto cleanup;
28899ebb4caSwyllys 	}
28999ebb4caSwyllys 
29099ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_OPENSSL;
29199ebb4caSwyllys 	sc_params.sslparms.certfile = fullcertpath;
29299ebb4caSwyllys 	sc_params.sslparms.keyfile = fullkeypath;
29399ebb4caSwyllys 	sc_params.sslparms.format = fmt;
29499ebb4caSwyllys 	/*
29599ebb4caSwyllys 	 * Store the cert in the DB.
29699ebb4caSwyllys 	 */
29799ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
29899ebb4caSwyllys 
29999ebb4caSwyllys cleanup:
30099ebb4caSwyllys 	if (fullkeypath != NULL)
30199ebb4caSwyllys 		free(fullkeypath);
30299ebb4caSwyllys 	if (fullcertpath != NULL)
30399ebb4caSwyllys 		free(fullcertpath);
30499ebb4caSwyllys 
30599ebb4caSwyllys 	KMF_FreeData(&x509DER);
30699ebb4caSwyllys 	KMF_FreeDN(&certSubject);
30799ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
30899ebb4caSwyllys 	return (kmfrv);
30999ebb4caSwyllys }
31099ebb4caSwyllys 
31199ebb4caSwyllys static KMF_RETURN
31299ebb4caSwyllys gencert_nss(KMF_HANDLE_T kmfhandle,
31399ebb4caSwyllys 	char *token, char *subject, char *altname,
31499ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype, int altcrit,
31599ebb4caSwyllys 	char *nickname, char *dir, char *prefix,
31699ebb4caSwyllys 	KMF_KEY_ALG keyAlg,
31799ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg,
31899ebb4caSwyllys 	int keylen, char *trust,
31999ebb4caSwyllys 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
32099ebb4caSwyllys 	int kucrit, KMF_CREDENTIAL *tokencred)
32199ebb4caSwyllys {
32299ebb4caSwyllys 	KMF_RETURN kmfrv;
32399ebb4caSwyllys 	KMF_CREATEKEYPAIR_PARAMS kp_params;
32499ebb4caSwyllys 	KMF_STORECERT_PARAMS sc_params;
32599ebb4caSwyllys 	KMF_KEY_HANDLE pubk, prik;
32699ebb4caSwyllys 	KMF_X509_CERTIFICATE signedCert;
32799ebb4caSwyllys 	KMF_X509_NAME	certSubject;
32899ebb4caSwyllys 	KMF_X509_NAME	certIssuer;
32999ebb4caSwyllys 	KMF_DATA x509DER;
33099ebb4caSwyllys 
33199ebb4caSwyllys 	if (token == NULL)
33299ebb4caSwyllys 		token = DEFAULT_NSS_TOKEN;
33399ebb4caSwyllys 
33499ebb4caSwyllys 	kmfrv = configure_nss(kmfhandle, dir, prefix);
33599ebb4caSwyllys 	if (kmfrv != KMF_OK)
33699ebb4caSwyllys 		return (kmfrv);
33799ebb4caSwyllys 
33899ebb4caSwyllys 	(void) memset(&signedCert, 0, sizeof (signedCert));
33999ebb4caSwyllys 	(void) memset(&certSubject, 0, sizeof (certSubject));
34099ebb4caSwyllys 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
34199ebb4caSwyllys 	(void) memset(&x509DER, 0, sizeof (x509DER));
34299ebb4caSwyllys 
34399ebb4caSwyllys 	/* If the subject name cannot be parsed, flag it now and exit */
34499ebb4caSwyllys 	if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
34599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
34699ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
34799ebb4caSwyllys 		return (PK_ERR_USAGE);
34899ebb4caSwyllys 	}
34999ebb4caSwyllys 
35099ebb4caSwyllys 	/* For a self-signed cert, the issuser and subject are the same */
35199ebb4caSwyllys 	if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
35299ebb4caSwyllys 		cryptoerror(LOG_STDERR,
35399ebb4caSwyllys 			gettext("Subject name cannot be parsed.\n"));
35499ebb4caSwyllys 		return (PK_ERR_USAGE);
35599ebb4caSwyllys 	}
35699ebb4caSwyllys 
35799ebb4caSwyllys 	(void) memset(&kp_params, 0, sizeof (kp_params));
35899ebb4caSwyllys 
35999ebb4caSwyllys 	kp_params.kstype = KMF_KEYSTORE_NSS;
36099ebb4caSwyllys 	kp_params.keylabel = nickname;
36199ebb4caSwyllys 	kp_params.keylength = keylen; /* bits */
36299ebb4caSwyllys 	kp_params.keytype = keyAlg;
36399ebb4caSwyllys 	kp_params.cred.cred = tokencred->cred;
36499ebb4caSwyllys 	kp_params.cred.credlen = tokencred->credlen;
36599ebb4caSwyllys 	kp_params.nssparms.slotlabel = token;
36699ebb4caSwyllys 
36799ebb4caSwyllys 	kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
36899ebb4caSwyllys 	if (kmfrv != KMF_OK) {
36999ebb4caSwyllys 		return (kmfrv);
37099ebb4caSwyllys 	}
37199ebb4caSwyllys 
37299ebb4caSwyllys 	SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
37399ebb4caSwyllys 			"keypair");
37499ebb4caSwyllys 
37599ebb4caSwyllys 	SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
37699ebb4caSwyllys 
37799ebb4caSwyllys 	SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
37899ebb4caSwyllys 			"serial number");
37999ebb4caSwyllys 
38099ebb4caSwyllys 	SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
38199ebb4caSwyllys 		"validity time");
38299ebb4caSwyllys 
38399ebb4caSwyllys 	SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
38499ebb4caSwyllys 		"signature algorithm");
38599ebb4caSwyllys 
38699ebb4caSwyllys 	SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
38799ebb4caSwyllys 		"subject name");
38899ebb4caSwyllys 
38999ebb4caSwyllys 	SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
39099ebb4caSwyllys 		"issuer name");
39199ebb4caSwyllys 
39299ebb4caSwyllys 	if (altname != NULL)
39399ebb4caSwyllys 		SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
39499ebb4caSwyllys 			alttype, altname), "subjectAltName");
39599ebb4caSwyllys 
39699ebb4caSwyllys 	if (kubits)
39799ebb4caSwyllys 		SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
39899ebb4caSwyllys 			"subjectAltName");
39999ebb4caSwyllys 
40099ebb4caSwyllys 	if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
40199ebb4caSwyllys 		&signedCert, &x509DER)) != KMF_OK) {
40299ebb4caSwyllys 		goto cleanup;
40399ebb4caSwyllys 	}
40499ebb4caSwyllys 
40599ebb4caSwyllys 	sc_params.kstype = KMF_KEYSTORE_NSS;
40699ebb4caSwyllys 	sc_params.certLabel = nickname;
40799ebb4caSwyllys 	sc_params.nssparms.trustflag = trust;
40899ebb4caSwyllys 	sc_params.nssparms.slotlabel = token;
40999ebb4caSwyllys 
41099ebb4caSwyllys 	/*
41199ebb4caSwyllys 	 * Store the cert in the DB.
41299ebb4caSwyllys 	 */
41399ebb4caSwyllys 	kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
41499ebb4caSwyllys 
41599ebb4caSwyllys cleanup:
41699ebb4caSwyllys 	KMF_FreeData(&x509DER);
41799ebb4caSwyllys 	KMF_FreeDN(&certSubject);
41899ebb4caSwyllys 	KMF_FreeDN(&certIssuer);
41999ebb4caSwyllys 	return (kmfrv);
42099ebb4caSwyllys }
42199ebb4caSwyllys 
42299ebb4caSwyllys int
42399ebb4caSwyllys pk_gencert(int argc, char *argv[])
42499ebb4caSwyllys {
42599ebb4caSwyllys 	int rv;
42699ebb4caSwyllys 	int opt;
42799ebb4caSwyllys 	extern int	optind_av;
42899ebb4caSwyllys 	extern char	*optarg_av;
42999ebb4caSwyllys 	KMF_KEYSTORE_TYPE kstype = 0;
43099ebb4caSwyllys 	char *subject = NULL;
43199ebb4caSwyllys 	char *tokenname = NULL;
43299ebb4caSwyllys 	char *dir = NULL;
43399ebb4caSwyllys 	char *prefix = NULL;
43499ebb4caSwyllys 	char *keytype = PK_DEFAULT_KEYTYPE;
43599ebb4caSwyllys 	int keylen = PK_DEFAULT_KEYLENGTH;
43699ebb4caSwyllys 	char *trust = NULL;
43799ebb4caSwyllys 	char *lifetime = NULL;
43899ebb4caSwyllys 	char *certlabel = NULL;
43999ebb4caSwyllys 	char *outcert = NULL;
44099ebb4caSwyllys 	char *outkey = NULL;
44199ebb4caSwyllys 	char *format = NULL;
44299ebb4caSwyllys 	char *serstr = NULL;
44399ebb4caSwyllys 	char *altname = NULL;
44499ebb4caSwyllys 	char *keyusagestr = NULL;
44599ebb4caSwyllys 	KMF_GENERALNAMECHOICES alttype = 0;
44699ebb4caSwyllys 	KMF_BIGINT serial = { NULL, 0 };
44799ebb4caSwyllys 	uint32_t ltime;
44899ebb4caSwyllys 	KMF_HANDLE_T kmfhandle = NULL;
44999ebb4caSwyllys 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
45099ebb4caSwyllys 	KMF_KEY_ALG keyAlg = KMF_RSA;
45199ebb4caSwyllys 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
45299ebb4caSwyllys 	boolean_t interactive = B_FALSE;
45399ebb4caSwyllys 	char *subname = NULL;
45499ebb4caSwyllys 	KMF_CREDENTIAL tokencred = {NULL, 0};
45599ebb4caSwyllys 	uint16_t kubits = 0;
45699ebb4caSwyllys 	int altcrit = 0, kucrit = 0;
45799ebb4caSwyllys 
45899ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
45999ebb4caSwyllys 		"ik:(keystore)s:(subject)n:(nickname)A:(altname)"
46099ebb4caSwyllys 		"T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
46199ebb4caSwyllys 		"r:(trust)L:(lifetime)l:(label)c:(outcert)"
46299ebb4caSwyllys 		"K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
46399ebb4caSwyllys 
46499ebb4caSwyllys 		if (opt != 'i' && EMPTYSTRING(optarg_av))
46599ebb4caSwyllys 			return (PK_ERR_USAGE);
46699ebb4caSwyllys 
46799ebb4caSwyllys 		switch (opt) {
46899ebb4caSwyllys 			case 'A':
46999ebb4caSwyllys 				altname = optarg_av;
47099ebb4caSwyllys 				break;
47199ebb4caSwyllys 			case 'i':
47299ebb4caSwyllys 				if (interactive || subject)
47399ebb4caSwyllys 					return (PK_ERR_USAGE);
47499ebb4caSwyllys 				else
47599ebb4caSwyllys 					interactive = B_TRUE;
47699ebb4caSwyllys 				break;
47799ebb4caSwyllys 			case 'k':
47899ebb4caSwyllys 				kstype = KS2Int(optarg_av);
47999ebb4caSwyllys 				if (kstype == 0)
48099ebb4caSwyllys 					return (PK_ERR_USAGE);
48199ebb4caSwyllys 				break;
48299ebb4caSwyllys 			case 's':
48399ebb4caSwyllys 				if (interactive || subject)
48499ebb4caSwyllys 					return (PK_ERR_USAGE);
48599ebb4caSwyllys 				else
48699ebb4caSwyllys 					subject = optarg_av;
48799ebb4caSwyllys 				break;
48899ebb4caSwyllys 			case 'l':
48999ebb4caSwyllys 			case 'n':
49099ebb4caSwyllys 				if (certlabel)
49199ebb4caSwyllys 					return (PK_ERR_USAGE);
49299ebb4caSwyllys 				certlabel = optarg_av;
49399ebb4caSwyllys 				break;
49499ebb4caSwyllys 			case 'T':
49599ebb4caSwyllys 				if (tokenname)
49699ebb4caSwyllys 					return (PK_ERR_USAGE);
49799ebb4caSwyllys 				tokenname = optarg_av;
49899ebb4caSwyllys 				break;
49999ebb4caSwyllys 			case 'd':
50099ebb4caSwyllys 				if (dir)
50199ebb4caSwyllys 					return (PK_ERR_USAGE);
50299ebb4caSwyllys 				dir = optarg_av;
50399ebb4caSwyllys 				break;
50499ebb4caSwyllys 			case 'p':
50599ebb4caSwyllys 				if (prefix)
50699ebb4caSwyllys 					return (PK_ERR_USAGE);
50799ebb4caSwyllys 				prefix = optarg_av;
50899ebb4caSwyllys 				break;
50999ebb4caSwyllys 			case 't':
51099ebb4caSwyllys 				keytype = optarg_av;
51199ebb4caSwyllys 				break;
51299ebb4caSwyllys 			case 'u':
51399ebb4caSwyllys 				keyusagestr = optarg_av;
51499ebb4caSwyllys 				break;
51599ebb4caSwyllys 			case 'y':
51699ebb4caSwyllys 				if (sscanf(optarg_av, "%d",
51799ebb4caSwyllys 					&keylen) != 1) {
51899ebb4caSwyllys 					cryptoerror(LOG_STDERR,
51999ebb4caSwyllys 						gettext("key length must be"
52099ebb4caSwyllys 						"a numeric value (%s)\n"),
52199ebb4caSwyllys 						optarg_av);
52299ebb4caSwyllys 					return (PK_ERR_USAGE);
52399ebb4caSwyllys 				}
52499ebb4caSwyllys 				break;
52599ebb4caSwyllys 			case 'r':
52699ebb4caSwyllys 				if (trust)
52799ebb4caSwyllys 					return (PK_ERR_USAGE);
52899ebb4caSwyllys 				trust = optarg_av;
52999ebb4caSwyllys 				break;
53099ebb4caSwyllys 			case 'L':
53199ebb4caSwyllys 				if (lifetime)
53299ebb4caSwyllys 					return (PK_ERR_USAGE);
53399ebb4caSwyllys 				lifetime = optarg_av;
53499ebb4caSwyllys 				break;
53599ebb4caSwyllys 			case 'c':
53699ebb4caSwyllys 				if (outcert)
53799ebb4caSwyllys 					return (PK_ERR_USAGE);
53899ebb4caSwyllys 				outcert = optarg_av;
53999ebb4caSwyllys 				break;
54099ebb4caSwyllys 			case 'K':
54199ebb4caSwyllys 				if (outkey)
54299ebb4caSwyllys 					return (PK_ERR_USAGE);
54399ebb4caSwyllys 				outkey = optarg_av;
54499ebb4caSwyllys 				break;
54599ebb4caSwyllys 			case 'S':
54699ebb4caSwyllys 				serstr = optarg_av;
54799ebb4caSwyllys 				break;
54899ebb4caSwyllys 			case 'F':
54999ebb4caSwyllys 				if (format)
55099ebb4caSwyllys 					return (PK_ERR_USAGE);
55199ebb4caSwyllys 				format = optarg_av;
55299ebb4caSwyllys 				break;
55399ebb4caSwyllys 			default:
55499ebb4caSwyllys 				return (PK_ERR_USAGE);
55599ebb4caSwyllys 		}
55699ebb4caSwyllys 	}
55799ebb4caSwyllys 
55899ebb4caSwyllys 	/* No additional args allowed. */
55999ebb4caSwyllys 	argc -= optind_av;
56099ebb4caSwyllys 	argv += optind_av;
56199ebb4caSwyllys 	if (argc) {
56299ebb4caSwyllys 		return (PK_ERR_USAGE);
56399ebb4caSwyllys 	}
56499ebb4caSwyllys 
56599ebb4caSwyllys 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
56699ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
56799ebb4caSwyllys 		return (PK_ERR_USAGE);
56899ebb4caSwyllys 	}
56999ebb4caSwyllys 
57099ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
57199ebb4caSwyllys 	if (kstype == 0)
57299ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
57399ebb4caSwyllys 
57499ebb4caSwyllys 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
57599ebb4caSwyllys 	    EMPTYSTRING(certlabel)) {
57699ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("A label must be specified "
57799ebb4caSwyllys 		    "to create a self-signed certificate.\n"));
57899ebb4caSwyllys 		return (PK_ERR_USAGE);
57999ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
58099ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
58199ebb4caSwyllys 		    "be specified to create a self-signed certificate.\n"));
58299ebb4caSwyllys 		return (PK_ERR_USAGE);
58399ebb4caSwyllys 	}
58499ebb4caSwyllys 
58599ebb4caSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
58699ebb4caSwyllys 		cryptoerror(LOG_STDERR,
58799ebb4caSwyllys 		    gettext("Error parsing format string (%s).\n"),
58899ebb4caSwyllys 		    format);
58999ebb4caSwyllys 		return (PK_ERR_USAGE);
59099ebb4caSwyllys 	}
59199ebb4caSwyllys 
59299ebb4caSwyllys 	if (Str2Lifetime(lifetime, &ltime) != 0) {
59399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
59499ebb4caSwyllys 			gettext("Error parsing lifetime string\n"));
59599ebb4caSwyllys 		return (PK_ERR_USAGE);
59699ebb4caSwyllys 	}
59799ebb4caSwyllys 
59899ebb4caSwyllys 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
59999ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
60099ebb4caSwyllys 			keytype);
60199ebb4caSwyllys 		return (PK_ERR_USAGE);
60299ebb4caSwyllys 	}
60399ebb4caSwyllys 
60499ebb4caSwyllys 
60599ebb4caSwyllys 	/*
60699ebb4caSwyllys 	 * Check the subject name.
60799ebb4caSwyllys 	 * If interactive is true, get it now interactively.
60899ebb4caSwyllys 	 */
60999ebb4caSwyllys 	if (interactive) {
61099ebb4caSwyllys 		if (get_subname(&subname) != KMF_OK) {
61199ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
61299ebb4caSwyllys 			    "subject name interactively.\n"));
61399ebb4caSwyllys 			return (PK_ERR_USAGE);
61499ebb4caSwyllys 		}
61599ebb4caSwyllys 	} else {
61699ebb4caSwyllys 		if (EMPTYSTRING(subject)) {
61799ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A subject name or "
61899ebb4caSwyllys 			    "-i must be specified to create a self-signed "
61999ebb4caSwyllys 			    "certificate.\n"));
62099ebb4caSwyllys 			return (PK_ERR_USAGE);
62199ebb4caSwyllys 		} else {
62299ebb4caSwyllys 			subname = strdup(subject);
62399ebb4caSwyllys 			if (subname == NULL) {
62499ebb4caSwyllys 				cryptoerror(LOG_STDERR,
62599ebb4caSwyllys 				    gettext("Out of memory.\n"));
62699ebb4caSwyllys 				return (PK_ERR_SYSTEM);
62799ebb4caSwyllys 			}
62899ebb4caSwyllys 		}
62999ebb4caSwyllys 	}
63099ebb4caSwyllys 
63199ebb4caSwyllys 	if (serstr == NULL) {
63299ebb4caSwyllys 		(void) fprintf(stderr, gettext("A serial number "
63399ebb4caSwyllys 			"must be specified as a hex number when creating"
63499ebb4caSwyllys 			" a self-signed certificate "
635*985be8f1Swyllys 			"(ex: serial=0x0102030405feedface)\n"));
63699ebb4caSwyllys 		rv = PK_ERR_USAGE;
63799ebb4caSwyllys 		goto end;
63899ebb4caSwyllys 	} else {
63999ebb4caSwyllys 		uchar_t *bytes = NULL;
64099ebb4caSwyllys 		size_t bytelen;
64199ebb4caSwyllys 
64299ebb4caSwyllys 		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
64399ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
64499ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
64599ebb4caSwyllys 				"must be specified as a hex number "
64699ebb4caSwyllys 				"(ex: 0x0102030405ffeeddee)\n"));
64799ebb4caSwyllys 			rv = PK_ERR_USAGE;
64899ebb4caSwyllys 			goto end;
64999ebb4caSwyllys 		}
65099ebb4caSwyllys 		serial.val = bytes;
65199ebb4caSwyllys 		serial.len = bytelen;
65299ebb4caSwyllys 	}
65399ebb4caSwyllys 
65499ebb4caSwyllys 	if (altname != NULL) {
65599ebb4caSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
65699ebb4caSwyllys 		if (rv != KMF_OK) {
65799ebb4caSwyllys 			(void) fprintf(stderr, gettext("Subject AltName "
65899ebb4caSwyllys 				"must be specified as a name=value pair. "
65999ebb4caSwyllys 				"See the man page for details.\n"));
66099ebb4caSwyllys 			rv = PK_ERR_USAGE;
66199ebb4caSwyllys 			goto end;
66299ebb4caSwyllys 		} else {
66399ebb4caSwyllys 			/* advance the altname past the '=' sign */
66499ebb4caSwyllys 			char *p = strchr(altname, '=');
66599ebb4caSwyllys 			if (p != NULL)
66699ebb4caSwyllys 				altname = p + 1;
66799ebb4caSwyllys 		}
66899ebb4caSwyllys 	}
66999ebb4caSwyllys 
67099ebb4caSwyllys 	if (keyusagestr != NULL) {
67199ebb4caSwyllys 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
67299ebb4caSwyllys 		if (rv != KMF_OK) {
67399ebb4caSwyllys 			(void) fprintf(stderr, gettext("KeyUsage "
67499ebb4caSwyllys 				"must be specified as a comma-separated list. "
67599ebb4caSwyllys 				"See the man page for details.\n"));
67699ebb4caSwyllys 			rv = PK_ERR_USAGE;
67799ebb4caSwyllys 			goto end;
67899ebb4caSwyllys 		}
67999ebb4caSwyllys 	}
68099ebb4caSwyllys 
68199ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
68299ebb4caSwyllys 		if (tokenname == NULL || !strlen(tokenname)) {
68399ebb4caSwyllys 			if (kstype == KMF_KEYSTORE_NSS) {
68499ebb4caSwyllys 				tokenname = "internal";
68599ebb4caSwyllys 			} else  {
68699ebb4caSwyllys 				tokenname = PK_DEFAULT_PK11TOKEN;
68799ebb4caSwyllys 			}
68899ebb4caSwyllys 		}
68999ebb4caSwyllys 
69099ebb4caSwyllys 		(void) get_token_password(kstype, tokenname, &tokencred);
69199ebb4caSwyllys 	}
69299ebb4caSwyllys 
69399ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
69499ebb4caSwyllys 		if (dir == NULL)
69599ebb4caSwyllys 			dir = PK_DEFAULT_DIRECTORY;
69699ebb4caSwyllys 
69799ebb4caSwyllys 		rv = gencert_nss(kmfhandle,
69899ebb4caSwyllys 			tokenname, subname, altname, alttype, altcrit,
69999ebb4caSwyllys 			certlabel, dir, prefix, keyAlg, sigAlg, keylen,
70099ebb4caSwyllys 			trust, ltime, &serial, kubits, kucrit, &tokencred);
70199ebb4caSwyllys 
70299ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
70399ebb4caSwyllys 		rv = gencert_pkcs11(kmfhandle,
70499ebb4caSwyllys 			tokenname, subname, altname, alttype, altcrit,
70599ebb4caSwyllys 			certlabel, keyAlg, sigAlg, keylen, ltime,
70699ebb4caSwyllys 			&serial, kubits, kucrit, &tokencred);
70799ebb4caSwyllys 
70899ebb4caSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
70999ebb4caSwyllys 		rv = gencert_file(kmfhandle,
71099ebb4caSwyllys 			keyAlg, sigAlg, keylen, fmt,
71199ebb4caSwyllys 			ltime, subname, altname, alttype, altcrit,
71299ebb4caSwyllys 			&serial, kubits, kucrit, dir, outcert, outkey);
71399ebb4caSwyllys 	}
71499ebb4caSwyllys 
71599ebb4caSwyllys 	if (rv != KMF_OK)
71699ebb4caSwyllys 		display_error(kmfhandle, rv,
71799ebb4caSwyllys 			gettext("Error creating certificate and keypair"));
71899ebb4caSwyllys end:
71999ebb4caSwyllys 	if (subname)
72099ebb4caSwyllys 		free(subname);
72199ebb4caSwyllys 	if (tokencred.cred != NULL)
72299ebb4caSwyllys 		free(tokencred.cred);
72399ebb4caSwyllys 
72499ebb4caSwyllys 	if (serial.val != NULL)
72599ebb4caSwyllys 		free(serial.val);
72699ebb4caSwyllys 
72799ebb4caSwyllys 	(void) KMF_Finalize(kmfhandle);
72899ebb4caSwyllys 	return (rv);
72999ebb4caSwyllys }
730