From 2dbe137fc7298023d155956810d1cc3c6250ce75 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Wed, 1 Nov 2023 11:49:02 -0500 Subject: [PATCH] Add PK11Store.importCert() Currently none of the cert import methods provided by JSS works like certutil -A since they call different NSS functions so in some cases it's necessary to call this external command from Java which could be problematic and does not work well with HSM. To address the problem the PK11Store.importCert() has been added to call the same NSS functions used by certutil -A so it's no longer necessary to call this external command from Java. --- .../org/mozilla/jss/crypto/CryptoStore.java | 11 ++++ .../org/mozilla/jss/pkcs11/PK11Store.java | 4 ++ lib/jss.map | 6 ++ .../native/org/mozilla/jss/pkcs11/PK11Store.c | 64 +++++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/base/src/main/java/org/mozilla/jss/crypto/CryptoStore.java b/base/src/main/java/org/mozilla/jss/crypto/CryptoStore.java index d1fc665cd..188578300 100644 --- a/base/src/main/java/org/mozilla/jss/crypto/CryptoStore.java +++ b/base/src/main/java/org/mozilla/jss/crypto/CryptoStore.java @@ -165,6 +165,17 @@ public void importEncryptedPrivateKeyInfo( */ public X509Certificate[] getCertificates() throws TokenException; + /** + * Imports a certificate into this token. + * + * @param certBytes Certificate binaries + * @param nickname Certificate nickname + * @return X509Certificate object of the imported certificate + * @throws TokenException + */ + public X509Certificate importCert(byte[] certBytes, String nickname) + throws TokenException; + /** * Deletes a certificate and the corresponding keys. * diff --git a/base/src/main/java/org/mozilla/jss/pkcs11/PK11Store.java b/base/src/main/java/org/mozilla/jss/pkcs11/PK11Store.java index b467fa218..0c4df8a67 100644 --- a/base/src/main/java/org/mozilla/jss/pkcs11/PK11Store.java +++ b/base/src/main/java/org/mozilla/jss/pkcs11/PK11Store.java @@ -194,6 +194,10 @@ public native void importEncryptedPrivateKeyInfo( } protected native void putCertsInVector(Vector certs) throws TokenException; + @Override + public native X509Certificate importCert(byte[] certBytes, String nickname) + throws TokenException; + /** * Deletes the specified certificate and its associated private * key from the store. diff --git a/lib/jss.map b/lib/jss.map index b70451848..94df9e771 100644 --- a/lib/jss.map +++ b/lib/jss.map @@ -512,3 +512,9 @@ Java_org_mozilla_jss_CryptoManager_initializeAllNativeWithContext; local: *; }; +JSS_5.5.0 { + global: +Java_org_mozilla_jss_pkcs11_PK11Store_importCert; + local: + *; +}; diff --git a/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c b/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c index c6ca206a8..ea201d9c4 100644 --- a/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c +++ b/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c @@ -385,6 +385,70 @@ JSS_PK11_getStoreSlotPtr(JNIEnv *env, jobject store, PK11SlotInfo **slot) PK11STORE_PROXY_SIG, (void**)slot); } +/********************************************************************** + * PK11Store.importCert + */ +JNIEXPORT jobject JNICALL +Java_org_mozilla_jss_pkcs11_PK11Store_importCert( + JNIEnv *env, + jobject this, + jbyteArray certBytes, + jstring nickname) +{ + PK11SlotInfo *slot = NULL; + char *nicknameChars = NULL; + jbyte *derCertBytes = NULL; + jsize derCertLen; + CERTCertificate *nssCert = NULL; + SECStatus rv; + jobject cert = NULL; + + if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { + goto finish; + } + + if (certBytes == NULL) { + goto finish; + } + + if (!JSS_RefByteArray(env, certBytes, &derCertBytes, &derCertLen)) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to parse certificate binaries"); + goto finish; + } + + if (nickname != NULL) { + nicknameChars = (char *)JSS_RefJString(env, nickname); + + if (nicknameChars == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to parse certificate nickname"); + goto finish; + } + } + + nssCert = CERT_DecodeCertFromPackage((char *)derCertBytes, derCertLen); + + if (nssCert == NULL) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to decode DER certificate"); + goto finish; + } + + rv = PK11_ImportCert(slot, nssCert, CK_INVALID_HANDLE, nicknameChars, PR_FALSE); + + if (rv != SECSuccess) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to import certificate"); + goto finish; + } + + cert = JSS_PK11_wrapCert(env, &nssCert); + +finish: + CERT_DestroyCertificate(nssCert); + JSS_DerefJString(env, nickname, nicknameChars); + JSS_DerefByteArray(env, certBytes, derCertBytes, JNI_ABORT); + + return cert; +} + /********************************************************************** * PK11Store.deletePrivateKey */