|
|
aee1ec |
# HG changeset patch
|
|
|
aee1ec |
# User Fraser Tweedale <ftweedal@redhat.com>
|
|
|
aee1ec |
# Date 1493324725 25200
|
|
|
aee1ec |
# Thu Apr 27 13:25:25 2017 -0700
|
|
|
aee1ec |
# Node ID c8885dd6787639d74a1c9d634fd289ff17fa6f02
|
|
|
aee1ec |
# Parent b2306481f30dcc8c0c060520805d405dd2546d14
|
|
|
aee1ec |
Bug 1355358 - CryptoStore: add methods for importing and exporting EncryptedPrivateKeyInfo, r=cfu
|
|
|
aee1ec |
|
|
|
aee1ec |
diff --git a/lib/jss.def b/lib/jss.def
|
|
|
aee1ec |
--- a/lib/jss.def
|
|
|
aee1ec |
+++ b/lib/jss.def
|
|
|
aee1ec |
@@ -324,3 +324,9 @@
|
|
|
aee1ec |
;+ local:
|
|
|
aee1ec |
;+ *;
|
|
|
aee1ec |
;+};
|
|
|
aee1ec |
+;+JSS_4.4.1 { # JSS 4.4.1 release
|
|
|
aee1ec |
+;+ global:
|
|
|
aee1ec |
+Java_org_mozilla_jss_pkcs11_PK11Store_importEncryptedPrivateKeyInfo;
|
|
|
aee1ec |
+;+ local:
|
|
|
aee1ec |
+;+ *;
|
|
|
aee1ec |
+;+};
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/Algorithm.c b/org/mozilla/jss/crypto/Algorithm.c
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/Algorithm.c
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/Algorithm.c
|
|
|
aee1ec |
@@ -86,7 +86,13 @@
|
|
|
aee1ec |
/* 55 */ {SEC_OID_PKCS5_PBMAC1, SEC_OID_TAG},
|
|
|
aee1ec |
/* 56 */ {SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST, SEC_OID_TAG},
|
|
|
aee1ec |
/* 57 */ {CKM_NSS_AES_KEY_WRAP, PK11_MECH},
|
|
|
aee1ec |
-/* 58 */ {CKM_NSS_AES_KEY_WRAP_PAD, PK11_MECH}
|
|
|
aee1ec |
+/* 58 */ {CKM_NSS_AES_KEY_WRAP_PAD, PK11_MECH},
|
|
|
aee1ec |
+/* 59 */ {SEC_OID_AES_128_ECB, SEC_OID_TAG},
|
|
|
aee1ec |
+/* 60 */ {SEC_OID_AES_128_CBC, SEC_OID_TAG},
|
|
|
aee1ec |
+/* 61 */ {SEC_OID_AES_192_ECB, SEC_OID_TAG},
|
|
|
aee1ec |
+/* 62 */ {SEC_OID_AES_192_CBC, SEC_OID_TAG},
|
|
|
aee1ec |
+/* 63 */ {SEC_OID_AES_256_ECB, SEC_OID_TAG},
|
|
|
aee1ec |
+/* 64 */ {SEC_OID_AES_256_CBC, SEC_OID_TAG}
|
|
|
aee1ec |
/* REMEMBER TO UPDATE NUM_ALGS!!! */
|
|
|
aee1ec |
};
|
|
|
aee1ec |
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/Algorithm.h b/org/mozilla/jss/crypto/Algorithm.h
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/Algorithm.h
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/Algorithm.h
|
|
|
aee1ec |
@@ -24,7 +24,7 @@
|
|
|
aee1ec |
JSS_AlgType type;
|
|
|
aee1ec |
} JSS_AlgInfo;
|
|
|
aee1ec |
|
|
|
aee1ec |
-#define NUM_ALGS 59
|
|
|
aee1ec |
+#define NUM_ALGS 65
|
|
|
aee1ec |
|
|
|
aee1ec |
extern JSS_AlgInfo JSS_AlgTable[];
|
|
|
aee1ec |
extern CK_ULONG JSS_symkeyUsage[];
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/Algorithm.java b/org/mozilla/jss/crypto/Algorithm.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/Algorithm.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/Algorithm.java
|
|
|
aee1ec |
@@ -212,4 +212,12 @@
|
|
|
aee1ec |
protected static final short SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST=56;
|
|
|
aee1ec |
protected static final short CKM_NSS_AES_KEY_WRAP=57;
|
|
|
aee1ec |
protected static final short CKM_NSS_AES_KEY_WRAP_PAD=58;
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // AES Encryption Algorithms
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_128_ECB = 59;
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_128_CBC = 60;
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_192_ECB = 61;
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_192_CBC = 62;
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_256_ECB = 63;
|
|
|
aee1ec |
+ protected static final short SEC_OID_AES_256_CBC = 64;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/CryptoStore.java b/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
@@ -4,6 +4,7 @@
|
|
|
aee1ec |
|
|
|
aee1ec |
package org.mozilla.jss.crypto;
|
|
|
aee1ec |
|
|
|
aee1ec |
+import org.mozilla.jss.CryptoManager;
|
|
|
aee1ec |
import org.mozilla.jss.util.*;
|
|
|
aee1ec |
import java.security.*;
|
|
|
aee1ec |
import java.security.cert.CertificateEncodingException;
|
|
|
aee1ec |
@@ -68,9 +69,50 @@
|
|
|
aee1ec |
public void deletePrivateKey(org.mozilla.jss.crypto.PrivateKey key)
|
|
|
aee1ec |
throws NoSuchItemOnTokenException, TokenException;
|
|
|
aee1ec |
|
|
|
aee1ec |
+ /**
|
|
|
aee1ec |
+ * Get an encrypted private key for the given cert.
|
|
|
aee1ec |
+ *
|
|
|
aee1ec |
+ * @param cert Certificate of key to be exported
|
|
|
aee1ec |
+ * @param pbeAlg The PBEAlgorithm to use
|
|
|
aee1ec |
+ * @param pw The password to encrypt with
|
|
|
aee1ec |
+ * @param iteration Iteration count; default of 2000 if le 0
|
|
|
aee1ec |
+ */
|
|
|
aee1ec |
+ public byte[] getEncryptedPrivateKeyInfo(X509Certificate cert,
|
|
|
aee1ec |
+ PBEAlgorithm pbeAlg, Password pw, int iteration)
|
|
|
aee1ec |
+ throws CryptoManager.NotInitializedException,
|
|
|
aee1ec |
+ ObjectNotFoundException, TokenException;
|
|
|
aee1ec |
|
|
|
aee1ec |
- public byte[] getEncryptedPrivateKeyInfo(X509Certificate cert,
|
|
|
aee1ec |
- PBEAlgorithm pbeAlg, Password pw, int iteration);
|
|
|
aee1ec |
+ /**
|
|
|
aee1ec |
+ * Get an encrypted private key, with optional password
|
|
|
aee1ec |
+ * conversion.
|
|
|
aee1ec |
+ *
|
|
|
aee1ec |
+ * @param conv Password converter. If null, pw.getByteCopy()
|
|
|
aee1ec |
+ * will be used to get password bytes.
|
|
|
aee1ec |
+ * @param pw The password
|
|
|
aee1ec |
+ * @param alg The encryption algorithm
|
|
|
aee1ec |
+ * @param n Iteration count; default of 2000 if le 0
|
|
|
aee1ec |
+ * @param k The private key
|
|
|
aee1ec |
+ */
|
|
|
aee1ec |
+ public byte[] getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ KeyGenerator.CharToByteConverter conv,
|
|
|
aee1ec |
+ Password pw,
|
|
|
aee1ec |
+ Algorithm alg,
|
|
|
aee1ec |
+ int n,
|
|
|
aee1ec |
+ PrivateKey k);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ /**
|
|
|
aee1ec |
+ * @param conv Password converter. If null, pw.getByteCopy()
|
|
|
aee1ec |
+ * will be used to get password bytes.
|
|
|
aee1ec |
+ * @param pw The password
|
|
|
aee1ec |
+ * @param nickname Nickname to use for private key
|
|
|
aee1ec |
+ * @param pubKey Public key corresponding to private key
|
|
|
aee1ec |
+ */
|
|
|
aee1ec |
+ public void importEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ KeyGenerator.CharToByteConverter conv,
|
|
|
aee1ec |
+ Password pw,
|
|
|
aee1ec |
+ String nickname,
|
|
|
aee1ec |
+ PublicKey pubKey,
|
|
|
aee1ec |
+ byte[] epkiBytes);
|
|
|
aee1ec |
|
|
|
aee1ec |
////////////////////////////////////////////////////////////
|
|
|
aee1ec |
// Certs
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/EncryptionAlgorithm.java b/org/mozilla/jss/crypto/EncryptionAlgorithm.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/EncryptionAlgorithm.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/EncryptionAlgorithm.java
|
|
|
aee1ec |
@@ -347,12 +347,14 @@
|
|
|
aee1ec |
{ 2, 16, 840, 1, 101, 3, 4, 1 } );
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_128_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
|
|
aee1ec |
+ AES_128_ECB = new EncryptionAlgorithm(SEC_OID_AES_128_ECB,
|
|
|
aee1ec |
+ Alg.AES, Mode.ECB,
|
|
|
aee1ec |
Padding.NONE, (Class)null, 16,
|
|
|
aee1ec |
AES_ROOT_OID.subBranch(1), 128);
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_128_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
|
|
aee1ec |
+ AES_128_CBC = new EncryptionAlgorithm(SEC_OID_AES_128_CBC,
|
|
|
aee1ec |
+ Alg.AES, Mode.CBC,
|
|
|
aee1ec |
Padding.NONE, IVParameterSpecClasses, 16,
|
|
|
aee1ec |
AES_ROOT_OID.subBranch(2), 128);
|
|
|
aee1ec |
|
|
|
aee1ec |
@@ -361,11 +363,13 @@
|
|
|
aee1ec |
Padding.PKCS5, IVParameterSpecClasses, 16, null, 128); // no oid
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_192_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
|
|
aee1ec |
+ AES_192_ECB = new EncryptionAlgorithm(SEC_OID_AES_192_ECB,
|
|
|
aee1ec |
+ Alg.AES, Mode.ECB,
|
|
|
aee1ec |
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(21), 192);
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_192_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
|
|
aee1ec |
+ AES_192_CBC = new EncryptionAlgorithm(SEC_OID_AES_192_CBC,
|
|
|
aee1ec |
+ Alg.AES, Mode.CBC,
|
|
|
aee1ec |
Padding.NONE, IVParameterSpecClasses, 16,
|
|
|
aee1ec |
AES_ROOT_OID.subBranch(22), 192);
|
|
|
aee1ec |
|
|
|
aee1ec |
@@ -374,11 +378,13 @@
|
|
|
aee1ec |
Padding.PKCS5, IVParameterSpecClasses, 16, null, 192); // no oid
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_256_ECB = new EncryptionAlgorithm(CKM_AES_ECB, Alg.AES, Mode.ECB,
|
|
|
aee1ec |
+ AES_256_ECB = new EncryptionAlgorithm(SEC_OID_AES_256_ECB,
|
|
|
aee1ec |
+ Alg.AES, Mode.ECB,
|
|
|
aee1ec |
Padding.NONE, (Class)null, 16, AES_ROOT_OID.subBranch(41), 256);
|
|
|
aee1ec |
|
|
|
aee1ec |
public static final EncryptionAlgorithm
|
|
|
aee1ec |
- AES_256_CBC = new EncryptionAlgorithm(CKM_AES_CBC, Alg.AES, Mode.CBC,
|
|
|
aee1ec |
+ AES_256_CBC = new EncryptionAlgorithm(SEC_OID_AES_256_CBC,
|
|
|
aee1ec |
+ Alg.AES, Mode.CBC,
|
|
|
aee1ec |
Padding.NONE, IVParameterSpecClasses, 16,
|
|
|
aee1ec |
AES_ROOT_OID.subBranch(42), 256);
|
|
|
aee1ec |
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/pkcs11/PK11Store.c b/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
--- a/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
+++ b/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
@@ -31,6 +31,8 @@
|
|
|
aee1ec |
char *data;
|
|
|
aee1ec |
} secuPWData;
|
|
|
aee1ec |
|
|
|
aee1ec |
+SECItem *preparePassword(JNIEnv *env, jobject conv, jobject pwObj);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
/**********************************************************************
|
|
|
aee1ec |
* PK11Store.putSymKeysInVector
|
|
|
aee1ec |
*/
|
|
|
aee1ec |
@@ -533,103 +535,293 @@
|
|
|
aee1ec |
|
|
|
aee1ec |
|
|
|
aee1ec |
JNIEXPORT jbyteArray JNICALL
|
|
|
aee1ec |
-Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo
|
|
|
aee1ec |
-(JNIEnv *env, jobject this, jobject certObj, jobject algObj,
|
|
|
aee1ec |
- jobject pwObj, jint iteration)
|
|
|
aee1ec |
+Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ JNIEnv *env,
|
|
|
aee1ec |
+ jobject this,
|
|
|
aee1ec |
+ jobject conv,
|
|
|
aee1ec |
+ jobject pwObj,
|
|
|
aee1ec |
+ jobject algObj,
|
|
|
aee1ec |
+ jint iterations,
|
|
|
aee1ec |
+ jobject key)
|
|
|
aee1ec |
+{
|
|
|
aee1ec |
+ // initialisations so we can goto finish
|
|
|
aee1ec |
+ SECItem *pwItem = NULL;
|
|
|
aee1ec |
+ SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
|
|
aee1ec |
+ SECItem epkiItem;
|
|
|
aee1ec |
+ epkiItem.data = NULL;
|
|
|
aee1ec |
+ epkiItem.len = 0;
|
|
|
aee1ec |
|
|
|
aee1ec |
-{
|
|
|
aee1ec |
- SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
|
|
aee1ec |
- jbyteArray encodedEpki = NULL;
|
|
|
aee1ec |
+ PR_ASSERT(env != NULL && this != NULL);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ if (pwObj == NULL || algObj == NULL || key == NULL) {
|
|
|
aee1ec |
+ JSS_throw(env, NULL_POINTER_EXCEPTION);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ if (iterations <= 0) {
|
|
|
aee1ec |
+ iterations = 2000; // set default iterations
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // get slot
|
|
|
aee1ec |
PK11SlotInfo *slot = NULL;
|
|
|
aee1ec |
- SECOidTag algTag;
|
|
|
aee1ec |
- jclass passwordClass = NULL;
|
|
|
aee1ec |
- jmethodID getByteCopyMethod = NULL;
|
|
|
aee1ec |
- jbyteArray pwArray = NULL;
|
|
|
aee1ec |
- jbyte* pwchars = NULL;
|
|
|
aee1ec |
- SECItem pwItem;
|
|
|
aee1ec |
- CERTCertificate *cert = NULL;
|
|
|
aee1ec |
- SECItem epkiItem;
|
|
|
aee1ec |
-
|
|
|
aee1ec |
- epkiItem.data = NULL;
|
|
|
aee1ec |
-
|
|
|
aee1ec |
- /* get slot */
|
|
|
aee1ec |
if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) {
|
|
|
aee1ec |
ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
PR_ASSERT(slot!=NULL);
|
|
|
aee1ec |
-
|
|
|
aee1ec |
- /* get algorithm */
|
|
|
aee1ec |
- algTag = JSS_getOidTagFromAlg(env, algObj);
|
|
|
aee1ec |
- if( algTag == SEC_OID_UNKNOWN ) {
|
|
|
aee1ec |
- JSS_throwMsg(env, NO_SUCH_ALG_EXCEPTION, "Unrecognized PBE algorithm");
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // get algorithm
|
|
|
aee1ec |
+ SECOidTag algTag = JSS_getOidTagFromAlg(env, algObj);
|
|
|
aee1ec |
+ if (algTag == SEC_OID_UNKNOWN) {
|
|
|
aee1ec |
+ JSS_throwMsg(env, NO_SUCH_ALG_EXCEPTION, "Unrecognized algorithm");
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
|
|
|
aee1ec |
- /*
|
|
|
aee1ec |
- * get password
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
- passwordClass = (*env)->GetObjectClass(env, pwObj);
|
|
|
aee1ec |
- if(passwordClass == NULL) {
|
|
|
aee1ec |
- ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
- goto finish;
|
|
|
aee1ec |
- }
|
|
|
aee1ec |
- getByteCopyMethod = (*env)->GetMethodID(
|
|
|
aee1ec |
- env,
|
|
|
aee1ec |
- passwordClass,
|
|
|
aee1ec |
- PW_GET_BYTE_COPY_NAME,
|
|
|
aee1ec |
- PW_GET_BYTE_COPY_SIG);
|
|
|
aee1ec |
- if(getByteCopyMethod==NULL) {
|
|
|
aee1ec |
+ pwItem = preparePassword(env, conv, pwObj);
|
|
|
aee1ec |
+ if (pwItem == NULL) {
|
|
|
aee1ec |
ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
- pwArray = (*env)->CallObjectMethod( env, pwObj, getByteCopyMethod);
|
|
|
aee1ec |
- pwchars = (*env)->GetByteArrayElements(env, pwArray, NULL);
|
|
|
aee1ec |
- /* !!! Include the NULL byte or not? */
|
|
|
aee1ec |
- pwItem.data = (unsigned char*) pwchars;
|
|
|
aee1ec |
- pwItem.len = strlen((const char*)pwchars) + 1;
|
|
|
aee1ec |
|
|
|
aee1ec |
- /*
|
|
|
aee1ec |
- * get cert
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
- if( JSS_PK11_getCertPtr(env, certObj, &cert) != PR_SUCCESS ) {
|
|
|
aee1ec |
- /* exception was thrown */
|
|
|
aee1ec |
+ // get key
|
|
|
aee1ec |
+ SECKEYPrivateKey *privk;
|
|
|
aee1ec |
+ if (JSS_PK11_getPrivKeyPtr(env, key, &privk) != PR_SUCCESS) {
|
|
|
aee1ec |
+ PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL);
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
|
|
|
aee1ec |
- /*
|
|
|
aee1ec |
- * export the epki
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
- epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algTag, &pwItem,
|
|
|
aee1ec |
- cert, iteration, NULL /*wincx*/);
|
|
|
aee1ec |
-
|
|
|
aee1ec |
+ // export the epki
|
|
|
aee1ec |
+ epki = PK11_ExportEncryptedPrivKeyInfo(
|
|
|
aee1ec |
+ slot, algTag, pwItem, privk, iterations, NULL /*wincx*/);
|
|
|
aee1ec |
|
|
|
aee1ec |
- /*
|
|
|
aee1ec |
- * DER-encode the epki
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
- epkiItem.data = NULL;
|
|
|
aee1ec |
- epkiItem.len = 0;
|
|
|
aee1ec |
- if( SEC_ASN1EncodeItem(NULL, &epkiItem, epki,
|
|
|
aee1ec |
- SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate) ) == NULL ) {
|
|
|
aee1ec |
- JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to ASN1-encode "
|
|
|
aee1ec |
- "EncryptedPrivateKeyInfo");
|
|
|
aee1ec |
+ // DER-encode the epki
|
|
|
aee1ec |
+ if (SEC_ASN1EncodeItem(NULL, &epkiItem, epki,
|
|
|
aee1ec |
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)) == NULL) {
|
|
|
aee1ec |
+ JSS_throwMsg(
|
|
|
aee1ec |
+ env, TOKEN_EXCEPTION,
|
|
|
aee1ec |
+ "Failed to ASN1-encode EncryptedPrivateKeyInfo");
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
|
|
|
aee1ec |
- /*
|
|
|
aee1ec |
- * convert to Java byte array
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
- encodedEpki = JSS_SECItemToByteArray(env, &epkiItem);
|
|
|
aee1ec |
+ // convert to Java byte array
|
|
|
aee1ec |
+ jbyteArray encodedEpki = JSS_SECItemToByteArray(env, &epkiItem);
|
|
|
aee1ec |
|
|
|
aee1ec |
finish:
|
|
|
aee1ec |
- if( epki != NULL ) {
|
|
|
aee1ec |
+ if (epki != NULL) {
|
|
|
aee1ec |
SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
}
|
|
|
aee1ec |
- if( pwchars != NULL ) {
|
|
|
aee1ec |
- (*env)->ReleaseByteArrayElements(env, pwArray, pwchars, JNI_ABORT);
|
|
|
aee1ec |
+ if (epkiItem.data != NULL) {
|
|
|
aee1ec |
+ SECITEM_FreeItem(&epkiItem, PR_FALSE /*freeit*/);
|
|
|
aee1ec |
}
|
|
|
aee1ec |
- if(epkiItem.data != NULL) {
|
|
|
aee1ec |
- PR_Free(epkiItem.data);
|
|
|
aee1ec |
+ if (pwItem != NULL) {
|
|
|
aee1ec |
+ SECITEM_FreeItem(pwItem, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
}
|
|
|
aee1ec |
return encodedEpki;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+JNIEXPORT void JNICALL
|
|
|
aee1ec |
+Java_org_mozilla_jss_pkcs11_PK11Store_importEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ JNIEnv *env,
|
|
|
aee1ec |
+ jobject this,
|
|
|
aee1ec |
+ jobject conv,
|
|
|
aee1ec |
+ jobject pwObj,
|
|
|
aee1ec |
+ jstring nickname,
|
|
|
aee1ec |
+ jobject pubKeyObj,
|
|
|
aee1ec |
+ jbyteArray epkiBytes)
|
|
|
aee1ec |
+{
|
|
|
aee1ec |
+ // initialisations so we can goto finish
|
|
|
aee1ec |
+ SECItem *epkiItem = NULL;
|
|
|
aee1ec |
+ SECKEYEncryptedPrivateKeyInfo *epki = NULL;
|
|
|
aee1ec |
+ SECItem *pwItem = NULL;
|
|
|
aee1ec |
+ SECItem *spkiItem = NULL;
|
|
|
aee1ec |
+ CERTSubjectPublicKeyInfo *spki = NULL;
|
|
|
aee1ec |
+ SECKEYPublicKey *pubKey = NULL;
|
|
|
aee1ec |
+ const char *nicknameChars = NULL;
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ PR_ASSERT(env != NULL && this != NULL);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ if (pwObj == NULL || nickname == NULL || pubKeyObj == NULL) {
|
|
|
aee1ec |
+ JSS_throw(env, NULL_POINTER_EXCEPTION);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // get slot
|
|
|
aee1ec |
+ PK11SlotInfo *slot = NULL;
|
|
|
aee1ec |
+ if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ PR_ASSERT(slot != NULL);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // decode EncryptedPrivateKeyInfo
|
|
|
aee1ec |
+ epkiItem = JSS_ByteArrayToSECItem(env, epkiBytes);
|
|
|
aee1ec |
+ epki = PR_Calloc(1, sizeof(SECKEYEncryptedPrivateKeyInfo));
|
|
|
aee1ec |
+ if (SEC_ASN1DecodeItem(
|
|
|
aee1ec |
+ NULL,
|
|
|
aee1ec |
+ epki,
|
|
|
aee1ec |
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate),
|
|
|
aee1ec |
+ epkiItem
|
|
|
aee1ec |
+ ) != SECSuccess) {
|
|
|
aee1ec |
+ JSS_throwMsg(env, INVALID_DER_EXCEPTION,
|
|
|
aee1ec |
+ "Failed to decode EncryptedPrivateKeyInfo");
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ pwItem = preparePassword(env, conv, pwObj);
|
|
|
aee1ec |
+ if (pwItem == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // get public key value
|
|
|
aee1ec |
+ jclass pubKeyClass = (*env)->GetObjectClass(env, pubKeyObj);
|
|
|
aee1ec |
+ if (pubKeyClass == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ jmethodID getEncoded = (*env)->GetMethodID(
|
|
|
aee1ec |
+ env, pubKeyClass, "getEncoded", "()[B");
|
|
|
aee1ec |
+ if (getEncoded == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ jbyteArray spkiBytes = (*env)->CallObjectMethod(
|
|
|
aee1ec |
+ env, pubKeyObj, getEncoded);
|
|
|
aee1ec |
+ spkiItem = JSS_ByteArrayToSECItem(env, spkiBytes);
|
|
|
aee1ec |
+ spki = PR_Calloc(1, sizeof(CERTSubjectPublicKeyInfo));
|
|
|
aee1ec |
+ if (SEC_ASN1DecodeItem(
|
|
|
aee1ec |
+ NULL,
|
|
|
aee1ec |
+ spki,
|
|
|
aee1ec |
+ SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
|
|
|
aee1ec |
+ spkiItem
|
|
|
aee1ec |
+ ) != SECSuccess) {
|
|
|
aee1ec |
+ JSS_throwMsg(env, INVALID_DER_EXCEPTION,
|
|
|
aee1ec |
+ "Failed to decode SubjectPublicKeyInfo");
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ pubKey = SECKEY_ExtractPublicKey(spki);
|
|
|
aee1ec |
+ if (pubKey == NULL) {
|
|
|
aee1ec |
+ JSS_throwMsgPrErr(env, INVALID_DER_EXCEPTION,
|
|
|
aee1ec |
+ "Failed to extract public key from SubjectPublicKeyInfo");
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ SECItem *pubValue;
|
|
|
aee1ec |
+ switch (pubKey->keyType) {
|
|
|
aee1ec |
+ case dsaKey:
|
|
|
aee1ec |
+ pubValue = &pubKey->u.dsa.publicValue;
|
|
|
aee1ec |
+ break;
|
|
|
aee1ec |
+ case dhKey:
|
|
|
aee1ec |
+ pubValue = &pubKey->u.dh.publicValue;
|
|
|
aee1ec |
+ break;
|
|
|
aee1ec |
+ case rsaKey:
|
|
|
aee1ec |
+ pubValue = &pubKey->u.rsa.modulus;
|
|
|
aee1ec |
+ break;
|
|
|
aee1ec |
+ case ecKey:
|
|
|
aee1ec |
+ pubValue = &pubKey->u.ec.publicValue;
|
|
|
aee1ec |
+ break;
|
|
|
aee1ec |
+ default:
|
|
|
aee1ec |
+ pubValue = NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // prepare nickname
|
|
|
aee1ec |
+ nicknameChars = (*env)->GetStringUTFChars(env, nickname, NULL);
|
|
|
aee1ec |
+ if (nicknameChars == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ SECItem nickItem;
|
|
|
aee1ec |
+ nickItem.data = nicknameChars;
|
|
|
aee1ec |
+ nickItem.len = (*env)->GetStringUTFLength(env, nickname);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // if keyUsage = 0, defaults to signing and encryption/key agreement.
|
|
|
aee1ec |
+ // see pk11akey.c in NSS
|
|
|
aee1ec |
+ int keyUsage = 0;
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ // perform import
|
|
|
aee1ec |
+ SECStatus result = PK11_ImportEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ slot, epki, pwItem, &nickItem, pubValue,
|
|
|
aee1ec |
+ PR_TRUE /* isperm */, PR_TRUE /* isprivate */,
|
|
|
aee1ec |
+ pubKey->keyType, keyUsage, NULL /* wincx */);
|
|
|
aee1ec |
+ if (result != SECSuccess) {
|
|
|
aee1ec |
+ JSS_throwMsg(
|
|
|
aee1ec |
+ env, TOKEN_EXCEPTION,
|
|
|
aee1ec |
+ "Failed to import EncryptedPrivateKeyInfo to token");
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+finish:
|
|
|
aee1ec |
+ if (epkiItem != NULL) {
|
|
|
aee1ec |
+ SECITEM_FreeItem(epkiItem, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (epki != NULL) {
|
|
|
aee1ec |
+ SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (spkiItem != NULL) {
|
|
|
aee1ec |
+ SECITEM_FreeItem(spkiItem, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (spki != NULL) {
|
|
|
aee1ec |
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (pwItem != NULL) {
|
|
|
aee1ec |
+ SECITEM_FreeItem(pwItem, PR_TRUE /*freeit*/);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (pubKey != NULL) {
|
|
|
aee1ec |
+ SECKEY_DestroyPublicKey(pubKey);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ if (nicknameChars != NULL) {
|
|
|
aee1ec |
+ (*env)->ReleaseStringUTFChars(env, nickname, nicknameChars);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+}
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+/* Process the given password through the given PasswordConverter,
|
|
|
aee1ec |
+ * returning a new SECItem* on success.
|
|
|
aee1ec |
+ *
|
|
|
aee1ec |
+ * After use, the caller should free the SECItem:
|
|
|
aee1ec |
+ *
|
|
|
aee1ec |
+ * SECITEM_FreeItem(pwItem, PR_TRUE).
|
|
|
aee1ec |
+ */
|
|
|
aee1ec |
+SECItem *preparePassword(JNIEnv *env, jobject conv, jobject pwObj) {
|
|
|
aee1ec |
+ jclass passwordClass = (*env)->GetObjectClass(env, pwObj);
|
|
|
aee1ec |
+ if (passwordClass == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ return NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ jbyteArray pwBytes;
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ if (conv == NULL) {
|
|
|
aee1ec |
+ jmethodID getByteCopy = (*env)->GetMethodID(
|
|
|
aee1ec |
+ env, passwordClass, PW_GET_BYTE_COPY_NAME, PW_GET_BYTE_COPY_SIG);
|
|
|
aee1ec |
+ if (getByteCopy == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ return NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ pwBytes = (*env)->CallObjectMethod(env, pwObj, getByteCopy);
|
|
|
aee1ec |
+ } else {
|
|
|
aee1ec |
+ jmethodID getChars = (*env)->GetMethodID(
|
|
|
aee1ec |
+ env, passwordClass, "getChars", "()[C");
|
|
|
aee1ec |
+ if (getChars == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ return NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ jcharArray pwChars = (*env)->CallObjectMethod(env, pwObj, getChars);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ jclass convClass = (*env)->GetObjectClass(env, conv);
|
|
|
aee1ec |
+ if (conv == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ return NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ jmethodID convert = (*env)->GetMethodID(
|
|
|
aee1ec |
+ env, convClass, "convert", "([C)[B");
|
|
|
aee1ec |
+ if (convert == NULL) {
|
|
|
aee1ec |
+ ASSERT_OUTOFMEM(env);
|
|
|
aee1ec |
+ return NULL;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+ pwBytes = (*env)->CallObjectMethod(env, conv, convert, pwChars);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ return JSS_ByteArrayToSECItem(env, pwBytes);
|
|
|
aee1ec |
+}
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/pkcs11/PK11Store.java b/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
@@ -4,8 +4,10 @@
|
|
|
aee1ec |
|
|
|
aee1ec |
package org.mozilla.jss.pkcs11;
|
|
|
aee1ec |
|
|
|
aee1ec |
+import org.mozilla.jss.CryptoManager;
|
|
|
aee1ec |
import org.mozilla.jss.crypto.*;
|
|
|
aee1ec |
import org.mozilla.jss.util.*;
|
|
|
aee1ec |
+import java.security.PublicKey;
|
|
|
aee1ec |
import java.security.cert.CertificateEncodingException;
|
|
|
aee1ec |
import java.util.Vector;
|
|
|
aee1ec |
|
|
|
aee1ec |
@@ -53,8 +55,35 @@
|
|
|
aee1ec |
public native void deletePrivateKey(PrivateKey key)
|
|
|
aee1ec |
throws NoSuchItemOnTokenException, TokenException;
|
|
|
aee1ec |
|
|
|
aee1ec |
- public native byte[] getEncryptedPrivateKeyInfo(X509Certificate cert,
|
|
|
aee1ec |
- PBEAlgorithm pbeAlg, Password pw, int iteration);
|
|
|
aee1ec |
+ public byte[] getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ X509Certificate cert,
|
|
|
aee1ec |
+ PBEAlgorithm pbeAlg,
|
|
|
aee1ec |
+ Password pw,
|
|
|
aee1ec |
+ int iteration)
|
|
|
aee1ec |
+ throws CryptoManager.NotInitializedException,
|
|
|
aee1ec |
+ ObjectNotFoundException, TokenException {
|
|
|
aee1ec |
+ return getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ null,
|
|
|
aee1ec |
+ pw,
|
|
|
aee1ec |
+ pbeAlg,
|
|
|
aee1ec |
+ iteration,
|
|
|
aee1ec |
+ CryptoManager.getInstance().findPrivKeyByCert(cert)
|
|
|
aee1ec |
+ );
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ public native byte[] getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ KeyGenerator.CharToByteConverter conv,
|
|
|
aee1ec |
+ Password pw,
|
|
|
aee1ec |
+ Algorithm alg,
|
|
|
aee1ec |
+ int n,
|
|
|
aee1ec |
+ PrivateKey k);
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ public native void importEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
+ KeyGenerator.CharToByteConverter conv,
|
|
|
aee1ec |
+ Password pw,
|
|
|
aee1ec |
+ String nickname,
|
|
|
aee1ec |
+ PublicKey pubKey,
|
|
|
aee1ec |
+ byte[] epkiBytes);
|
|
|
aee1ec |
|
|
|
aee1ec |
////////////////////////////////////////////////////////////
|
|
|
aee1ec |
// Certs
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/util/jss_exceptions.h b/org/mozilla/jss/util/jss_exceptions.h
|
|
|
aee1ec |
--- a/org/mozilla/jss/util/jss_exceptions.h
|
|
|
aee1ec |
+++ b/org/mozilla/jss/util/jss_exceptions.h
|
|
|
aee1ec |
@@ -47,6 +47,8 @@
|
|
|
aee1ec |
|
|
|
aee1ec |
#define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException"
|
|
|
aee1ec |
|
|
|
aee1ec |
+#define INVALID_DER_EXCEPTION "org/mozilla/jss/crypto/InvalidDERException"
|
|
|
aee1ec |
+
|
|
|
aee1ec |
#define INVALID_NICKNAME_EXCEPTION "org/mozilla/jss/util/InvalidNicknameException"
|
|
|
aee1ec |
|
|
|
aee1ec |
#define INVALID_KEY_FORMAT_EXCEPTION "org/mozilla/jss/crypto/InvalidKeyFormatException"
|
|
|
aee1ec |
# HG changeset patch
|
|
|
aee1ec |
# User Fraser Tweedale <ftweedal@redhat.com>
|
|
|
aee1ec |
# Date 1493335326 25200
|
|
|
aee1ec |
# Thu Apr 27 16:22:06 2017 -0700
|
|
|
aee1ec |
# Node ID ead2ea094c98ddc708169c3de411ca8d8883cab8
|
|
|
aee1ec |
# Parent c8885dd6787639d74a1c9d634fd289ff17fa6f02
|
|
|
aee1ec |
Bug 1359731 - CryptoStore.importPrivateKey enhancements, r=cfu
|
|
|
aee1ec |
|
|
|
aee1ec |
- Enhance CryptoStore.importPrivateKey to support temporary import, and
|
|
|
aee1ec |
- returning the private key to the caller.
|
|
|
aee1ec |
- Also remove some validation of the unused keyType argument.
|
|
|
aee1ec |
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/crypto/CryptoStore.java b/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/crypto/CryptoStore.java
|
|
|
aee1ec |
@@ -21,17 +21,30 @@
|
|
|
aee1ec |
////////////////////////////////////////////////////////////
|
|
|
aee1ec |
|
|
|
aee1ec |
/**
|
|
|
aee1ec |
- * Imports a raw private key into this token.
|
|
|
aee1ec |
+ * Imports a raw private key into this token (permanently).
|
|
|
aee1ec |
*
|
|
|
aee1ec |
* @param key The private key.
|
|
|
aee1ec |
* @exception TokenException If the key cannot be imported to this token.
|
|
|
aee1ec |
* @exception KeyAlreadyImportedException If the key already exists on this token.
|
|
|
aee1ec |
*/
|
|
|
aee1ec |
- public void
|
|
|
aee1ec |
+ public PrivateKey
|
|
|
aee1ec |
importPrivateKey( byte[] key,
|
|
|
aee1ec |
PrivateKey.Type type )
|
|
|
aee1ec |
throws TokenException, KeyAlreadyImportedException;
|
|
|
aee1ec |
|
|
|
aee1ec |
+ /**
|
|
|
aee1ec |
+ * Imports a raw private key into this token.
|
|
|
aee1ec |
+ *
|
|
|
aee1ec |
+ * @param key The private key.
|
|
|
aee1ec |
+ * @param temporary Whether the key should be temporary.
|
|
|
aee1ec |
+ * @exception TokenException If the key cannot be imported to this token.
|
|
|
aee1ec |
+ * @exception KeyAlreadyImportedException If the key already exists on this token.
|
|
|
aee1ec |
+ */
|
|
|
aee1ec |
+ public PrivateKey
|
|
|
aee1ec |
+ importPrivateKey( byte[] key,
|
|
|
aee1ec |
+ PrivateKey.Type type, boolean temporary)
|
|
|
aee1ec |
+ throws TokenException, KeyAlreadyImportedException;
|
|
|
aee1ec |
+
|
|
|
aee1ec |
|
|
|
aee1ec |
/**
|
|
|
aee1ec |
* Returns all private keys stored on this token.
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/pkcs11/PK11Store.c b/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
--- a/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
+++ b/org/mozilla/jss/pkcs11/PK11Store.c
|
|
|
aee1ec |
@@ -429,22 +429,22 @@
|
|
|
aee1ec |
int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int);
|
|
|
aee1ec |
|
|
|
aee1ec |
/***********************************************************************
|
|
|
aee1ec |
- * importPrivateKey
|
|
|
aee1ec |
+ * PK11Store.importdPrivateKey
|
|
|
aee1ec |
*/
|
|
|
aee1ec |
-static void
|
|
|
aee1ec |
-importPrivateKey
|
|
|
aee1ec |
+JNIEXPORT jobject JNICALL
|
|
|
aee1ec |
+Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey
|
|
|
aee1ec |
( JNIEnv *env,
|
|
|
aee1ec |
jobject this,
|
|
|
aee1ec |
jbyteArray keyArray,
|
|
|
aee1ec |
jobject keyTypeObj,
|
|
|
aee1ec |
- PRBool temporary )
|
|
|
aee1ec |
+ jboolean temporary )
|
|
|
aee1ec |
{
|
|
|
aee1ec |
SECItem derPK;
|
|
|
aee1ec |
PK11SlotInfo *slot;
|
|
|
aee1ec |
jthrowable excep;
|
|
|
aee1ec |
- KeyType keyType;
|
|
|
aee1ec |
SECStatus status;
|
|
|
aee1ec |
SECItem nickname;
|
|
|
aee1ec |
+ jobject privkObj = NULL;
|
|
|
aee1ec |
|
|
|
aee1ec |
/*
|
|
|
aee1ec |
* initialize so we can goto finish
|
|
|
aee1ec |
@@ -452,13 +452,6 @@
|
|
|
aee1ec |
derPK.data = NULL;
|
|
|
aee1ec |
derPK.len = 0;
|
|
|
aee1ec |
|
|
|
aee1ec |
-
|
|
|
aee1ec |
- keyType = JSS_PK11_getKeyType(env, keyTypeObj);
|
|
|
aee1ec |
- if( keyType == nullKey ) {
|
|
|
aee1ec |
- /* exception was thrown */
|
|
|
aee1ec |
- goto finish;
|
|
|
aee1ec |
- }
|
|
|
aee1ec |
-
|
|
|
aee1ec |
PR_ASSERT(env!=NULL && this!=NULL);
|
|
|
aee1ec |
|
|
|
aee1ec |
if(keyArray == NULL) {
|
|
|
aee1ec |
@@ -492,14 +485,22 @@
|
|
|
aee1ec |
nickname.len = 0;
|
|
|
aee1ec |
nickname.data = NULL;
|
|
|
aee1ec |
|
|
|
aee1ec |
- status = PK11_ImportDERPrivateKeyInfo(slot, &derPK, &nickname,
|
|
|
aee1ec |
- NULL /*public value*/, PR_TRUE /*isPerm*/,
|
|
|
aee1ec |
- PR_TRUE /*isPrivate*/, 0 /*keyUsage*/, NULL /*wincx*/);
|
|
|
aee1ec |
+ SECKEYPrivateKey *privk = NULL;
|
|
|
aee1ec |
+ status = PK11_ImportDERPrivateKeyInfoAndReturnKey(
|
|
|
aee1ec |
+ slot, &derPK, &nickname,
|
|
|
aee1ec |
+ NULL /*public value*/, !temporary /*isPerm*/,
|
|
|
aee1ec |
+ PR_TRUE /*isPrivate*/, 0 /*keyUsage*/,
|
|
|
aee1ec |
+ &privk, NULL /*wincx*/);
|
|
|
aee1ec |
if(status != SECSuccess) {
|
|
|
aee1ec |
JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to import private key info");
|
|
|
aee1ec |
goto finish;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
|
|
|
aee1ec |
+ privkObj = JSS_PK11_wrapPrivKey(env, &privk);
|
|
|
aee1ec |
+ if (privkObj == NULL) {
|
|
|
aee1ec |
+ goto finish;
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
finish:
|
|
|
aee1ec |
/* Save any exceptions */
|
|
|
aee1ec |
if( (excep=(*env)->ExceptionOccurred(env)) ) {
|
|
|
aee1ec |
@@ -515,24 +516,11 @@
|
|
|
aee1ec |
if( excep ) {
|
|
|
aee1ec |
(*env)->Throw(env, excep);
|
|
|
aee1ec |
}
|
|
|
aee1ec |
+ return privkObj;
|
|
|
aee1ec |
}
|
|
|
aee1ec |
|
|
|
aee1ec |
extern const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[];
|
|
|
aee1ec |
|
|
|
aee1ec |
-/***********************************************************************
|
|
|
aee1ec |
- * PK11Store.importdPrivateKey
|
|
|
aee1ec |
- */
|
|
|
aee1ec |
-JNIEXPORT void JNICALL
|
|
|
aee1ec |
-Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey
|
|
|
aee1ec |
- ( JNIEnv *env,
|
|
|
aee1ec |
- jobject this,
|
|
|
aee1ec |
- jbyteArray keyArray,
|
|
|
aee1ec |
- jobject keyTypeObj )
|
|
|
aee1ec |
-{
|
|
|
aee1ec |
- importPrivateKey(env, this, keyArray,
|
|
|
aee1ec |
- keyTypeObj, PR_FALSE /* not temporary */);
|
|
|
aee1ec |
-}
|
|
|
aee1ec |
-
|
|
|
aee1ec |
|
|
|
aee1ec |
JNIEXPORT jbyteArray JNICALL
|
|
|
aee1ec |
Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo(
|
|
|
aee1ec |
diff --git a/org/mozilla/jss/pkcs11/PK11Store.java b/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
--- a/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
+++ b/org/mozilla/jss/pkcs11/PK11Store.java
|
|
|
aee1ec |
@@ -23,9 +23,15 @@
|
|
|
aee1ec |
* @exception TokenException If the key cannot be imported to this token.
|
|
|
aee1ec |
* @exception KeyAlreadyImportedException If the key already on this token.
|
|
|
aee1ec |
*/
|
|
|
aee1ec |
- public native void
|
|
|
aee1ec |
- importPrivateKey( byte[] key,
|
|
|
aee1ec |
- PrivateKey.Type type )
|
|
|
aee1ec |
+ public PrivateKey
|
|
|
aee1ec |
+ importPrivateKey(byte[] key, PrivateKey.Type type)
|
|
|
aee1ec |
+ throws TokenException,KeyAlreadyImportedException {
|
|
|
aee1ec |
+ return importPrivateKey(key, type, false);
|
|
|
aee1ec |
+ }
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ public native PrivateKey
|
|
|
aee1ec |
+ importPrivateKey(
|
|
|
aee1ec |
+ byte[] key, PrivateKey.Type type, boolean temporary)
|
|
|
aee1ec |
throws TokenException,KeyAlreadyImportedException;
|
|
|
aee1ec |
|
|
|
aee1ec |
public synchronized PrivateKey[]
|
|
|
aee1ec |
# HG changeset patch
|
|
|
aee1ec |
# User Matthew Harmsen <mharmsen@redhat.com>
|
|
|
aee1ec |
# Date 1493389838 25200
|
|
|
aee1ec |
# Fri Apr 28 07:30:38 2017 -0700
|
|
|
aee1ec |
# Node ID 4ee5af07d6d8fd7efe60d130d3e7593f6e12e642
|
|
|
aee1ec |
# Parent ead2ea094c98ddc708169c3de411ca8d8883cab8
|
|
|
aee1ec |
Bug 1352476 - RFE: Document on the README how to create a release tag, r=emaldona
|
|
|
aee1ec |
|
|
|
aee1ec |
diff --git a/README b/README
|
|
|
aee1ec |
--- a/README
|
|
|
aee1ec |
+++ b/README
|
|
|
aee1ec |
@@ -158,7 +158,40 @@
|
|
|
aee1ec |
be necessary.
|
|
|
aee1ec |
|
|
|
aee1ec |
|
|
|
aee1ec |
-(7) Known Issues
|
|
|
aee1ec |
+(7) Tagging the Source Code for a Release
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ During development, several releases may be made. Consequently, it is
|
|
|
aee1ec |
+ good practice to create a "regular tag" to the source code at these
|
|
|
aee1ec |
+ various points in time using the following format:
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ # hg tag -m "message" JSS_<major>_<minor>_YYYYMMDD
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ where: <major> = JSS Major Version Number
|
|
|
aee1ec |
+ <minor> = JSS Minor Version Number
|
|
|
aee1ec |
+ YYYY = 4-digit year (e. g. - 2017)
|
|
|
aee1ec |
+ MM = 2-digit month (e. g. - 01, ..., 12)
|
|
|
aee1ec |
+ DD = 2-digit day of the month (e. g. - 01, ..., 31)
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ For example:
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ # hg id
|
|
|
aee1ec |
+ b3e864205ff0+ tip
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ # hg tag -m "Added tag JSS_4_4_20170328 for changeset b3e864205ff0" JSS_4_4_20170328
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ At the appropriate time, a new major.minor version may be created. At this
|
|
|
aee1ec |
+ time, it is important to create a maintenance branch for any future changes
|
|
|
aee1ec |
+ to the previous major.minor version:
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ For example:
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ # hg id
|
|
|
aee1ec |
+ f00f00f00f00+ tip
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+ # hg branch -m "Created branch JSS_4_4_BRANCH for changeset f00f00f00f00" JSS_4_4_BRANCH
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+
|
|
|
aee1ec |
+(8) Known Issues
|
|
|
aee1ec |
|
|
|
aee1ec |
* Mozilla Bug #1346410 - Load JSS libraries appropriately
|
|
|
aee1ec |
|