static KMF_RETURN gencsr_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, KMF_ENCODE_FORMAT fmt, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, uint16_t kubits, int kucrit, char *outcsr, char *outkey, EKU_LIST *ekulist, KMF_ALGORITHM_INDEX sigAlg) { KMF_RETURN kmfrv; KMF_KEY_HANDLE pubk, prik; KMF_X509_NAME csrSubject; KMF_CSR_DATA csr; KMF_DATA signedCsr = {NULL, 0}; char *fullcsrpath = NULL; char *fullkeypath = NULL; (void) memset(&csr, 0, sizeof (csr)); (void) memset(&csrSubject, 0, sizeof (csrSubject)); if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) { cryptoerror(LOG_STDERR, gettext("No output file was specified for " "the csr or key\n")); return (KMF_ERR_BAD_PARAMETER); } fullcsrpath = strdup(outcsr); if (verify_file(fullcsrpath)) { cryptoerror(LOG_STDERR, gettext("Cannot write the indicated output " "certificate file (%s).\n"), fullcsrpath); free(fullcsrpath); return (PK_ERR_USAGE); } /* If the subject name cannot be parsed, flag it now and exit */ if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { return (kmfrv); } /* * Share the "genkeypair" routine for creating the keypair. */ kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen, fmt, outkey, &prik, &pubk); if (kmfrv != KMF_OK) return (kmfrv); SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "SetCSRPubKey"); SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion"); SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "kmf_set_csr_subject"); SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg"); if (altname != NULL) { SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, alttype), "kmf_set_csr_subject_altname"); } if (kubits != NULL) { SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), "kmf_set_csr_ku"); } if (ekulist != NULL) { int i; for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { SET_VALUE(kmf_add_csr_eku(&csr, &ekulist->ekulist[i], ekulist->critlist[i]), "Extended Key Usage"); } } if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == KMF_OK) { kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath); } cleanup: if (fullkeypath) free(fullkeypath); if (fullcsrpath) free(fullcsrpath); kmf_free_data(&signedCsr); kmf_free_kmf_key(kmfhandle, &prik); kmf_free_signed_csr(&csr); return (kmfrv); }
int pk_genkeypair(int argc, char *argv[]) { int rv; int opt; extern int optind_av; extern char *optarg_av; KMF_KEYSTORE_TYPE kstype = 0; char *tokenname = NULL; char *dir = NULL; char *prefix = NULL; char *keytype = PK_DEFAULT_KEYTYPE; int keylen = PK_DEFAULT_KEYLENGTH; char *label = NULL; char *outkey = NULL; char *format = NULL; KMF_HANDLE_T kmfhandle = NULL; KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; KMF_KEY_ALG keyAlg = KMF_RSA; KMF_ALGORITHM_INDEX sigAlg; KMF_CREDENTIAL tokencred = {NULL, 0}; KMF_OID *curveoid = NULL; /* ECC */ int y_flag = 0; while ((opt = getopt_av(argc, argv, "k:(keystore)s:(subject)n:(nickname)" "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)" "l:(label)K:(outkey)F:(format)C:(curve)" "E(listcurves)")) != EOF) { if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av)) return (PK_ERR_USAGE); switch (opt) { case 'k': kstype = KS2Int(optarg_av); if (kstype == 0) return (PK_ERR_USAGE); break; case 'l': case 'n': if (label) return (PK_ERR_USAGE); label = optarg_av; break; case 'T': if (tokenname) return (PK_ERR_USAGE); tokenname = optarg_av; break; case 'd': if (dir) return (PK_ERR_USAGE); dir = optarg_av; break; case 'p': if (prefix) return (PK_ERR_USAGE); prefix = optarg_av; break; case 't': keytype = optarg_av; break; case 'y': if (sscanf(optarg_av, "%d", &keylen) != 1) { cryptoerror(LOG_STDERR, gettext("key length must be" "a numeric value (%s)\n"), optarg_av); return (PK_ERR_USAGE); } y_flag++; break; case 'K': if (outkey) return (PK_ERR_USAGE); outkey = optarg_av; break; case 'F': if (format) return (PK_ERR_USAGE); format = optarg_av; break; case 'C': curveoid = ecc_name_to_oid(optarg_av); if (curveoid == NULL) { cryptoerror(LOG_STDERR, gettext( "Unrecognized ECC curve.\n")); return (PK_ERR_USAGE); } break; case 'E': show_ecc_curves(); return (0); default: return (PK_ERR_USAGE); } } /* No additional args allowed. */ argc -= optind_av; argv += optind_av; if (argc) { return (PK_ERR_USAGE); } if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); return (PK_ERR_USAGE); } /* Assume keystore = PKCS#11 if not specified. */ if (kstype == 0) kstype = KMF_KEYSTORE_PK11TOKEN; DIR_OPTION_CHECK(kstype, dir); if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { cryptoerror(LOG_STDERR, gettext("Error parsing format string (%s).\n"), format); return (PK_ERR_USAGE); } if (Str2KeyType(keytype, NULL, &keyAlg, &sigAlg) != 0) { cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), keytype); return (PK_ERR_USAGE); } if (curveoid != NULL && keyAlg != KMF_ECDSA) { cryptoerror(LOG_STDERR, gettext("EC curves are only " "valid for EC keytypes.\n")); return (PK_ERR_USAGE); } if (keyAlg == KMF_ECDSA && curveoid == NULL) { cryptoerror(LOG_STDERR, gettext("A curve must be " "specifed when using EC keys.\n")); return (PK_ERR_USAGE); } if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) { (void) fprintf(stderr, gettext("ECC certificates are" "only supported with the pkcs11 and nss keystores\n")); rv = PK_ERR_USAGE; goto end; } /* Adjust default keylength for NSS and DSA */ if (keyAlg == KMF_DSA && kstype == KMF_KEYSTORE_NSS) { /* NSS only allows for 512-1024 bit DSA keys */ if (!y_flag) /* If nothing was given, default to 1024 */ keylen = 1024; else if (keylen > 1024 || keylen < 512) { (void) fprintf(stderr, gettext("NSS keystore only " "supports DSA keylengths of 512 - 1024 bits\n")); rv = PK_ERR_USAGE; goto end; } } if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { if (label == NULL) { (void) fprintf(stderr, gettext("No key label specified\n")); rv = PK_ERR_USAGE; goto end; } if (tokenname == NULL || !strlen(tokenname)) { if (kstype == KMF_KEYSTORE_NSS) { tokenname = "internal"; } else { tokenname = PK_DEFAULT_PK11TOKEN; } } (void) get_token_password(kstype, tokenname, &tokencred); } if (kstype == KMF_KEYSTORE_NSS) { if (dir == NULL) dir = PK_DEFAULT_DIRECTORY; rv = genkeypair_nss(kmfhandle, tokenname, label, dir, prefix, keyAlg, keylen, &tokencred, curveoid, NULL, NULL); } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { rv = genkeypair_pkcs11(kmfhandle, tokenname, label, keyAlg, keylen, &tokencred, curveoid, NULL, NULL); } else if (kstype == KMF_KEYSTORE_OPENSSL) { rv = genkeypair_file(kmfhandle, keyAlg, keylen, fmt, outkey, NULL, NULL); } if (rv != KMF_OK) display_error(kmfhandle, rv, gettext("Error creating and keypair")); end: if (tokencred.cred != NULL) free(tokencred.cred); (void) kmf_finalize(kmfhandle); return (rv); }
static int gencert_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg, int keylen, KMF_ENCODE_FORMAT fmt, uint32_t ltime, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, KMF_BIGINT *serial, uint16_t kubits, int kucrit, char *outcert, char *outkey, EKU_LIST *ekulist) { KMF_RETURN kmfrv; KMF_KEY_HANDLE pubk, prik; KMF_X509_CERTIFICATE signedCert; KMF_X509_NAME certSubject; KMF_X509_NAME certIssuer; KMF_DATA x509DER; char *fullcertpath = NULL; char *fullkeypath = NULL; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; KMF_ATTRIBUTE attrlist[10]; int numattr = 0; (void) memset(&signedCert, 0, sizeof (signedCert)); (void) memset(&certSubject, 0, sizeof (certSubject)); (void) memset(&certIssuer, 0, sizeof (certIssuer)); (void) memset(&x509DER, 0, sizeof (x509DER)); if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) { cryptoerror(LOG_STDERR, gettext("No output file was specified for " "the cert or key\n")); return (PK_ERR_USAGE); } fullcertpath = strdup(outcert); if (verify_file(fullcertpath)) { cryptoerror(LOG_STDERR, gettext("Cannot write the indicated output " "certificate file (%s).\n"), fullcertpath); free(fullcertpath); return (PK_ERR_USAGE); } /* If the subject name cannot be parsed, flag it now and exit */ if (kmf_dn_parser(subject, &certSubject) != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Subject name cannot be parsed (%s)\n"), subject); return (PK_ERR_USAGE); } /* For a self-signed cert, the issuser and subject are the same */ if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Subject name cannot be parsed (%s)\n"), subject); kmf_free_dn(&certSubject); return (PK_ERR_USAGE); } /* * Share the "genkeypair" routine for creating the keypair. */ kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen, fmt, outkey, &prik, &pubk); if (kmfrv != KMF_OK) return (kmfrv); SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert), "keypair"); SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number"); SET_VALUE(kmf_set_cert_serial(&signedCert, serial), "serial number"); SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime), "validity time"); SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg), "signature algorithm"); SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject), "subject name"); SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer), "issuer name"); if (altname != NULL) SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit, alttype, altname), "subjectAltName"); if (kubits != 0) SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits), "KeyUsage"); if (ekulist != NULL) { int i; for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) { SET_VALUE(kmf_add_cert_eku(&signedCert, &ekulist->ekulist[i], ekulist->critlist[i]), "Extended Key Usage"); } } /* * Construct attributes for the kmf_sign_cert operation. */ numattr = 0; kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE_ATTR)); numattr++; /* cert data that is to be signed */ kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR, &signedCert, sizeof (KMF_X509_CERTIFICATE)); numattr++; /* output buffer for the signed cert */ kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR, &x509DER, sizeof (KMF_DATA)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_ALGORITHM_INDEX_ATTR, &sigAlg, sizeof (sigAlg)); numattr++; if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) != KMF_OK) { goto cleanup; } /* * Store the cert in the DB. */ numattr = 0; kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR, &x509DER, sizeof (KMF_DATA)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR, fullcertpath, strlen(fullcertpath)); numattr++; kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, &fmt, sizeof (fmt)); numattr++; kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist); cleanup: if (fullkeypath != NULL) free(fullkeypath); if (fullcertpath != NULL) free(fullcertpath); kmf_free_data(&x509DER); kmf_free_dn(&certSubject); kmf_free_dn(&certIssuer); return (kmfrv); }