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 * 213089Swyllys * 229145SHuie-Ying.Lee@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 233089Swyllys * Use is subject to license terms. 243089Swyllys */ 253089Swyllys 263089Swyllys #include <stdio.h> 273089Swyllys #include <string.h> 283089Swyllys #include <ctype.h> 293089Swyllys #include <malloc.h> 303089Swyllys #include <libgen.h> 313089Swyllys #include <errno.h> 323089Swyllys #include <cryptoutil.h> 333089Swyllys #include <security/cryptoki.h> 343089Swyllys #include "common.h" 353089Swyllys 363089Swyllys #include <kmfapi.h> 373089Swyllys 383089Swyllys #define SET_VALUE(f, s) \ 393089Swyllys kmfrv = f; \ 403089Swyllys if (kmfrv != KMF_OK) { \ 413089Swyllys cryptoerror(LOG_STDERR, \ 423089Swyllys gettext("Failed to %s: 0x%02\n"), \ 433089Swyllys s, kmfrv); \ 443089Swyllys goto cleanup; \ 453089Swyllys } 463089Swyllys 473089Swyllys static KMF_RETURN 483089Swyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle, 493089Swyllys char *token, char *subject, char *altname, 503089Swyllys KMF_GENERALNAMECHOICES alttype, int altcrit, 513089Swyllys char *certlabel, KMF_KEY_ALG keyAlg, 526051Swyllys int keylen, uint16_t kubits, int kucrit, 533089Swyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 546051Swyllys KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist) 553089Swyllys { 563089Swyllys KMF_RETURN kmfrv = KMF_OK; 573089Swyllys KMF_KEY_HANDLE pubk, prik; 583089Swyllys KMF_X509_NAME csrSubject; 593089Swyllys KMF_CSR_DATA csr; 603089Swyllys KMF_ALGORITHM_INDEX sigAlg; 613089Swyllys KMF_DATA signedCsr = {NULL, 0}; 623089Swyllys 635051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 645051Swyllys int numattr = 0; 655051Swyllys KMF_ATTRIBUTE attrlist[16]; 665051Swyllys boolean_t storekey = TRUE; 675051Swyllys 683089Swyllys (void) memset(&csr, 0, sizeof (csr)); 693089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 703089Swyllys 713089Swyllys if (keyAlg == KMF_DSA) 723089Swyllys sigAlg = KMF_ALGID_SHA1WithDSA; 733089Swyllys else 743089Swyllys sigAlg = KMF_ALGID_MD5WithRSA; 753089Swyllys 763089Swyllys 773089Swyllys /* If the subject name cannot be parsed, flag it now and exit */ 785051Swyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 793089Swyllys return (kmfrv); 803089Swyllys } 813089Swyllys 823089Swyllys /* Select a PKCS11 token */ 833089Swyllys kmfrv = select_token(kmfhandle, token, FALSE); 843089Swyllys if (kmfrv != KMF_OK) { 853089Swyllys return (kmfrv); 863089Swyllys } 873089Swyllys 885051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 895051Swyllys &kstype, sizeof (kstype)); 905051Swyllys numattr++; 915051Swyllys 925051Swyllys if (certlabel != NULL && strlen(certlabel)) { 935051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 945051Swyllys certlabel, strlen(certlabel)); 955051Swyllys numattr++; 965051Swyllys } 975051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 985051Swyllys &keylen, sizeof (keylen)); 995051Swyllys numattr++; 1005051Swyllys 1015051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 1025051Swyllys &keyAlg, sizeof (keyAlg)); 1035051Swyllys numattr++; 1045051Swyllys 1055051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 1065051Swyllys tokencred, sizeof (KMF_CREDENTIAL)); 1075051Swyllys numattr++; 1085051Swyllys 1095051Swyllys if (token && strlen(token)) { 1105051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 1115051Swyllys token, strlen(token)); 1125051Swyllys numattr++; 1135051Swyllys } 1145051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 1155051Swyllys &pubk, sizeof (KMF_KEY_HANDLE)); 1165051Swyllys numattr++; 1175051Swyllys 1185051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 1195051Swyllys &prik, sizeof (KMF_KEY_HANDLE)); 1205051Swyllys numattr++; 1215051Swyllys 1225051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 1235051Swyllys &storekey, sizeof (storekey)); 1245051Swyllys numattr++; 1255051Swyllys 1265051Swyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 1273089Swyllys if (kmfrv != KMF_OK) { 1283089Swyllys return (kmfrv); 1293089Swyllys } 1303089Swyllys 1315051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair"); 1323089Swyllys 1335051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "version number"); 1343089Swyllys 1355051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name"); 1363089Swyllys 1375051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), 1385051Swyllys "SignatureAlgorithm"); 1393089Swyllys 1403089Swyllys if (altname != NULL) { 1415051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 1425051Swyllys alttype), "SetCSRSubjectAltName"); 1433089Swyllys } 1443089Swyllys 1453089Swyllys if (kubits != 0) { 1465051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 1475051Swyllys "SetCSRKeyUsage"); 1483089Swyllys } 1496051Swyllys if (ekulist != NULL) { 1506051Swyllys int i; 1516051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 1526051Swyllys SET_VALUE(kmf_add_csr_eku(&csr, 1536051Swyllys &ekulist->ekulist[i], 1546051Swyllys ekulist->critlist[i]), 1556051Swyllys "Extended Key Usage"); 1566051Swyllys } 1576051Swyllys } 1585051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 1595051Swyllys KMF_OK) { 1605051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile); 1613089Swyllys } 1623089Swyllys 1633089Swyllys cleanup: 1645051Swyllys (void) kmf_free_data(&signedCsr); 1659145SHuie-Ying.Lee@Sun.COM (void) kmf_free_signed_csr(&csr); 1669145SHuie-Ying.Lee@Sun.COM 1679145SHuie-Ying.Lee@Sun.COM /* delete the public key */ 1685051Swyllys numattr = 0; 1695051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 1705051Swyllys &kstype, sizeof (kstype)); 1715051Swyllys numattr++; 1725051Swyllys 1735051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 1745051Swyllys &pubk, sizeof (KMF_KEY_HANDLE)); 1755051Swyllys numattr++; 1765051Swyllys 1779145SHuie-Ying.Lee@Sun.COM if (tokencred != NULL && tokencred->cred != NULL) { 1789145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 1799145SHuie-Ying.Lee@Sun.COM tokencred, sizeof (KMF_CREDENTIAL)); 1809145SHuie-Ying.Lee@Sun.COM numattr++; 1819145SHuie-Ying.Lee@Sun.COM } 1829145SHuie-Ying.Lee@Sun.COM 1835051Swyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); 1845051Swyllys 1859145SHuie-Ying.Lee@Sun.COM /* 1869145SHuie-Ying.Lee@Sun.COM * If there is an error, then we need to remove the private key 1879145SHuie-Ying.Lee@Sun.COM * from the token. 1889145SHuie-Ying.Lee@Sun.COM */ 1899145SHuie-Ying.Lee@Sun.COM if (kmfrv != KMF_OK) { 1909145SHuie-Ying.Lee@Sun.COM numattr = 0; 1919145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr, 1929145SHuie-Ying.Lee@Sun.COM KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1939145SHuie-Ying.Lee@Sun.COM numattr++; 1943089Swyllys 1959145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr, 1969145SHuie-Ying.Lee@Sun.COM KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE)); 1979145SHuie-Ying.Lee@Sun.COM numattr++; 1989145SHuie-Ying.Lee@Sun.COM 1999145SHuie-Ying.Lee@Sun.COM if (tokencred != NULL && tokencred->cred != NULL) { 2009145SHuie-Ying.Lee@Sun.COM kmf_set_attr_at_index(attrlist, numattr, 2019145SHuie-Ying.Lee@Sun.COM KMF_CREDENTIAL_ATTR, tokencred, 2029145SHuie-Ying.Lee@Sun.COM sizeof (KMF_CREDENTIAL)); 2039145SHuie-Ying.Lee@Sun.COM numattr++; 2049145SHuie-Ying.Lee@Sun.COM } 2059145SHuie-Ying.Lee@Sun.COM 2069145SHuie-Ying.Lee@Sun.COM (void) kmf_delete_key_from_keystore(kmfhandle, numattr, 2079145SHuie-Ying.Lee@Sun.COM attrlist); 2089145SHuie-Ying.Lee@Sun.COM } 2099145SHuie-Ying.Lee@Sun.COM 2109145SHuie-Ying.Lee@Sun.COM (void) kmf_free_kmf_key(kmfhandle, &prik); 2113089Swyllys return (kmfrv); 2123089Swyllys } 2133089Swyllys 2143089Swyllys static KMF_RETURN 2153089Swyllys gencsr_file(KMF_HANDLE_T kmfhandle, 2163089Swyllys KMF_KEY_ALG keyAlg, 2173089Swyllys int keylen, KMF_ENCODE_FORMAT fmt, 2183089Swyllys char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, 2193089Swyllys int altcrit, uint16_t kubits, int kucrit, 2206669Swyllys char *outcsr, char *outkey, EKU_LIST *ekulist) 2213089Swyllys { 2223089Swyllys KMF_RETURN kmfrv; 2233089Swyllys KMF_KEY_HANDLE pubk, prik; 2243089Swyllys KMF_X509_NAME csrSubject; 2253089Swyllys KMF_CSR_DATA csr; 2263089Swyllys KMF_ALGORITHM_INDEX sigAlg; 2273089Swyllys KMF_DATA signedCsr = {NULL, 0}; 2283089Swyllys char *fullcsrpath = NULL; 2293089Swyllys char *fullkeypath = NULL; 2303089Swyllys 2315051Swyllys int numattr = 0; 2325051Swyllys KMF_ATTRIBUTE attrlist[16]; 2335051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 2345051Swyllys boolean_t storekey = TRUE; 2355051Swyllys 2363089Swyllys (void) memset(&csr, 0, sizeof (csr)); 2373089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 2383089Swyllys 2393089Swyllys if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) { 2403089Swyllys cryptoerror(LOG_STDERR, 2415051Swyllys gettext("No output file was specified for " 2425051Swyllys "the csr or key\n")); 2433089Swyllys return (KMF_ERR_BAD_PARAMETER); 2443089Swyllys } 2456669Swyllys fullcsrpath = strdup(outcsr); 2463089Swyllys if (verify_file(fullcsrpath)) { 2473089Swyllys cryptoerror(LOG_STDERR, 2485051Swyllys gettext("Cannot write the indicated output " 2495051Swyllys "certificate file (%s).\n"), fullcsrpath); 2503089Swyllys free(fullcsrpath); 2513089Swyllys return (PK_ERR_USAGE); 2523089Swyllys } 2536669Swyllys 2546669Swyllys fullkeypath = strdup(outkey); 2553089Swyllys if (verify_file(fullcsrpath)) { 2563089Swyllys cryptoerror(LOG_STDERR, 2575051Swyllys gettext("Cannot write the indicated output " 2585051Swyllys "key file (%s).\n"), fullkeypath); 2593089Swyllys free(fullcsrpath); 2603089Swyllys return (PK_ERR_USAGE); 2613089Swyllys } 2623089Swyllys 2633089Swyllys if (keyAlg == KMF_DSA) 2643089Swyllys sigAlg = KMF_ALGID_SHA1WithDSA; 2653089Swyllys else 2663089Swyllys sigAlg = KMF_ALGID_MD5WithRSA; 2673089Swyllys 2683089Swyllys /* If the subject name cannot be parsed, flag it now and exit */ 2695051Swyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 2703089Swyllys return (kmfrv); 2713089Swyllys } 2723089Swyllys 2735051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 2745051Swyllys &kstype, sizeof (kstype)); 2755051Swyllys numattr++; 2765051Swyllys 2775051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 2785051Swyllys fullkeypath, strlen(fullkeypath)); 2795051Swyllys numattr++; 2805051Swyllys 2815051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 2825051Swyllys &keylen, sizeof (keylen)); 2835051Swyllys numattr++; 2845051Swyllys 2855051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 2865051Swyllys &keyAlg, sizeof (keyAlg)); 2875051Swyllys numattr++; 2883089Swyllys 2895051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 2905051Swyllys &fmt, sizeof (fmt)); 2915051Swyllys numattr++; 2925051Swyllys 2935051Swyllys (void) memset(&prik, 0, sizeof (prik)); 2945051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 2955051Swyllys &prik, sizeof (KMF_KEY_HANDLE)); 2965051Swyllys numattr++; 2973089Swyllys 2985051Swyllys (void) memset(&pubk, 0, sizeof (pubk)); 2995051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 3005051Swyllys &pubk, sizeof (KMF_KEY_HANDLE)); 3015051Swyllys numattr++; 3025051Swyllys 3035051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 3045051Swyllys &storekey, sizeof (storekey)); 3055051Swyllys numattr++; 3065051Swyllys 3075051Swyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 3083089Swyllys if (kmfrv != KMF_OK) { 3093089Swyllys goto cleanup; 3103089Swyllys } 3115051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), 3125051Swyllys "SetCSRPubKey"); 3133089Swyllys 3145051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion"); 3153089Swyllys 3165051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), 3175051Swyllys "kmf_set_csr_subject"); 3183089Swyllys 3195051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg"); 3203089Swyllys 3213089Swyllys if (altname != NULL) { 3225051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 3235051Swyllys alttype), "kmf_set_csr_subject_altname"); 3243089Swyllys } 3253089Swyllys if (kubits != NULL) { 3265051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 3275051Swyllys "kmf_set_csr_ku"); 3283089Swyllys } 3296051Swyllys if (ekulist != NULL) { 3306051Swyllys int i; 3316051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 3326051Swyllys SET_VALUE(kmf_add_csr_eku(&csr, 3336051Swyllys &ekulist->ekulist[i], 3346051Swyllys ekulist->critlist[i]), 3356051Swyllys "Extended Key Usage"); 3366051Swyllys } 3376051Swyllys } 3385051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 3395051Swyllys KMF_OK) { 3405051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath); 3413089Swyllys } 3423089Swyllys 3433089Swyllys cleanup: 3443089Swyllys if (fullkeypath) 3453089Swyllys free(fullkeypath); 3463089Swyllys if (fullcsrpath) 3473089Swyllys free(fullcsrpath); 3483089Swyllys 3495051Swyllys kmf_free_data(&signedCsr); 3505051Swyllys kmf_free_kmf_key(kmfhandle, &prik); 3515051Swyllys kmf_free_signed_csr(&csr); 3523089Swyllys 3533089Swyllys return (kmfrv); 3543089Swyllys } 3553089Swyllys 3563089Swyllys static KMF_RETURN 3573089Swyllys gencsr_nss(KMF_HANDLE_T kmfhandle, 3583089Swyllys char *token, char *subject, char *altname, 3593089Swyllys KMF_GENERALNAMECHOICES alttype, int altcrit, 3603089Swyllys char *nickname, char *dir, char *prefix, 3613089Swyllys KMF_KEY_ALG keyAlg, int keylen, 3623089Swyllys uint16_t kubits, int kucrit, 3633089Swyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 3646051Swyllys KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist) 3653089Swyllys { 3663089Swyllys KMF_RETURN kmfrv; 3673089Swyllys KMF_KEY_HANDLE pubk, prik; 3683089Swyllys KMF_X509_NAME csrSubject; 3693089Swyllys KMF_CSR_DATA csr; 3703089Swyllys KMF_ALGORITHM_INDEX sigAlg; 3713089Swyllys KMF_DATA signedCsr = {NULL, 0}; 3725051Swyllys 3735051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 3745051Swyllys int numattr = 0; 3755051Swyllys KMF_ATTRIBUTE attrlist[16]; 3765051Swyllys boolean_t storekey = TRUE; 3773089Swyllys 3783089Swyllys if (token == NULL) 3793089Swyllys token = DEFAULT_NSS_TOKEN; 3803089Swyllys 3813089Swyllys if (keyAlg == KMF_DSA) 3823089Swyllys sigAlg = KMF_ALGID_SHA1WithDSA; 3833089Swyllys else 3843089Swyllys sigAlg = KMF_ALGID_MD5WithRSA; 3853089Swyllys 3863089Swyllys kmfrv = configure_nss(kmfhandle, dir, prefix); 3873089Swyllys if (kmfrv != KMF_OK) 3883089Swyllys return (kmfrv); 3893089Swyllys 3903089Swyllys (void) memset(&csr, 0, sizeof (csr)); 3913089Swyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 3926669Swyllys (void) memset(&pubk, 0, sizeof (pubk)); 3936669Swyllys (void) memset(&prik, 0, sizeof (prik)); 3943089Swyllys 3953089Swyllys /* If the subject name cannot be parsed, flag it now and exit */ 3965051Swyllys if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { 3973089Swyllys return (kmfrv); 3983089Swyllys } 3993089Swyllys 4005051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4015051Swyllys &kstype, sizeof (kstype)); 4025051Swyllys numattr++; 4035051Swyllys 4045051Swyllys if (nickname != NULL && strlen(nickname)) { 4055051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 4065051Swyllys nickname, strlen(nickname)); 4075051Swyllys numattr++; 4085051Swyllys } 4095051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR, 4105051Swyllys &keylen, sizeof (keylen)); 4115051Swyllys numattr++; 4125051Swyllys 4135051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR, 4145051Swyllys &keyAlg, sizeof (keyAlg)); 4155051Swyllys numattr++; 4163089Swyllys 4175051Swyllys if (tokencred != NULL && tokencred->credlen > 0) { 4185051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4195051Swyllys tokencred, sizeof (KMF_CREDENTIAL)); 4205051Swyllys numattr++; 4215051Swyllys } 4223089Swyllys 4235051Swyllys if (token && strlen(token)) { 4245051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 4255051Swyllys token, strlen(token)); 4265051Swyllys numattr++; 4275051Swyllys } 4285051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 4295051Swyllys &pubk, sizeof (KMF_KEY_HANDLE)); 4305051Swyllys numattr++; 4315051Swyllys 4325051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR, 4335051Swyllys &prik, sizeof (KMF_KEY_HANDLE)); 4345051Swyllys numattr++; 4355051Swyllys 4365051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR, 4375051Swyllys &storekey, sizeof (storekey)); 4385051Swyllys numattr++; 4395051Swyllys 4405051Swyllys kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 4413089Swyllys if (kmfrv != KMF_OK) { 4423089Swyllys goto cleanup; 4433089Swyllys } 4443089Swyllys 4455051Swyllys SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), 4465051Swyllys "kmf_set_csr_pubkey"); 4475051Swyllys SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version"); 4485051Swyllys SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), 4495051Swyllys "kmf_set_csr_subject"); 4505051Swyllys SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg"); 4513089Swyllys 4523089Swyllys if (altname != NULL) { 4535051Swyllys SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, 4545051Swyllys alttype), "kmf_set_csr_subject_altname"); 4553089Swyllys } 4563089Swyllys if (kubits != NULL) { 4575051Swyllys SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), 4585051Swyllys "kmf_set_csr_ku"); 4593089Swyllys } 4606051Swyllys if (ekulist != NULL) { 4616051Swyllys int i; 4626051Swyllys for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { 4636051Swyllys SET_VALUE(kmf_add_csr_eku(&csr, 4646051Swyllys &ekulist->ekulist[i], 4656051Swyllys ekulist->critlist[i]), 4666051Swyllys "Extended Key Usage"); 4676051Swyllys } 4686051Swyllys } 4695051Swyllys if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 4705051Swyllys KMF_OK) { 4715051Swyllys kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile); 4723089Swyllys } 4733089Swyllys 4743089Swyllys cleanup: 4755051Swyllys (void) kmf_free_data(&signedCsr); 4765051Swyllys (void) kmf_free_kmf_key(kmfhandle, &prik); 4775051Swyllys 4783089Swyllys /* delete the key */ 4795051Swyllys numattr = 0; 4805051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4815051Swyllys &kstype, sizeof (kstype)); 4825051Swyllys numattr++; 4835051Swyllys 4845051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR, 4855051Swyllys &pubk, sizeof (KMF_KEY_HANDLE)); 4865051Swyllys numattr++; 4875051Swyllys 4885051Swyllys if (tokencred != NULL && tokencred->credlen > 0) { 4895051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4905051Swyllys tokencred, sizeof (KMF_CREDENTIAL)); 4915051Swyllys numattr++; 4925051Swyllys } 4935051Swyllys 4945051Swyllys if (token && strlen(token)) { 4955051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 4965051Swyllys token, strlen(token)); 4975051Swyllys numattr++; 4985051Swyllys } 4995051Swyllys 5005051Swyllys (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); 5015051Swyllys 5025051Swyllys (void) kmf_free_signed_csr(&csr); 5033089Swyllys 5043089Swyllys return (kmfrv); 5053089Swyllys } 5063089Swyllys 5073089Swyllys int 5083089Swyllys pk_gencsr(int argc, char *argv[]) 5093089Swyllys { 5103089Swyllys KMF_RETURN rv; 5113089Swyllys int opt; 5123089Swyllys extern int optind_av; 5133089Swyllys extern char *optarg_av; 5143089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 5153089Swyllys char *subject = NULL; 5163089Swyllys char *tokenname = NULL; 5173089Swyllys char *dir = NULL; 5183089Swyllys char *prefix = NULL; 5193089Swyllys int keylen = PK_DEFAULT_KEYLENGTH; 5203089Swyllys char *certlabel = NULL; 5213089Swyllys char *outcsr = NULL; 5223089Swyllys char *outkey = NULL; 5233089Swyllys char *format = NULL; 5243089Swyllys char *altname = NULL; 5253089Swyllys char *kustr = NULL; 5266051Swyllys char *ekustr = NULL; 5273089Swyllys uint16_t kubits = 0; 5283089Swyllys char *keytype = PK_DEFAULT_KEYTYPE; 5293089Swyllys KMF_HANDLE_T kmfhandle = NULL; 5303089Swyllys KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 5313089Swyllys KMF_KEY_ALG keyAlg = KMF_RSA; 5323089Swyllys KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 5333089Swyllys boolean_t interactive = B_FALSE; 5343089Swyllys char *subname = NULL; 5353089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 5363089Swyllys KMF_GENERALNAMECHOICES alttype = 0; 5373089Swyllys int altcrit = 0, kucrit = 0; 5386051Swyllys EKU_LIST *ekulist = NULL; 5393089Swyllys 5403089Swyllys while ((opt = getopt_av(argc, argv, 5415051Swyllys "ik:(keystore)s:(subject)n:(nickname)A:(altname)" 5425051Swyllys "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)" 5436051Swyllys "y:(keylen)l:(label)c:(outcsr)e:(eku)" 5445051Swyllys "K:(outkey)F:(format)")) != EOF) { 5453089Swyllys 5463089Swyllys if (opt != 'i' && EMPTYSTRING(optarg_av)) 5473089Swyllys return (PK_ERR_USAGE); 5483089Swyllys 5493089Swyllys switch (opt) { 5503089Swyllys case 'A': 5513089Swyllys altname = optarg_av; 5523089Swyllys break; 5533089Swyllys case 'i': 554*10241Swyllys.ingersoll@sun.com if (interactive) 5553089Swyllys return (PK_ERR_USAGE); 556*10241Swyllys.ingersoll@sun.com else if (subject) { 557*10241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, 558*10241Swyllys.ingersoll@sun.com gettext("Interactive (-i) and " 559*10241Swyllys.ingersoll@sun.com "subject options are mutually " 560*10241Swyllys.ingersoll@sun.com "exclusive.\n")); 561*10241Swyllys.ingersoll@sun.com return (PK_ERR_USAGE); 562*10241Swyllys.ingersoll@sun.com } else 5633089Swyllys interactive = B_TRUE; 5643089Swyllys break; 5653089Swyllys case 'k': 5663089Swyllys kstype = KS2Int(optarg_av); 5673089Swyllys if (kstype == 0) 5683089Swyllys return (PK_ERR_USAGE); 5693089Swyllys break; 5703089Swyllys case 's': 571*10241Swyllys.ingersoll@sun.com if (subject) 5723089Swyllys return (PK_ERR_USAGE); 573*10241Swyllys.ingersoll@sun.com else if (interactive) { 574*10241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, 575*10241Swyllys.ingersoll@sun.com gettext("Interactive (-i) and " 576*10241Swyllys.ingersoll@sun.com "subject options are mutually " 577*10241Swyllys.ingersoll@sun.com "exclusive.\n")); 578*10241Swyllys.ingersoll@sun.com return (PK_ERR_USAGE); 579*10241Swyllys.ingersoll@sun.com } else 5803089Swyllys subject = optarg_av; 5813089Swyllys break; 5823089Swyllys case 'l': 5833089Swyllys case 'n': 5843089Swyllys if (certlabel) 5853089Swyllys return (PK_ERR_USAGE); 5863089Swyllys certlabel = optarg_av; 5873089Swyllys break; 5883089Swyllys case 'T': 5893089Swyllys if (tokenname) 5903089Swyllys return (PK_ERR_USAGE); 5913089Swyllys tokenname = optarg_av; 5923089Swyllys break; 5933089Swyllys case 'd': 5943089Swyllys dir = optarg_av; 5953089Swyllys break; 5963089Swyllys case 'p': 5973089Swyllys if (prefix) 5983089Swyllys return (PK_ERR_USAGE); 5993089Swyllys prefix = optarg_av; 6003089Swyllys break; 6013089Swyllys case 't': 6023089Swyllys keytype = optarg_av; 6033089Swyllys break; 6043089Swyllys case 'u': 6053089Swyllys kustr = optarg_av; 6063089Swyllys break; 6073089Swyllys case 'y': 6083089Swyllys if (sscanf(optarg_av, "%d", 6095051Swyllys &keylen) != 1) { 6103089Swyllys cryptoerror(LOG_STDERR, 6115051Swyllys gettext("Unrecognized " 6125051Swyllys "key length (%s)\n"), optarg_av); 6133089Swyllys return (PK_ERR_USAGE); 6143089Swyllys } 6153089Swyllys break; 6163089Swyllys case 'c': 6173089Swyllys if (outcsr) 6183089Swyllys return (PK_ERR_USAGE); 6193089Swyllys outcsr = optarg_av; 6203089Swyllys break; 6213089Swyllys case 'K': 6223089Swyllys if (outkey) 6233089Swyllys return (PK_ERR_USAGE); 6243089Swyllys outkey = optarg_av; 6253089Swyllys break; 6263089Swyllys case 'F': 6273089Swyllys if (format) 6283089Swyllys return (PK_ERR_USAGE); 6293089Swyllys format = optarg_av; 6303089Swyllys break; 6316051Swyllys case 'e': 6326051Swyllys ekustr = optarg_av; 6336051Swyllys break; 6343089Swyllys default: 6353089Swyllys cryptoerror(LOG_STDERR, gettext( 6365051Swyllys "unrecognized gencsr option '%s'\n"), 6375051Swyllys argv[optind_av]); 6383089Swyllys return (PK_ERR_USAGE); 6393089Swyllys } 6403089Swyllys } 6413089Swyllys /* No additional args allowed. */ 6423089Swyllys argc -= optind_av; 6433089Swyllys argv += optind_av; 6443089Swyllys if (argc) { 6453089Swyllys return (PK_ERR_USAGE); 6463089Swyllys } 6473089Swyllys 6483089Swyllys /* Assume keystore = PKCS#11 if not specified. */ 6493089Swyllys if (kstype == 0) 6503089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 6513089Swyllys 6526884Swyllys DIR_OPTION_CHECK(kstype, dir); 6536884Swyllys 6545221Swyllys if (EMPTYSTRING(outcsr) && interactive) { 6555221Swyllys (void) get_filename("CSR", &outcsr); 6565221Swyllys } 6573089Swyllys if (EMPTYSTRING(outcsr)) { 6583089Swyllys (void) printf(gettext("A filename must be specified to hold" 6595051Swyllys "the final certificate request data.\n")); 6603089Swyllys return (PK_ERR_USAGE); 6615221Swyllys } 6625221Swyllys /* 6635221Swyllys * verify that the outcsr file does not already exist 6645221Swyllys * and that it can be created. 6655221Swyllys */ 6665221Swyllys rv = verify_file(outcsr); 6675221Swyllys if (rv != KMF_OK) { 6685221Swyllys cryptoerror(LOG_STDERR, gettext("output file (%s) " 6695221Swyllys "cannot be created.\n"), outcsr); 6705221Swyllys return (PK_ERR_USAGE); 6715221Swyllys } 6725221Swyllys 6735221Swyllys if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) { 6745221Swyllys if (EMPTYSTRING(certlabel) && interactive) 6755221Swyllys (void) get_certlabel(&certlabel); 6765221Swyllys 6775221Swyllys if (EMPTYSTRING(certlabel)) { 6785221Swyllys cryptoerror(LOG_STDERR, gettext("A label must be " 6795221Swyllys "specified to create a certificate request.\n")); 6803089Swyllys return (PK_ERR_USAGE); 6813089Swyllys } 6825221Swyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) { 6835221Swyllys if (EMPTYSTRING(outkey) && interactive) 6845221Swyllys (void) get_filename("private key", &outkey); 6853089Swyllys 6865221Swyllys if (EMPTYSTRING(outkey)) { 6875221Swyllys cryptoerror(LOG_STDERR, gettext("A key filename " 6885221Swyllys "must be specified to create a certificate " 6895221Swyllys "request.\n")); 6905221Swyllys return (PK_ERR_USAGE); 6915221Swyllys } 6923089Swyllys } 6933089Swyllys 6943089Swyllys if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 6953089Swyllys cryptoerror(LOG_STDERR, 6965051Swyllys gettext("Error parsing format string (%s).\n"), format); 6973089Swyllys return (PK_ERR_USAGE); 6983089Swyllys } 6993089Swyllys if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) { 7003089Swyllys cryptoerror(LOG_STDERR, 7015051Swyllys gettext("CSR must be DER or PEM format.\n")); 7023089Swyllys return (PK_ERR_USAGE); 7033089Swyllys } 7043089Swyllys 7053089Swyllys /* 7063089Swyllys * Check the subject name. 7073089Swyllys * If interactive is true, get it now interactively. 7083089Swyllys */ 7093089Swyllys if (interactive) { 7103089Swyllys if (get_subname(&subname) != KMF_OK) { 7113089Swyllys cryptoerror(LOG_STDERR, gettext("Failed to get the " 7123089Swyllys "subject name interactively.\n")); 7133089Swyllys return (PK_ERR_USAGE); 7143089Swyllys } 7153089Swyllys } else { 7163089Swyllys if (EMPTYSTRING(subject)) { 7173089Swyllys cryptoerror(LOG_STDERR, gettext("A subject name or " 7183089Swyllys "-i must be specified to create a certificate " 7193089Swyllys "request.\n")); 7203089Swyllys return (PK_ERR_USAGE); 7213089Swyllys } else { 7223089Swyllys subname = strdup(subject); 7233089Swyllys if (subname == NULL) { 7243089Swyllys cryptoerror(LOG_STDERR, 7253089Swyllys gettext("Out of memory.\n")); 7263089Swyllys return (PK_ERR_SYSTEM); 7273089Swyllys } 7283089Swyllys } 7293089Swyllys } 7303089Swyllys if (altname != NULL) { 7313089Swyllys rv = verify_altname(altname, &alttype, &altcrit); 7323089Swyllys if (rv != KMF_OK) { 7333089Swyllys cryptoerror(LOG_STDERR, gettext("Subject AltName " 7345051Swyllys "must be specified as a name=value pair. " 7355051Swyllys "See the man page for details.")); 7363089Swyllys goto end; 7373089Swyllys } else { 7383089Swyllys /* advance the altname past the '=' sign */ 7393089Swyllys char *p = strchr(altname, '='); 7403089Swyllys if (p != NULL) 7413089Swyllys altname = p + 1; 7423089Swyllys } 7433089Swyllys } 7443089Swyllys 7453089Swyllys if (kustr != NULL) { 7463089Swyllys rv = verify_keyusage(kustr, &kubits, &kucrit); 7473089Swyllys if (rv != KMF_OK) { 7483089Swyllys cryptoerror(LOG_STDERR, gettext("KeyUsage " 7495051Swyllys "must be specified as a comma-separated list. " 7505051Swyllys "See the man page for details.")); 7513089Swyllys goto end; 7523089Swyllys } 7533089Swyllys } 7546051Swyllys if (ekustr != NULL) { 7556051Swyllys rv = verify_ekunames(ekustr, &ekulist); 7566051Swyllys if (rv != KMF_OK) { 7576051Swyllys (void) fprintf(stderr, gettext("EKUs must " 7586051Swyllys "be specified as a comma-separated list. " 7596051Swyllys "See the man page for details.\n")); 7606051Swyllys rv = PK_ERR_USAGE; 7616051Swyllys goto end; 7626051Swyllys } 7636051Swyllys } 7646051Swyllys 7653089Swyllys if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) { 7663089Swyllys cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 7675051Swyllys keytype); 7683089Swyllys goto end; 7693089Swyllys } 7703089Swyllys 7713089Swyllys if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 7723089Swyllys if (tokenname == NULL || !strlen(tokenname)) { 7733089Swyllys if (kstype == KMF_KEYSTORE_NSS) { 7743089Swyllys tokenname = "internal"; 7753089Swyllys } else { 7763089Swyllys tokenname = PK_DEFAULT_PK11TOKEN; 7773089Swyllys } 7783089Swyllys } 7793089Swyllys 7803089Swyllys (void) get_token_password(kstype, tokenname, &tokencred); 7813089Swyllys } 7823089Swyllys 7836884Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 7846884Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 7856884Swyllys return (PK_ERR_USAGE); 7866884Swyllys } 7876884Swyllys 7886884Swyllys 7893089Swyllys if (kstype == KMF_KEYSTORE_NSS) { 7903089Swyllys if (dir == NULL) 7913089Swyllys dir = PK_DEFAULT_DIRECTORY; 7923089Swyllys 7933089Swyllys rv = gencsr_nss(kmfhandle, 7945051Swyllys tokenname, subname, altname, alttype, altcrit, 7955051Swyllys certlabel, dir, prefix, 7965051Swyllys keyAlg, keylen, kubits, kucrit, 7976051Swyllys fmt, outcsr, &tokencred, ekulist); 7983089Swyllys 7993089Swyllys } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 8003089Swyllys rv = gencsr_pkcs11(kmfhandle, 8015051Swyllys tokenname, subname, altname, alttype, altcrit, 8025051Swyllys certlabel, keyAlg, keylen, 8036051Swyllys kubits, kucrit, fmt, outcsr, &tokencred, ekulist); 8043089Swyllys 8053089Swyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) { 8063089Swyllys rv = gencsr_file(kmfhandle, 8075051Swyllys keyAlg, keylen, fmt, subname, altname, 8085051Swyllys alttype, altcrit, kubits, kucrit, 8096669Swyllys outcsr, outkey, ekulist); 8103089Swyllys } 8113089Swyllys 8123089Swyllys end: 813*10241Swyllys.ingersoll@sun.com if (rv != KMF_OK) { 8143089Swyllys display_error(kmfhandle, rv, 8155051Swyllys gettext("Error creating CSR or keypair")); 8163089Swyllys 817*10241Swyllys.ingersoll@sun.com if (rv == KMF_ERR_RDN_PARSER) { 818*10241Swyllys.ingersoll@sun.com cryptoerror(LOG_STDERR, gettext("subject or " 819*10241Swyllys.ingersoll@sun.com "issuer name must be in proper DN format.\n")); 820*10241Swyllys.ingersoll@sun.com } 821*10241Swyllys.ingersoll@sun.com } 822*10241Swyllys.ingersoll@sun.com 8236051Swyllys if (ekulist != NULL) 8246051Swyllys free_eku_list(ekulist); 8256051Swyllys 8263089Swyllys if (subname) 8273089Swyllys free(subname); 8283089Swyllys 8293089Swyllys if (tokencred.cred != NULL) 8303089Swyllys free(tokencred.cred); 8313089Swyllys 8325051Swyllys (void) kmf_finalize(kmfhandle); 8333089Swyllys if (rv != KMF_OK) 8343089Swyllys return (PK_ERR_USAGE); 8353089Swyllys 8363089Swyllys return (0); 8373089Swyllys } 838