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 * 22d00756ccSwyllys * Copyright 2008 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 %s: 0x%02\n"), \ 4599ebb4caSwyllys s, kmfrv); \ 4699ebb4caSwyllys goto cleanup; \ 4799ebb4caSwyllys } 4899ebb4caSwyllys 4999ebb4caSwyllys static KMF_RETURN 5099ebb4caSwyllys gencsr_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, 54d00756ccSwyllys int keylen, uint16_t kubits, int kucrit, 5599ebb4caSwyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 56d00756ccSwyllys KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist) 5799ebb4caSwyllys { 5899ebb4caSwyllys KMF_RETURN kmfrv = KMF_OK; 5999ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 6099ebb4caSwyllys KMF_X509_NAME csrSubject; 6199ebb4caSwyllys KMF_CSR_DATA csr; 6299ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 6399ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 6499ebb4caSwyllys 6530a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 6630a5e8faSwyllys int numattr = 0; 6730a5e8faSwyllys KMF_ATTRIBUTE attrlist[16]; 6830a5e8faSwyllys boolean_t storekey = TRUE; 6930a5e8faSwyllys 7099ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 7199ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 7299ebb4caSwyllys 7399ebb4caSwyllys if (keyAlg == KMF_DSA) 7499ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 7599ebb4caSwyllys else 7699ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 7799ebb4caSwyllys 7899ebb4caSwyllys 7999ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 8030a5e8faSwyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 8199ebb4caSwyllys return (kmfrv); 8299ebb4caSwyllys } 8399ebb4caSwyllys 8499ebb4caSwyllys /* Select a PKCS11 token */ 8599ebb4caSwyllys kmfrv = select_token(kmfhandle, token, FALSE); 8699ebb4caSwyllys if (kmfrv != KMF_OK) { 8799ebb4caSwyllys return (kmfrv); 8899ebb4caSwyllys } 8999ebb4caSwyllys 9030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 9130a5e8faSwyllys &kstype, sizeof (kstype)); 9230a5e8faSwyllys numattr++; 9330a5e8faSwyllys 9430a5e8faSwyllys if (certlabel != NULL && strlen(certlabel)) { 9530a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 9630a5e8faSwyllys certlabel, strlen(certlabel)); 9730a5e8faSwyllys numattr++; 9830a5e8faSwyllys } 9930a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 10030a5e8faSwyllys &keylen, sizeof (keylen)); 10130a5e8faSwyllys numattr++; 10230a5e8faSwyllys 10330a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 10430a5e8faSwyllys &keyAlg, sizeof (keyAlg)); 10530a5e8faSwyllys numattr++; 10630a5e8faSwyllys 10730a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 10830a5e8faSwyllys tokencred, sizeof (KMF_CREDENTIAL)); 10930a5e8faSwyllys numattr++; 11030a5e8faSwyllys 11130a5e8faSwyllys if (token && strlen(token)) { 11230a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 11330a5e8faSwyllys token, strlen(token)); 11430a5e8faSwyllys numattr++; 11530a5e8faSwyllys } 11630a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 11730a5e8faSwyllys &pubk, sizeof (KMF_KEY_HANDLE)); 11830a5e8faSwyllys numattr++; 11930a5e8faSwyllys 12030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 12130a5e8faSwyllys &prik, sizeof (KMF_KEY_HANDLE)); 12230a5e8faSwyllys numattr++; 12330a5e8faSwyllys 12430a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 12530a5e8faSwyllys &storekey, sizeof (storekey)); 12630a5e8faSwyllys numattr++; 12730a5e8faSwyllys 12830a5e8faSwyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 12999ebb4caSwyllys if (kmfrv != KMF_OK) { 13099ebb4caSwyllys return (kmfrv); 13199ebb4caSwyllys } 13299ebb4caSwyllys 13330a5e8faSwyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair"); 13499ebb4caSwyllys 13530a5e8faSwyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "version number"); 13699ebb4caSwyllys 13730a5e8faSwyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name"); 13899ebb4caSwyllys 13930a5e8faSwyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), 14099ebb4caSwyllys "SignatureAlgorithm"); 14199ebb4caSwyllys 14299ebb4caSwyllys if (altname != NULL) { 14330a5e8faSwyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 14499ebb4caSwyllys alttype), "SetCSRSubjectAltName"); 14599ebb4caSwyllys } 14699ebb4caSwyllys 14799ebb4caSwyllys if (kubits != 0) { 14830a5e8faSwyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 14999ebb4caSwyllys "SetCSRKeyUsage"); 15099ebb4caSwyllys } 151d00756ccSwyllys if (ekulist != NULL) { 152d00756ccSwyllys int i; 153d00756ccSwyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 154d00756ccSwyllys SET_VALUE(kmf_add_csr_eku(&csr, 155d00756ccSwyllys &ekulist->ekulist[i], 156d00756ccSwyllys ekulist->critlist[i]), 157d00756ccSwyllys "Extended Key Usage"); 158d00756ccSwyllys } 159d00756ccSwyllys } 16030a5e8faSwyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 16199ebb4caSwyllys KMF_OK) { 16230a5e8faSwyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile); 16399ebb4caSwyllys } 16499ebb4caSwyllys 16599ebb4caSwyllys cleanup: 16630a5e8faSwyllys (void) kmf_free_data(&signedCsr); 16730a5e8faSwyllys (void) kmf_free_kmf_key(kmfhandle, &prik); 16899ebb4caSwyllys /* delete the key */ 16930a5e8faSwyllys numattr = 0; 17030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 17130a5e8faSwyllys &kstype, sizeof (kstype)); 17230a5e8faSwyllys numattr++; 17330a5e8faSwyllys 17430a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 17530a5e8faSwyllys &pubk, sizeof (KMF_KEY_HANDLE)); 17630a5e8faSwyllys numattr++; 17730a5e8faSwyllys 17830a5e8faSwyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); 17930a5e8faSwyllys 18030a5e8faSwyllys (void) kmf_free_signed_csr(&csr); 18199ebb4caSwyllys 18299ebb4caSwyllys return (kmfrv); 18399ebb4caSwyllys } 18499ebb4caSwyllys 18599ebb4caSwyllys static KMF_RETURN 18699ebb4caSwyllys gencsr_file(KMF_HANDLE_T kmfhandle, 18799ebb4caSwyllys KMF_KEY_ALG keyAlg, 18899ebb4caSwyllys int keylen, KMF_ENCODE_FORMAT fmt, 18999ebb4caSwyllys char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, 19099ebb4caSwyllys int altcrit, uint16_t kubits, int kucrit, 191*448b8615Swyllys char *outcsr, char *outkey, EKU_LIST *ekulist) 19299ebb4caSwyllys { 19399ebb4caSwyllys KMF_RETURN kmfrv; 19499ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 19599ebb4caSwyllys KMF_X509_NAME csrSubject; 19699ebb4caSwyllys KMF_CSR_DATA csr; 19799ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 19899ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 19999ebb4caSwyllys char *fullcsrpath = NULL; 20099ebb4caSwyllys char *fullkeypath = NULL; 20199ebb4caSwyllys 20230a5e8faSwyllys int numattr = 0; 20330a5e8faSwyllys KMF_ATTRIBUTE attrlist[16]; 20430a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 20530a5e8faSwyllys boolean_t storekey = TRUE; 20630a5e8faSwyllys 20799ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 20899ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 20999ebb4caSwyllys 21099ebb4caSwyllys if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) { 21199ebb4caSwyllys cryptoerror(LOG_STDERR, 21299ebb4caSwyllys gettext("No output file was specified for " 21399ebb4caSwyllys "the csr or key\n")); 21499ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 21599ebb4caSwyllys } 21699ebb4caSwyllys fullcsrpath = strdup(outcsr); 21799ebb4caSwyllys if (verify_file(fullcsrpath)) { 21899ebb4caSwyllys cryptoerror(LOG_STDERR, 21999ebb4caSwyllys gettext("Cannot write the indicated output " 22099ebb4caSwyllys "certificate file (%s).\n"), fullcsrpath); 22199ebb4caSwyllys free(fullcsrpath); 22299ebb4caSwyllys return (PK_ERR_USAGE); 22399ebb4caSwyllys } 224*448b8615Swyllys 22599ebb4caSwyllys fullkeypath = strdup(outkey); 22699ebb4caSwyllys if (verify_file(fullcsrpath)) { 22799ebb4caSwyllys cryptoerror(LOG_STDERR, 22899ebb4caSwyllys gettext("Cannot write the indicated output " 22999ebb4caSwyllys "key file (%s).\n"), fullkeypath); 23099ebb4caSwyllys free(fullcsrpath); 23199ebb4caSwyllys return (PK_ERR_USAGE); 23299ebb4caSwyllys } 23399ebb4caSwyllys 23499ebb4caSwyllys if (keyAlg == KMF_DSA) 23599ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 23699ebb4caSwyllys else 23799ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 23899ebb4caSwyllys 23999ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 24030a5e8faSwyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 24199ebb4caSwyllys return (kmfrv); 24299ebb4caSwyllys } 24399ebb4caSwyllys 24430a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 24530a5e8faSwyllys &kstype, sizeof (kstype)); 24630a5e8faSwyllys numattr++; 24799ebb4caSwyllys 24830a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 24930a5e8faSwyllys fullkeypath, strlen(fullkeypath)); 25030a5e8faSwyllys numattr++; 25199ebb4caSwyllys 25230a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 25330a5e8faSwyllys &keylen, sizeof (keylen)); 25430a5e8faSwyllys numattr++; 25530a5e8faSwyllys 25630a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 25730a5e8faSwyllys &keyAlg, sizeof (keyAlg)); 25830a5e8faSwyllys numattr++; 25930a5e8faSwyllys 26030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 26130a5e8faSwyllys &fmt, sizeof (fmt)); 26230a5e8faSwyllys numattr++; 26330a5e8faSwyllys 26430a5e8faSwyllys (void) memset(&prik, 0, sizeof (prik)); 26530a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 26630a5e8faSwyllys &prik, sizeof (KMF_KEY_HANDLE)); 26730a5e8faSwyllys numattr++; 26830a5e8faSwyllys 26930a5e8faSwyllys (void) memset(&pubk, 0, sizeof (pubk)); 27030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 27130a5e8faSwyllys &pubk, sizeof (KMF_KEY_HANDLE)); 27230a5e8faSwyllys numattr++; 27330a5e8faSwyllys 27430a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 27530a5e8faSwyllys &storekey, sizeof (storekey)); 27630a5e8faSwyllys numattr++; 27730a5e8faSwyllys 27830a5e8faSwyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 27999ebb4caSwyllys if (kmfrv != KMF_OK) { 28099ebb4caSwyllys goto cleanup; 28199ebb4caSwyllys } 28230a5e8faSwyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), 28399ebb4caSwyllys "SetCSRPubKey"); 28499ebb4caSwyllys 28530a5e8faSwyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion"); 28699ebb4caSwyllys 28730a5e8faSwyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), 28830a5e8faSwyllys "kmf_set_csr_subject"); 28999ebb4caSwyllys 29030a5e8faSwyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg"); 29199ebb4caSwyllys 29299ebb4caSwyllys if (altname != NULL) { 29330a5e8faSwyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 29430a5e8faSwyllys alttype), "kmf_set_csr_subject_altname"); 29599ebb4caSwyllys } 29699ebb4caSwyllys if (kubits != NULL) { 29730a5e8faSwyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 29830a5e8faSwyllys "kmf_set_csr_ku"); 29999ebb4caSwyllys } 300d00756ccSwyllys if (ekulist != NULL) { 301d00756ccSwyllys int i; 302d00756ccSwyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 303d00756ccSwyllys SET_VALUE(kmf_add_csr_eku(&csr, 304d00756ccSwyllys &ekulist->ekulist[i], 305d00756ccSwyllys ekulist->critlist[i]), 306d00756ccSwyllys "Extended Key Usage"); 307d00756ccSwyllys } 308d00756ccSwyllys } 30930a5e8faSwyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 31099ebb4caSwyllys KMF_OK) { 31130a5e8faSwyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath); 31299ebb4caSwyllys } 31399ebb4caSwyllys 31499ebb4caSwyllys cleanup: 31599ebb4caSwyllys if (fullkeypath) 31699ebb4caSwyllys free(fullkeypath); 31799ebb4caSwyllys if (fullcsrpath) 31899ebb4caSwyllys free(fullcsrpath); 31999ebb4caSwyllys 32030a5e8faSwyllys kmf_free_data(&signedCsr); 32130a5e8faSwyllys kmf_free_kmf_key(kmfhandle, &prik); 32230a5e8faSwyllys kmf_free_signed_csr(&csr); 32399ebb4caSwyllys 32499ebb4caSwyllys return (kmfrv); 32599ebb4caSwyllys } 32699ebb4caSwyllys 32799ebb4caSwyllys static KMF_RETURN 32899ebb4caSwyllys gencsr_nss(KMF_HANDLE_T kmfhandle, 32999ebb4caSwyllys char *token, char *subject, char *altname, 33099ebb4caSwyllys KMF_GENERALNAMECHOICES alttype, int altcrit, 33199ebb4caSwyllys char *nickname, char *dir, char *prefix, 33299ebb4caSwyllys KMF_KEY_ALG keyAlg, int keylen, 33399ebb4caSwyllys uint16_t kubits, int kucrit, 33499ebb4caSwyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 335d00756ccSwyllys KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist) 33699ebb4caSwyllys { 33799ebb4caSwyllys KMF_RETURN kmfrv; 33899ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 33999ebb4caSwyllys KMF_X509_NAME csrSubject; 34099ebb4caSwyllys KMF_CSR_DATA csr; 34199ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 34299ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 34330a5e8faSwyllys 34430a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 34530a5e8faSwyllys int numattr = 0; 34630a5e8faSwyllys KMF_ATTRIBUTE attrlist[16]; 34730a5e8faSwyllys boolean_t storekey = TRUE; 34899ebb4caSwyllys 34999ebb4caSwyllys if (token == NULL) 35099ebb4caSwyllys token = DEFAULT_NSS_TOKEN; 35199ebb4caSwyllys 35299ebb4caSwyllys if (keyAlg == KMF_DSA) 35399ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 35499ebb4caSwyllys else 35599ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 35699ebb4caSwyllys 35799ebb4caSwyllys kmfrv = configure_nss(kmfhandle, dir, prefix); 35899ebb4caSwyllys if (kmfrv != KMF_OK) 35999ebb4caSwyllys return (kmfrv); 36099ebb4caSwyllys 36199ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 36299ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 363*448b8615Swyllys (void) memset(&pubk, 0, sizeof (pubk)); 364*448b8615Swyllys (void) memset(&prik, 0, sizeof (prik)); 36599ebb4caSwyllys 36699ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 36730a5e8faSwyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 36899ebb4caSwyllys return (kmfrv); 36999ebb4caSwyllys } 37099ebb4caSwyllys 37130a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 37230a5e8faSwyllys &kstype, sizeof (kstype)); 37330a5e8faSwyllys numattr++; 37499ebb4caSwyllys 37530a5e8faSwyllys if (nickname != NULL && strlen(nickname)) { 37630a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 37730a5e8faSwyllys nickname, strlen(nickname)); 37830a5e8faSwyllys numattr++; 37930a5e8faSwyllys } 38030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 38130a5e8faSwyllys &keylen, sizeof (keylen)); 38230a5e8faSwyllys numattr++; 38399ebb4caSwyllys 38430a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 38530a5e8faSwyllys &keyAlg, sizeof (keyAlg)); 38630a5e8faSwyllys numattr++; 38730a5e8faSwyllys 38830a5e8faSwyllys if (tokencred != NULL && tokencred->credlen > 0) { 38930a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 39030a5e8faSwyllys tokencred, sizeof (KMF_CREDENTIAL)); 39130a5e8faSwyllys numattr++; 39230a5e8faSwyllys } 39330a5e8faSwyllys 39430a5e8faSwyllys if (token && strlen(token)) { 39530a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 39630a5e8faSwyllys token, strlen(token)); 39730a5e8faSwyllys numattr++; 39830a5e8faSwyllys } 39930a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 40030a5e8faSwyllys &pubk, sizeof (KMF_KEY_HANDLE)); 40130a5e8faSwyllys numattr++; 40230a5e8faSwyllys 40330a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 40430a5e8faSwyllys &prik, sizeof (KMF_KEY_HANDLE)); 40530a5e8faSwyllys numattr++; 40630a5e8faSwyllys 40730a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 40830a5e8faSwyllys &storekey, sizeof (storekey)); 40930a5e8faSwyllys numattr++; 41030a5e8faSwyllys 41130a5e8faSwyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 41299ebb4caSwyllys if (kmfrv != KMF_OK) { 41399ebb4caSwyllys goto cleanup; 41499ebb4caSwyllys } 41599ebb4caSwyllys 41630a5e8faSwyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), 41730a5e8faSwyllys "kmf_set_csr_pubkey"); 41830a5e8faSwyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version"); 41930a5e8faSwyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), 42030a5e8faSwyllys "kmf_set_csr_subject"); 42130a5e8faSwyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg"); 42299ebb4caSwyllys 42399ebb4caSwyllys if (altname != NULL) { 42430a5e8faSwyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 42530a5e8faSwyllys alttype), "kmf_set_csr_subject_altname"); 42699ebb4caSwyllys } 42799ebb4caSwyllys if (kubits != NULL) { 42830a5e8faSwyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 42930a5e8faSwyllys "kmf_set_csr_ku"); 43099ebb4caSwyllys } 431d00756ccSwyllys if (ekulist != NULL) { 432d00756ccSwyllys int i; 433d00756ccSwyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 434d00756ccSwyllys SET_VALUE(kmf_add_csr_eku(&csr, 435d00756ccSwyllys &ekulist->ekulist[i], 436d00756ccSwyllys ekulist->critlist[i]), 437d00756ccSwyllys "Extended Key Usage"); 438d00756ccSwyllys } 439d00756ccSwyllys } 44030a5e8faSwyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 44199ebb4caSwyllys KMF_OK) { 44230a5e8faSwyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile); 44399ebb4caSwyllys } 44499ebb4caSwyllys 44599ebb4caSwyllys cleanup: 44630a5e8faSwyllys (void) kmf_free_data(&signedCsr); 44730a5e8faSwyllys (void) kmf_free_kmf_key(kmfhandle, &prik); 44830a5e8faSwyllys 44999ebb4caSwyllys /* delete the key */ 45030a5e8faSwyllys numattr = 0; 45130a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 45230a5e8faSwyllys &kstype, sizeof (kstype)); 45330a5e8faSwyllys numattr++; 45430a5e8faSwyllys 45530a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 45630a5e8faSwyllys &pubk, sizeof (KMF_KEY_HANDLE)); 45730a5e8faSwyllys numattr++; 45830a5e8faSwyllys 45930a5e8faSwyllys if (tokencred != NULL && tokencred->credlen > 0) { 46030a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 46130a5e8faSwyllys tokencred, sizeof (KMF_CREDENTIAL)); 46230a5e8faSwyllys numattr++; 46330a5e8faSwyllys } 46430a5e8faSwyllys 46530a5e8faSwyllys if (token && strlen(token)) { 46630a5e8faSwyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 46730a5e8faSwyllys token, strlen(token)); 46830a5e8faSwyllys numattr++; 46930a5e8faSwyllys } 47030a5e8faSwyllys 47130a5e8faSwyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); 47230a5e8faSwyllys 47330a5e8faSwyllys (void) kmf_free_signed_csr(&csr); 47499ebb4caSwyllys 47599ebb4caSwyllys return (kmfrv); 47699ebb4caSwyllys } 47799ebb4caSwyllys 47899ebb4caSwyllys int 47999ebb4caSwyllys pk_gencsr(int argc, char *argv[]) 48099ebb4caSwyllys { 48199ebb4caSwyllys KMF_RETURN rv; 48299ebb4caSwyllys int opt; 48399ebb4caSwyllys extern int optind_av; 48499ebb4caSwyllys extern char *optarg_av; 48599ebb4caSwyllys KMF_KEYSTORE_TYPE kstype = 0; 48699ebb4caSwyllys char *subject = NULL; 48799ebb4caSwyllys char *tokenname = NULL; 48899ebb4caSwyllys char *dir = NULL; 48999ebb4caSwyllys char *prefix = NULL; 49099ebb4caSwyllys int keylen = PK_DEFAULT_KEYLENGTH; 49199ebb4caSwyllys char *certlabel = NULL; 49299ebb4caSwyllys char *outcsr = NULL; 49399ebb4caSwyllys char *outkey = NULL; 49499ebb4caSwyllys char *format = NULL; 49599ebb4caSwyllys char *altname = NULL; 49699ebb4caSwyllys char *kustr = NULL; 497d00756ccSwyllys char *ekustr = NULL; 49899ebb4caSwyllys uint16_t kubits = 0; 49999ebb4caSwyllys char *keytype = PK_DEFAULT_KEYTYPE; 50099ebb4caSwyllys KMF_HANDLE_T kmfhandle = NULL; 50199ebb4caSwyllys KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 50299ebb4caSwyllys KMF_KEY_ALG keyAlg = KMF_RSA; 50399ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 50499ebb4caSwyllys boolean_t interactive = B_FALSE; 50599ebb4caSwyllys char *subname = NULL; 50699ebb4caSwyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 50799ebb4caSwyllys KMF_GENERALNAMECHOICES alttype = 0; 50899ebb4caSwyllys int altcrit = 0, kucrit = 0; 509d00756ccSwyllys EKU_LIST *ekulist = NULL; 51099ebb4caSwyllys 51199ebb4caSwyllys while ((opt = getopt_av(argc, argv, 51299ebb4caSwyllys "ik:(keystore)s:(subject)n:(nickname)A:(altname)" 51399ebb4caSwyllys "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)" 514d00756ccSwyllys "y:(keylen)l:(label)c:(outcsr)e:(eku)" 51599ebb4caSwyllys "K:(outkey)F:(format)")) != EOF) { 51699ebb4caSwyllys 51799ebb4caSwyllys if (opt != 'i' && EMPTYSTRING(optarg_av)) 51899ebb4caSwyllys return (PK_ERR_USAGE); 51999ebb4caSwyllys 52099ebb4caSwyllys switch (opt) { 52199ebb4caSwyllys case 'A': 52299ebb4caSwyllys altname = optarg_av; 52399ebb4caSwyllys break; 52499ebb4caSwyllys case 'i': 52599ebb4caSwyllys if (interactive || subject) 52699ebb4caSwyllys return (PK_ERR_USAGE); 52799ebb4caSwyllys else 52899ebb4caSwyllys interactive = B_TRUE; 52999ebb4caSwyllys break; 53099ebb4caSwyllys case 'k': 53199ebb4caSwyllys kstype = KS2Int(optarg_av); 53299ebb4caSwyllys if (kstype == 0) 53399ebb4caSwyllys return (PK_ERR_USAGE); 53499ebb4caSwyllys break; 53599ebb4caSwyllys case 's': 53699ebb4caSwyllys if (interactive || subject) 53799ebb4caSwyllys return (PK_ERR_USAGE); 53899ebb4caSwyllys else 53999ebb4caSwyllys subject = optarg_av; 54099ebb4caSwyllys break; 54199ebb4caSwyllys case 'l': 54299ebb4caSwyllys case 'n': 54399ebb4caSwyllys if (certlabel) 54499ebb4caSwyllys return (PK_ERR_USAGE); 54599ebb4caSwyllys certlabel = optarg_av; 54699ebb4caSwyllys break; 54799ebb4caSwyllys case 'T': 54899ebb4caSwyllys if (tokenname) 54999ebb4caSwyllys return (PK_ERR_USAGE); 55099ebb4caSwyllys tokenname = optarg_av; 55199ebb4caSwyllys break; 55299ebb4caSwyllys case 'd': 55399ebb4caSwyllys dir = optarg_av; 55499ebb4caSwyllys break; 55599ebb4caSwyllys case 'p': 55699ebb4caSwyllys if (prefix) 55799ebb4caSwyllys return (PK_ERR_USAGE); 55899ebb4caSwyllys prefix = optarg_av; 55999ebb4caSwyllys break; 56099ebb4caSwyllys case 't': 56199ebb4caSwyllys keytype = optarg_av; 56299ebb4caSwyllys break; 56399ebb4caSwyllys case 'u': 56499ebb4caSwyllys kustr = optarg_av; 56599ebb4caSwyllys break; 56699ebb4caSwyllys case 'y': 56799ebb4caSwyllys if (sscanf(optarg_av, "%d", 56899ebb4caSwyllys &keylen) != 1) { 56999ebb4caSwyllys cryptoerror(LOG_STDERR, 57099ebb4caSwyllys gettext("Unrecognized " 57130a5e8faSwyllys "key length (%s)\n"), optarg_av); 57299ebb4caSwyllys return (PK_ERR_USAGE); 57399ebb4caSwyllys } 57499ebb4caSwyllys break; 57599ebb4caSwyllys case 'c': 57699ebb4caSwyllys if (outcsr) 57799ebb4caSwyllys return (PK_ERR_USAGE); 57899ebb4caSwyllys outcsr = optarg_av; 57999ebb4caSwyllys break; 58099ebb4caSwyllys case 'K': 58199ebb4caSwyllys if (outkey) 58299ebb4caSwyllys return (PK_ERR_USAGE); 58399ebb4caSwyllys outkey = optarg_av; 58499ebb4caSwyllys break; 58599ebb4caSwyllys case 'F': 58699ebb4caSwyllys if (format) 58799ebb4caSwyllys return (PK_ERR_USAGE); 58899ebb4caSwyllys format = optarg_av; 58999ebb4caSwyllys break; 590d00756ccSwyllys case 'e': 591d00756ccSwyllys ekustr = optarg_av; 592d00756ccSwyllys break; 59399ebb4caSwyllys default: 59499ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 59599ebb4caSwyllys "unrecognized gencsr option '%s'\n"), 59699ebb4caSwyllys argv[optind_av]); 59799ebb4caSwyllys return (PK_ERR_USAGE); 59899ebb4caSwyllys } 59999ebb4caSwyllys } 60099ebb4caSwyllys /* No additional args allowed. */ 60199ebb4caSwyllys argc -= optind_av; 60299ebb4caSwyllys argv += optind_av; 60399ebb4caSwyllys if (argc) { 60499ebb4caSwyllys return (PK_ERR_USAGE); 60599ebb4caSwyllys } 60699ebb4caSwyllys 60730a5e8faSwyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 60899ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 60999ebb4caSwyllys return (PK_ERR_USAGE); 61099ebb4caSwyllys } 61199ebb4caSwyllys 61299ebb4caSwyllys /* Assume keystore = PKCS#11 if not specified. */ 61399ebb4caSwyllys if (kstype == 0) 61499ebb4caSwyllys kstype = KMF_KEYSTORE_PK11TOKEN; 61599ebb4caSwyllys 6162cbed729Swyllys if (EMPTYSTRING(outcsr) && interactive) { 6172cbed729Swyllys (void) get_filename("CSR", &outcsr); 6182cbed729Swyllys } 61999ebb4caSwyllys if (EMPTYSTRING(outcsr)) { 62099ebb4caSwyllys (void) printf(gettext("A filename must be specified to hold" 62199ebb4caSwyllys "the final certificate request data.\n")); 62299ebb4caSwyllys return (PK_ERR_USAGE); 6232cbed729Swyllys } 62499ebb4caSwyllys /* 62599ebb4caSwyllys * verify that the outcsr file does not already exist 62699ebb4caSwyllys * and that it can be created. 62799ebb4caSwyllys */ 62899ebb4caSwyllys rv = verify_file(outcsr); 62999ebb4caSwyllys if (rv != KMF_OK) { 63099ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("output file (%s) " 63199ebb4caSwyllys "cannot be created.\n"), outcsr); 63299ebb4caSwyllys return (PK_ERR_USAGE); 63399ebb4caSwyllys } 63499ebb4caSwyllys 6352cbed729Swyllys if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) { 6362cbed729Swyllys if (EMPTYSTRING(certlabel) && interactive) 6372cbed729Swyllys (void) get_certlabel(&certlabel); 6382cbed729Swyllys 6392cbed729Swyllys if (EMPTYSTRING(certlabel)) { 6402cbed729Swyllys cryptoerror(LOG_STDERR, gettext("A label must be " 64199ebb4caSwyllys "specified to create a certificate request.\n")); 64299ebb4caSwyllys return (PK_ERR_USAGE); 64399ebb4caSwyllys } 6442cbed729Swyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) { 6452cbed729Swyllys if (EMPTYSTRING(outkey) && interactive) 6462cbed729Swyllys (void) get_filename("private key", &outkey); 6472cbed729Swyllys 6482cbed729Swyllys if (EMPTYSTRING(outkey)) { 6492cbed729Swyllys cryptoerror(LOG_STDERR, gettext("A key filename " 6502cbed729Swyllys "must be specified to create a certificate " 6512cbed729Swyllys "request.\n")); 6522cbed729Swyllys return (PK_ERR_USAGE); 6532cbed729Swyllys } 6542cbed729Swyllys } 65599ebb4caSwyllys 65699ebb4caSwyllys if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 65799ebb4caSwyllys cryptoerror(LOG_STDERR, 65830a5e8faSwyllys gettext("Error parsing format string (%s).\n"), format); 65999ebb4caSwyllys return (PK_ERR_USAGE); 66099ebb4caSwyllys } 66199ebb4caSwyllys if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) { 66299ebb4caSwyllys cryptoerror(LOG_STDERR, 66399ebb4caSwyllys gettext("CSR must be DER or PEM format.\n")); 66499ebb4caSwyllys return (PK_ERR_USAGE); 66599ebb4caSwyllys } 66699ebb4caSwyllys 66799ebb4caSwyllys /* 66899ebb4caSwyllys * Check the subject name. 66999ebb4caSwyllys * If interactive is true, get it now interactively. 67099ebb4caSwyllys */ 67199ebb4caSwyllys if (interactive) { 67299ebb4caSwyllys if (get_subname(&subname) != KMF_OK) { 67399ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Failed to get the " 67499ebb4caSwyllys "subject name interactively.\n")); 67599ebb4caSwyllys return (PK_ERR_USAGE); 67699ebb4caSwyllys } 67799ebb4caSwyllys } else { 67899ebb4caSwyllys if (EMPTYSTRING(subject)) { 67999ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("A subject name or " 68099ebb4caSwyllys "-i must be specified to create a certificate " 68199ebb4caSwyllys "request.\n")); 68299ebb4caSwyllys return (PK_ERR_USAGE); 68399ebb4caSwyllys } else { 68499ebb4caSwyllys subname = strdup(subject); 68599ebb4caSwyllys if (subname == NULL) { 68699ebb4caSwyllys cryptoerror(LOG_STDERR, 68799ebb4caSwyllys gettext("Out of memory.\n")); 68899ebb4caSwyllys return (PK_ERR_SYSTEM); 68999ebb4caSwyllys } 69099ebb4caSwyllys } 69199ebb4caSwyllys } 69299ebb4caSwyllys if (altname != NULL) { 69399ebb4caSwyllys rv = verify_altname(altname, &alttype, &altcrit); 69499ebb4caSwyllys if (rv != KMF_OK) { 69599ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Subject AltName " 69699ebb4caSwyllys "must be specified as a name=value pair. " 69799ebb4caSwyllys "See the man page for details.")); 69899ebb4caSwyllys goto end; 69999ebb4caSwyllys } else { 70099ebb4caSwyllys /* advance the altname past the '=' sign */ 70199ebb4caSwyllys char *p = strchr(altname, '='); 70299ebb4caSwyllys if (p != NULL) 70399ebb4caSwyllys altname = p + 1; 70499ebb4caSwyllys } 70599ebb4caSwyllys } 70699ebb4caSwyllys 70799ebb4caSwyllys if (kustr != NULL) { 70899ebb4caSwyllys rv = verify_keyusage(kustr, &kubits, &kucrit); 70999ebb4caSwyllys if (rv != KMF_OK) { 71099ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("KeyUsage " 71199ebb4caSwyllys "must be specified as a comma-separated list. " 71299ebb4caSwyllys "See the man page for details.")); 71399ebb4caSwyllys goto end; 71499ebb4caSwyllys } 71599ebb4caSwyllys } 716d00756ccSwyllys if (ekustr != NULL) { 717d00756ccSwyllys rv = verify_ekunames(ekustr, &ekulist); 718d00756ccSwyllys if (rv != KMF_OK) { 719d00756ccSwyllys (void) fprintf(stderr, gettext("EKUs must " 720d00756ccSwyllys "be specified as a comma-separated list. " 721d00756ccSwyllys "See the man page for details.\n")); 722d00756ccSwyllys rv = PK_ERR_USAGE; 723d00756ccSwyllys goto end; 724d00756ccSwyllys } 725d00756ccSwyllys } 726d00756ccSwyllys 727d00756ccSwyllys 72899ebb4caSwyllys if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) { 72999ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 73099ebb4caSwyllys keytype); 73199ebb4caSwyllys goto end; 73299ebb4caSwyllys } 73399ebb4caSwyllys 73499ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 73599ebb4caSwyllys if (tokenname == NULL || !strlen(tokenname)) { 73699ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS) { 73799ebb4caSwyllys tokenname = "internal"; 73899ebb4caSwyllys } else { 73999ebb4caSwyllys tokenname = PK_DEFAULT_PK11TOKEN; 74099ebb4caSwyllys } 74199ebb4caSwyllys } 74299ebb4caSwyllys 74399ebb4caSwyllys (void) get_token_password(kstype, tokenname, &tokencred); 74499ebb4caSwyllys } 74599ebb4caSwyllys 74699ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS) { 74799ebb4caSwyllys if (dir == NULL) 74899ebb4caSwyllys dir = PK_DEFAULT_DIRECTORY; 74999ebb4caSwyllys 75099ebb4caSwyllys rv = gencsr_nss(kmfhandle, 75199ebb4caSwyllys tokenname, subname, altname, alttype, altcrit, 75299ebb4caSwyllys certlabel, dir, prefix, 75399ebb4caSwyllys keyAlg, keylen, kubits, kucrit, 754d00756ccSwyllys fmt, outcsr, &tokencred, ekulist); 75599ebb4caSwyllys 75699ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 75799ebb4caSwyllys rv = gencsr_pkcs11(kmfhandle, 75899ebb4caSwyllys tokenname, subname, altname, alttype, altcrit, 75999ebb4caSwyllys certlabel, keyAlg, keylen, 760d00756ccSwyllys kubits, kucrit, fmt, outcsr, &tokencred, ekulist); 76199ebb4caSwyllys 76299ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) { 76399ebb4caSwyllys rv = gencsr_file(kmfhandle, 76499ebb4caSwyllys keyAlg, keylen, fmt, subname, altname, 76599ebb4caSwyllys alttype, altcrit, kubits, kucrit, 766*448b8615Swyllys outcsr, outkey, ekulist); 76799ebb4caSwyllys } 76899ebb4caSwyllys 76999ebb4caSwyllys end: 77099ebb4caSwyllys if (rv != KMF_OK) 77199ebb4caSwyllys display_error(kmfhandle, rv, 77299ebb4caSwyllys gettext("Error creating CSR or keypair")); 77399ebb4caSwyllys 774d00756ccSwyllys if (ekulist != NULL) 775d00756ccSwyllys free_eku_list(ekulist); 776d00756ccSwyllys 77799ebb4caSwyllys if (subname) 77899ebb4caSwyllys free(subname); 77999ebb4caSwyllys 78099ebb4caSwyllys if (tokencred.cred != NULL) 78199ebb4caSwyllys free(tokencred.cred); 78299ebb4caSwyllys 78330a5e8faSwyllys (void) kmf_finalize(kmfhandle); 78499ebb4caSwyllys if (rv != KMF_OK) 78599ebb4caSwyllys return (PK_ERR_USAGE); 78699ebb4caSwyllys 78799ebb4caSwyllys return (0); 78899ebb4caSwyllys } 789