static KMF_RETURN gencsr_pkcs11(KMF_HANDLE_T kmfhandle, char *token, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, char *certlabel, KMF_KEY_ALG keyAlg, int keylen, uint16_t kubits, int kucrit, KMF_ENCODE_FORMAT fmt, char *csrfile, KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist, KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid) { KMF_RETURN kmfrv = KMF_OK; KMF_KEY_HANDLE pubk, prik; KMF_X509_NAME csrSubject; KMF_CSR_DATA csr; KMF_DATA signedCsr = {NULL, 0}; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; int numattr = 0; KMF_ATTRIBUTE attrlist[16]; (void) memset(&csr, 0, sizeof (csr)); (void) memset(&csrSubject, 0, sizeof (csrSubject)); /* If the subject name cannot be parsed, flag it now and exit */ if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) return (kmfrv); /* Select a PKCS11 token */ kmfrv = select_token(kmfhandle, token, FALSE); if (kmfrv != KMF_OK) return (kmfrv); /* * Share the "genkeypair" routine for creating the keypair. */ kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel, keyAlg, keylen, tokencred, curveoid, &prik, &pubk); if (kmfrv != KMF_OK) return (kmfrv); SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair"); SET_VALUE(kmf_set_csr_version(&csr, 2), "version number"); SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name"); SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "SignatureAlgorithm"); if (altname != NULL) { SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit, alttype), "SetCSRSubjectAltName"); } if (kubits != 0) { SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits), "SetCSRKeyUsage"); } 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, csrfile); } cleanup: (void) kmf_free_data(&signedCsr); (void) kmf_free_signed_csr(&csr); /* delete the public key */ 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_PUBKEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE)); numattr++; if (tokencred != NULL && tokencred->cred != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); numattr++; } (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); /* * If there is an error, then we need to remove the private key * from the token. */ if (kmfrv != KMF_OK) { 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)); numattr++; if (tokencred != NULL && tokencred->cred != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); numattr++; } (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); } (void) kmf_free_kmf_key(kmfhandle, &prik); return (kmfrv); }
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); }
static KMF_RETURN gencsr_nss(KMF_HANDLE_T kmfhandle, char *token, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, char *nickname, char *dir, char *prefix, KMF_KEY_ALG keyAlg, int keylen, uint16_t kubits, int kucrit, KMF_ENCODE_FORMAT fmt, char *csrfile, KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist, KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid) { KMF_RETURN kmfrv; KMF_KEY_HANDLE pubk, prik; KMF_X509_NAME csrSubject; KMF_CSR_DATA csr; KMF_DATA signedCsr = {NULL, 0}; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; int numattr = 0; KMF_ATTRIBUTE attrlist[16]; if (token == NULL) token = DEFAULT_NSS_TOKEN; kmfrv = configure_nss(kmfhandle, dir, prefix); if (kmfrv != KMF_OK) return (kmfrv); (void) memset(&csr, 0, sizeof (csr)); (void) memset(&csrSubject, 0, sizeof (csrSubject)); (void) memset(&pubk, 0, sizeof (pubk)); (void) memset(&prik, 0, sizeof (prik)); /* If the subject name cannot be parsed, flag it now and exit */ if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) { return (kmfrv); } kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir, prefix, keyAlg, keylen, tokencred, curveoid, &prik, &pubk); if (kmfrv != KMF_OK) return (kmfrv); SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "kmf_set_csr_pubkey"); SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version"); 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, csrfile); } cleanup: (void) kmf_free_data(&signedCsr); (void) kmf_free_kmf_key(kmfhandle, &prik); /* delete the key */ 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_PUBKEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE)); numattr++; if (tokencred != NULL && tokencred->credlen > 0) { kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); numattr++; } if (token && strlen(token)) { kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, token, strlen(token)); numattr++; } (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); (void) kmf_free_signed_csr(&csr); return (kmfrv); }
static int gencert_pkcs11(KMF_HANDLE_T kmfhandle, char *token, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, char *certlabel, KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg, int keylen, uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist, KMF_OID *curveoid) { KMF_RETURN kmfrv = KMF_OK; KMF_KEY_HANDLE pubk, prik; KMF_X509_CERTIFICATE signedCert; KMF_X509_NAME certSubject; KMF_X509_NAME certIssuer; KMF_DATA x509DER; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; KMF_ATTRIBUTE attrlist[16]; int numattr = 0; KMF_KEY_ALG keytype; uint32_t keylength; (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 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.\n")); 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.\n")); return (PK_ERR_USAGE); } keylength = keylen; /* bits */ keytype = keyAlg; /* Select a PKCS11 token */ kmfrv = select_token(kmfhandle, token, FALSE); if (kmfrv != KMF_OK) { return (kmfrv); } /* * Share the "genkeypair" routine for creating the keypair. */ kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel, keytype, keylength, tokencred, curveoid, &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++; if (certlabel != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); numattr++; } kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist); cleanup: kmf_free_data(&x509DER); kmf_free_dn(&certSubject); kmf_free_dn(&certIssuer); /* * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up * the key pair from the token. */ if (kmfrv != KMF_OK) { /* delete the public key */ 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, &pubk, sizeof (KMF_KEY_HANDLE)); numattr++; if (tokencred != NULL && tokencred->cred != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); numattr++; } (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); /* delete the private key */ 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)); numattr++; if (tokencred != NULL && tokencred->cred != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); numattr++; } (void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist); } return (kmfrv); }
static KMF_RETURN gencert_nss(KMF_HANDLE_T kmfhandle, char *token, char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit, char *nickname, char *dir, char *prefix, KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg, int keylen, char *trust, uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist, KMF_OID *curveoid) { KMF_RETURN kmfrv; KMF_KEY_HANDLE pubk, prik; KMF_X509_CERTIFICATE signedCert; KMF_X509_NAME certSubject; KMF_X509_NAME certIssuer; KMF_DATA x509DER; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; KMF_ATTRIBUTE attrlist[16]; int numattr = 0; if (token == NULL) token = DEFAULT_NSS_TOKEN; kmfrv = configure_nss(kmfhandle, dir, prefix); if (kmfrv != KMF_OK) return (kmfrv); (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 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.\n")); 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.\n")); return (PK_ERR_USAGE); } kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir, prefix, keyAlg, keylen, tokencred, curveoid, &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) SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits), "subjectAltName"); 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++; if (nickname != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR, nickname, strlen(nickname)); numattr++; } if (trust != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR, trust, strlen(trust)); numattr++; } if (token != NULL) { kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, token, strlen(token)); numattr++; } kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist); cleanup: kmf_free_data(&x509DER); kmf_free_dn(&certSubject); kmf_free_dn(&certIssuer); return (kmfrv); }
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); }
int pk_download(int argc, char *argv[]) { int rv; int opt; extern int optind_av; extern char *optarg_av; int oclass = 0; char *url = NULL; char *http_proxy = NULL; char *dir = NULL; char *outfile = NULL; char *proxy = NULL; int proxy_port = 0; KMF_HANDLE_T kmfhandle = NULL; KMF_ENCODE_FORMAT format; KMF_RETURN ch_rv = KMF_OK; char *fullpath = NULL; KMF_DATA cert = { 0, NULL }; KMF_DATA cert_der = { 0, NULL }; while ((opt = getopt_av(argc, argv, "t:(objtype)u:(url)h:(http_proxy)o:(outfile)d:(dir)")) != EOF) { if (EMPTYSTRING(optarg_av)) return (PK_ERR_USAGE); switch (opt) { case 't': if (oclass) return (PK_ERR_USAGE); oclass = OT2Int(optarg_av); if (!(oclass & (PK_CERT_OBJ | PK_CRL_OBJ))) return (PK_ERR_USAGE); break; case 'u': if (url) return (PK_ERR_USAGE); url = optarg_av; break; case 'h': if (http_proxy) return (PK_ERR_USAGE); http_proxy = optarg_av; break; case 'o': if (outfile) return (PK_ERR_USAGE); outfile = optarg_av; break; case 'd': if (dir) return (PK_ERR_USAGE); dir = optarg_av; break; default: cryptoerror(LOG_STDERR, gettext( "unrecognized download option '%s'\n"), argv[optind_av]); return (PK_ERR_USAGE); } } /* No additional args allowed. */ argc -= optind_av; argv += optind_av; if (argc) { return (PK_ERR_USAGE); } /* Check the dir and outfile options */ if (outfile == NULL) { /* If outfile is not specified, use the basename of URI */ outfile = basename(url); } fullpath = get_fullpath(dir, outfile); if (fullpath == NULL) { cryptoerror(LOG_STDERR, gettext("Incorrect dir or outfile " "option value \n")); return (PK_ERR_USAGE); } /* Check if the file exists and might be overwritten. */ if (verify_file(fullpath) != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, " "will be overwritten."), fullpath); if (yesno(gettext("Continue with download? "), gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { return (0); } } /* URI MUST be specified */ if (url == NULL) { cryptoerror(LOG_STDERR, gettext("A URL must be specified\n")); rv = PK_ERR_USAGE; goto end; } /* * Get the http proxy from the command "http_proxy" option or the * environment variable. The command option has a higher priority. */ if (http_proxy == NULL) http_proxy = getenv("http_proxy"); if (http_proxy != NULL) { char *ptmp = http_proxy; char *proxy_port_s; if (strncasecmp(ptmp, "http://", 7) == 0) ptmp += 7; /* skip the scheme prefix */ proxy = strtok(ptmp, ":"); proxy_port_s = strtok(NULL, "\0"); if (proxy_port_s != NULL) proxy_port = strtol(proxy_port_s, NULL, 0); else proxy_port = 8080; } /* If objtype is not specified, default to CRL */ if (oclass == 0) { oclass = PK_CRL_OBJ; } if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); rv = PK_ERR_USAGE; goto end; } /* Now we are ready to download */ if (oclass & PK_CRL_OBJ) { rv = kmf_download_crl(kmfhandle, url, proxy, proxy_port, 30, fullpath, &format); } else if (oclass & PK_CERT_OBJ) { rv = kmf_download_cert(kmfhandle, url, proxy, proxy_port, 30, fullpath, &format); } if (rv != KMF_OK) { switch (rv) { case KMF_ERR_BAD_URI: cryptoerror(LOG_STDERR, gettext("Error in parsing URI\n")); rv = PK_ERR_USAGE; break; case KMF_ERR_OPEN_FILE: cryptoerror(LOG_STDERR, gettext("Error in opening file\n")); rv = PK_ERR_USAGE; break; case KMF_ERR_WRITE_FILE: cryptoerror(LOG_STDERR, gettext("Error in writing file\n")); rv = PK_ERR_USAGE; break; case KMF_ERR_BAD_CRLFILE: cryptoerror(LOG_STDERR, gettext("Not a CRL file\n")); rv = PK_ERR_USAGE; break; case KMF_ERR_BAD_CERTFILE: cryptoerror(LOG_STDERR, gettext("Not a certificate file\n")); rv = PK_ERR_USAGE; break; case KMF_ERR_MEMORY: cryptoerror(LOG_STDERR, gettext("Not enough memory\n")); rv = PK_ERR_SYSTEM; break; default: cryptoerror(LOG_STDERR, gettext("Error in downloading the file.\n")); rv = PK_ERR_SYSTEM; break; } goto end; } /* * If the file is successfully downloaded, we also check the date. * If the downloaded file is outdated, give a warning. */ if (oclass & PK_CRL_OBJ) { ch_rv = kmf_check_crl_date(kmfhandle, fullpath); } else { /* certificate */ ch_rv = kmf_read_input_file(kmfhandle, fullpath, &cert); if (ch_rv != KMF_OK) goto end; if (format == KMF_FORMAT_PEM) { int len; ch_rv = kmf_pem_to_der(cert.Data, cert.Length, &cert_der.Data, &len); if (ch_rv != KMF_OK) goto end; cert_der.Length = (size_t)len; } ch_rv = kmf_check_cert_date(kmfhandle, format == KMF_FORMAT_ASN1 ? &cert : &cert_der); } end: if (ch_rv == KMF_ERR_VALIDITY_PERIOD) { cryptoerror(LOG_STDERR, gettext("Warning: the downloaded file is expired.\n")); } else if (ch_rv != KMF_OK) { cryptoerror(LOG_STDERR, gettext("Warning: failed to check the validity.\n")); } if (fullpath) free(fullpath); kmf_free_data(&cert); kmf_free_data(&cert_der); (void) kmf_finalize(kmfhandle); return (rv); }
/* * Convert an SPKI data record to PKCS#11 * public key object. */ static KMF_RETURN PKCS_CreatePublicKey( const KMF_X509_SPKI *pKey, CK_SESSION_HANDLE ckSession, CK_OBJECT_HANDLE *pckPublicKey) { KMF_RETURN mrReturn = KMF_OK; CK_RV ckRv; CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES]; CK_ULONG ckNumTemplates = 0; /* Common object attributes */ CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY; CK_BBOOL ckToken = 0; CK_BBOOL ckPrivate = 0; /* Common key attributes */ CK_KEY_TYPE ckKeyType; CK_BBOOL ckDerive = CK_FALSE; /* Common public key attributes */ CK_BBOOL ckEncrypt = 1; CK_BBOOL ckVerify = 1; CK_BBOOL ckVerifyRecover = CK_FALSE; CK_BBOOL ckWrap = CK_FALSE; /* Key part array */ KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS]; uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS; KMF_ALGORITHM_INDEX AlgorithmId; /* Parse the keyblob */ (void) memset(KeyParts, 0, sizeof (KeyParts)); AlgorithmId = x509_algoid_to_algid( (KMF_OID *)&pKey->algorithm.algorithm); if (AlgorithmId == KMF_ALGID_NONE) return (KMF_ERR_BAD_ALGORITHM); mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts); if (mrReturn != KMF_OK) return (mrReturn); /* Fill in the common object attributes */ if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass, sizeof (ckObjClass)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken, sizeof (ckToken)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate, sizeof (ckPrivate))) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } /* Fill in the common key attributes */ if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) { goto cleanup; } if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, sizeof (ckKeyType)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive, sizeof (ckDerive))) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } /* Add common public key attributes */ if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt, sizeof (ckEncrypt)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify, sizeof (ckVerify)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER, (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap, sizeof (ckWrap))) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } /* Add algorithm specific attributes */ switch (ckKeyType) { case CKK_RSA: if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS, (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data, (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT, (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data, (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } break; case CKK_DSA: if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME, (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data, (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME, (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data, (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE, (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data, (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE, (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data, (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } break; case CKK_EC: if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT, (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data, (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) || !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS, (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data, (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) { mrReturn = KMF_ERR_INTERNAL; goto cleanup; } break; default: mrReturn = KMF_ERR_BAD_PARAMETER; } if (mrReturn == KMF_OK) { /* Instantiate the object */ ckRv = C_CreateObject(ckSession, ckTemplate, ckNumTemplates, pckPublicKey); if (ckRv != CKR_OK) mrReturn = KMF_ERR_INTERNAL; } cleanup: for (i = 0; i < uNumKeyParts; i++) { kmf_free_data(&KeyParts[i]); } return (mrReturn); }