From 94b8206fde24bc109d2fe5217484c8d3af7905a2 Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Thu, 19 May 2016 14:01:14 -0700 Subject: [PATCH] Resolves: rhbz #1074208,1331596 -PKI Ticket #801 --- jss-VerifyCertificate-enhancement.patch | 204 +++ jss-lunasaUnwrap.patch | 12 + jss-symkey-enhancements.patch | 1855 +++++++++++++++++++++++ jss.spec | 22 +- 4 files changed, 2089 insertions(+), 4 deletions(-) create mode 100644 jss-VerifyCertificate-enhancement.patch create mode 100644 jss-lunasaUnwrap.patch create mode 100644 jss-symkey-enhancements.patch diff --git a/jss-VerifyCertificate-enhancement.patch b/jss-VerifyCertificate-enhancement.patch new file mode 100644 index 0000000..6582b41 --- /dev/null +++ b/jss-VerifyCertificate-enhancement.patch @@ -0,0 +1,204 @@ +From 3c4ca8a2010889fe292704ebcc8b922f77f2f7c2 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 9 Dec 2015 00:30:50 +0100 +Subject: [PATCH] Added verifyCertificate() method. + +A new CryptoManager.verifyCertificate() method has been added as +an alternative to isCertValid(). If there is a certificate +validation problem, the method will throw a CertificateValidation +exception that contains the NSS error message and code. The +exception will also provide a stack trace to help troubleshoot +validation issues. + +https://fedorahosted.org/pki/ticket/850 +--- + .../jss/org/mozilla/jss/CryptoManager.java | 54 ++++++++------ + mozilla/security/jss/org/mozilla/jss/PK11Finder.c | 83 +++++++++++++++++++--- + .../jss/org/mozilla/jss/util/jss_exceptions.h | 2 + + 3 files changed, 110 insertions(+), 29 deletions(-) + +diff --git a/mozilla/security/jss/org/mozilla/jss/CryptoManager.java b/mozilla/security/jss/org/mozilla/jss/CryptoManager.java +index 0a4f59064bfddb42d473022550c24f251719d02b..54ffd8130b0e1f1fca49dd8b130a621e449c7ce7 100644 +--- a/mozilla/security/jss/org/mozilla/jss/CryptoManager.java ++++ b/mozilla/security/jss/org/mozilla/jss/CryptoManager.java +@@ -1515,30 +1515,44 @@ public final class CryptoManager implements TokenSupplier + CertificateUsage certificateUsage) + throws ObjectNotFoundException, InvalidNicknameException + { +- if (nickname==null) { +- throw new InvalidNicknameException("Nickname must be non-null"); +- } +- // 0 certificate usage will get current usage +- // should call isCertValid() call above that returns certificate usage +- if ((certificateUsage == null) || +- (certificateUsage == CertificateUsage.CheckAllUsages)){ +- int currCertificateUsage = 0x0000; +- currCertificateUsage = verifyCertificateNowCUNative(nickname, +- checkSig); ++ try { ++ verifyCertificate(nickname, checkSig, certificateUsage); ++ return true; ++ ++ } catch (ObjectNotFoundException | InvalidNicknameException e) { ++ throw e; + +- if (currCertificateUsage == CertificateUsage.basicCertificateUsages){ +- // cert is good for nothing +- return false; +- } else +- return true; +- } else { +- return verifyCertificateNowNative(nickname, checkSig, +- certificateUsage.getUsage()); ++ } catch (CertificateException e) { ++ return false; + } + } + +- private native boolean verifyCertificateNowNative(String nickname, +- boolean checkSig, int certificateUsage) throws ObjectNotFoundException; ++ /** ++ * Verify a certificate that exists in the given cert database, ++ * check if it's valid and that we trust the issuer. Verify time ++ * against now. ++ * @param nickname nickname of the certificate to verify. ++ * @param checkSig verify the signature of the certificate ++ * @param certificateUsage see certificate usage defined to verify certificate ++ * ++ * @exception InvalidNicknameException If the nickname is null. ++ * @exception ObjectNotFoundException If no certificate could be found ++ * with the given nickname. ++ * @exception CertificateException If certificate is invalid. ++ */ ++ public void verifyCertificate(String nickname, ++ boolean checkSig, ++ CertificateUsage certificateUsage) ++ throws ObjectNotFoundException, InvalidNicknameException, CertificateException { ++ int usage = certificateUsage == null ? 0 : certificateUsage.getUsage(); ++ verifyCertificateNowNative(nickname, checkSig, usage); ++ } ++ ++ private native void verifyCertificateNowNative( ++ String nickname, ++ boolean checkSig, ++ int certificateUsage) ++ throws ObjectNotFoundException, InvalidNicknameException, CertificateException; + + /** + * note: this method calls obsolete function in NSS +diff --git a/mozilla/security/jss/org/mozilla/jss/PK11Finder.c b/mozilla/security/jss/org/mozilla/jss/PK11Finder.c +index 8c7f0b4c05b58527a41cac140dbb5dc30578570f..4986478ffc860e145cd31e41c2880fcc2b5e007e 100644 +--- a/mozilla/security/jss/org/mozilla/jss/PK11Finder.c ++++ b/mozilla/security/jss/org/mozilla/jss/PK11Finder.c +@@ -1667,21 +1667,86 @@ Java_org_mozilla_jss_CryptoManager_verifyCertificateNowCUNative(JNIEnv *env, + /*********************************************************************** + * CryptoManager.verifyCertificateNowNative + * +- * Returns JNI_TRUE if success, JNI_FALSE otherwise ++ * Verify a certificate that exists in the given cert database, ++ * check if it's valid and that we trust the issuer. Verify time ++ * against now. ++ * @param nickname nickname of the certificate to verify. ++ * @param checkSig verify the signature of the certificate ++ * @param certificateUsage see certificate usage defined to verify certificate ++ * ++ * @exception InvalidNicknameException If the nickname is null. ++ * @exception ObjectNotFoundException If no certificate could be found ++ * with the given nickname. ++ * @exception CertificateException If certificate is invalid. + */ +-JNIEXPORT jboolean JNICALL ++JNIEXPORT void JNICALL + Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative(JNIEnv *env, +- jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage) ++ jobject self, jstring nickString, jboolean checkSig, jint certificateUsage) + { +- SECStatus rv = SECFailure; + SECCertificateUsage currUsage = 0x0000; ++ SECStatus rv = SECFailure; ++ CERTCertificate *cert = NULL; ++ char *nickname = NULL; + +- rv = verifyCertificateNow(env, self, nickString, checkSig, required_certificateUsage, &currUsage); ++ if (nickString == NULL) { ++ JSS_throwMsg(env, INVALID_NICKNAME_EXCEPTION, "Missing certificate nickname"); ++ goto finish; ++ } + +- if( rv == SECSuccess) { +- return JNI_TRUE; +- } else { +- return JNI_FALSE; ++ nickname = (char *) (*env)->GetStringUTFChars(env, nickString, NULL); ++ ++ if (nickname == NULL) { ++ JSS_throwMsg(env, INVALID_NICKNAME_EXCEPTION, "Missing certificate nickname"); ++ goto finish; ++ } ++ ++ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), nickname); ++ ++ if (cert == NULL) { ++ char *msgBuf; ++ msgBuf = PR_smprintf("Certificate not found: %s", nickname); ++ JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, msgBuf); ++ PR_Free(msgBuf); ++ goto finish; ++ } ++ ++ /* 0 for certificateUsage in call to CERT_VerifyCertificateNow will ++ * retrieve the current valid usage into currUsage ++ */ ++ rv = CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, ++ checkSig, certificateUsage, NULL, &currUsage); ++ ++ if (rv != SECSuccess) { ++ JSS_throwMsgPrErr(env, CERTIFICATE_EXCEPTION, "Invalid certificate"); ++ goto finish; ++ } ++ ++ if ((certificateUsage == 0x0000) && ++ (currUsage == ++ ( certUsageUserCertImport | ++ certUsageVerifyCA | ++ certUsageProtectedObjectSigner | ++ certUsageAnyCA ))) { ++ ++ /* The certificate is good for nothing. ++ * The following usages cannot be verified: ++ * certUsageAnyCA ++ * certUsageProtectedObjectSigner ++ * certUsageUserCertImport ++ * certUsageVerifyCA ++ * (0x0b80) ++ */ ++ ++ JSS_throwMsgPrErr(env, CERTIFICATE_EXCEPTION, "Unusable certificate"); ++ goto finish; ++ } ++ ++finish: ++ if (nickname != NULL) { ++ (*env)->ReleaseStringUTFChars(env, nickString, nickname); ++ } ++ if (cert != NULL) { ++ CERT_DestroyCertificate(cert); + } + } + +diff --git a/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h b/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h +index 4884928306223ff0699a22e7da33e3d13a904d39..acd329a4ecd3592ebe1d72c7bdac435d84dcae99 100644 +--- a/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h ++++ b/mozilla/security/jss/org/mozilla/jss/util/jss_exceptions.h +@@ -79,6 +79,8 @@ PR_BEGIN_EXTERN_C + + #define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException" + ++#define INVALID_NICKNAME_EXCEPTION "org/mozilla/jss/util/InvalidNicknameException" ++ + #define INVALID_KEY_FORMAT_EXCEPTION "org/mozilla/jss/crypto/InvalidKeyFormatException" + + #define INVALID_PARAMETER_EXCEPTION "java/security/InvalidParameterException" +-- +2.5.0 + diff --git a/jss-lunasaUnwrap.patch b/jss-lunasaUnwrap.patch new file mode 100644 index 0000000..5021bd6 --- /dev/null +++ b/jss-lunasaUnwrap.patch @@ -0,0 +1,12 @@ +diff -up jss-4.2.6/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c.cfu jss-4.2.6/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c +--- jss-4.2.6/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c.cfu 2016-04-28 16:50:06.000000000 -0700 ++++ jss-4.2.6/mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c 2016-04-28 16:50:00.000000000 -0700 +@@ -434,7 +434,7 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapp + isSensitive = PR_FALSE; + isExtractable = PR_FALSE; + } else if ( isLunasa) { +- isSensitive = PR_FALSE; ++ isSensitive = PR_TRUE; + isExtractable = PR_TRUE; + } + diff --git a/jss-symkey-enhancements.patch b/jss-symkey-enhancements.patch new file mode 100644 index 0000000..fe994d9 --- /dev/null +++ b/jss-symkey-enhancements.patch @@ -0,0 +1,1855 @@ +diff -up ./mozilla/security/jss/build_java.pl.jmagne ./mozilla/security/jss/build_java.pl +--- ./mozilla/security/jss/build_java.pl.jmagne 2016-04-14 13:56:16.946920239 -0700 ++++ ./mozilla/security/jss/build_java.pl 2016-04-14 14:53:08.501298062 -0700 +@@ -31,7 +31,8 @@ org.mozilla.jss.pkcs11.PK11MessageDigest + org.mozilla.jss.pkcs11.PK11PrivKey + org.mozilla.jss.pkcs11.PK11PubKey + org.mozilla.jss.pkcs11.PK11SymKey +-org.mozilla.jss.pkcs11.PK11KeyPairGenerator ++org.mozilla.jss.pkcs11.PK11KeyPairGenerator ++org.mozilla.jss.pkcs11.PK11SymmetricKeyDeriver + org.mozilla.jss.pkcs11.PK11KeyGenerator + org.mozilla.jss.pkcs11.PK11Token + org.mozilla.jss.pkcs11.PrivateKeyProxy +diff -up ./mozilla/security/jss/lib/jss.def.jmagne ./mozilla/security/jss/lib/jss.def +--- ./mozilla/security/jss/lib/jss.def.jmagne 2016-04-14 16:00:06.229534228 -0700 ++++ ./mozilla/security/jss/lib/jss.def 2016-04-14 16:00:32.229356314 -0700 +@@ -158,6 +158,7 @@ Java_org_mozilla_jss_pkcs11_PK11Store_de + Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey; + Java_org_mozilla_jss_pkcs11_PK11Store_putCertsInVector; + Java_org_mozilla_jss_pkcs11_PK11Store_putKeysInVector; ++Java_org_mozilla_jss_pkcs11_PK11Store_putSymKeysInVector; + Java_org_mozilla_jss_pkcs11_SigContextProxy_releaseNativeResources; + Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getModulusByteArray; + Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getPublicExponentByteArray; +@@ -336,6 +337,8 @@ Java_org_mozilla_jss_CryptoManager_verif + Java_org_mozilla_jss_asn1_ASN1Util_getTagDescriptionByOid; + Java_org_mozilla_jss_ssl_SocketBase_setSSLVersionRange; + Java_org_mozilla_jss_ssl_SSLSocket_setSSLVersionRangeDefault; ++Java_org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver_nativeDeriveSymKey; ++Java_org_mozilla_jss_pkcs11_PK11SymKey_setNickNameNative; + ;+ local: + ;+ *; + ;+}; +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c +--- ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c.jmagne 2016-04-14 16:02:38.108494940 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.c 2016-04-14 16:02:47.243432431 -0700 +@@ -114,6 +114,11 @@ JSS_AlgInfo JSS_AlgTable[NUM_ALGS] = { + /* 51 */ {SEC_OID_PKCS5_PBKDF2, SEC_OID_TAG}, + /* 52 */ {SEC_OID_PKCS5_PBES2, SEC_OID_TAG}, + /* 53 */ {SEC_OID_PKCS5_PBMAC1, SEC_OID_TAG}, ++/* 54 */ {SEC_OID_HMAC_SHA1,SEC_OID_TAG}, ++/* 55 */ {SEC_OID_HMAC_SHA224,SEC_OID_TAG}, ++/* 56 */ {SEC_OID_HMAC_SHA256,SEC_OID_TAG}, ++/* 57 */ {SEC_OID_HMAC_SHA384,SEC_OID_TAG}, ++/* 58 */ {SEC_OID_HMAC_SHA512,SEC_OID_TAG} + /* REMEMBER TO UPDATE NUM_ALGS!!! */ + }; + +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h +--- ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h.jmagne 2016-04-14 11:30:41.871517926 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.h 2016-04-14 11:30:54.933436860 -0700 +@@ -56,7 +56,7 @@ typedef struct JSS_AlgInfoStr { + JSS_AlgType type; + } JSS_AlgInfo; + +-#define NUM_ALGS 54 ++#define NUM_ALGS 59 + + extern JSS_AlgInfo JSS_AlgTable[]; + extern CK_ULONG JSS_symkeyUsage[]; +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java.jmagne 2016-04-14 16:06:13.388021812 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/Algorithm.java 2016-04-14 16:06:27.537924813 -0700 +@@ -237,5 +237,9 @@ public class Algorithm { + protected static final short SEC_OID_PKCS5_PBKDF2=51; + protected static final short SEC_OID_PKCS5_PBES2=52; + protected static final short SEC_OID_PKCS5_PBMAC1=53; +- ++ protected static final short SEC_OID_HMAC_SHA1=54; ++ protected static final short SEC_OID_HMAC_SHA224=55; ++ protected static final short SEC_OID_HMAC_SHA256=56; ++ protected static final short SEC_OID_HMAC_SHA384=57; ++ protected static final short SEC_OID_HMAC_SHA512=58; + } +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java.jmagne 2016-04-14 17:03:33.504298176 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoStore.java 2016-04-14 17:03:42.198238112 -0700 +@@ -75,6 +75,18 @@ public interface CryptoStore { + getPrivateKeys() throws TokenException; + + /** ++ * Returns all symmetric keys stored on this token. ++ * ++ * @return An array of all symmetric keys stored on this token. ++ * @exception TokenException If an error occurs on the token while ++ * gathering the keys. ++ */ ++ public SymmetricKey[] ++ getSymmetricKeys() throws TokenException; ++ ++ ++ ++ /** + * Deletes the given PrivateKey from the CryptoToken. + * This is a very dangerous call: it deletes the key from the underlying + * token. After calling this, the PrivateKey passed in must no longer +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java.jmagne 2016-04-14 16:07:39.458429756 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/CryptoToken.java 2016-04-14 16:07:52.266341595 -0700 +@@ -92,6 +92,9 @@ public interface CryptoToken { + getCipherContext(EncryptionAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; + ++ public abstract SymmetricKeyDeriver getSymmetricKeyDeriver() ++ throws TokenException; ++ + public abstract KeyWrapper + getKeyWrapper(KeyWrapAlgorithm algorithm) + throws java.security.NoSuchAlgorithmException, TokenException; +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java.jmagne 2016-04-14 16:09:02.858855679 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/HMACAlgorithm.java 2016-04-14 16:09:18.048751121 -0700 +@@ -85,4 +85,21 @@ public class HMACAlgorithm extends Diges + public static final HMACAlgorithm SHA1 = new HMACAlgorithm + (CKM_SHA_1_HMAC, "SHA-1-HMAC", + OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20); ++ ++ public static final HMACAlgorithm SHA224 = new HMACAlgorithm ++ (SEC_OID_HMAC_SHA224, "SHA-224-HMAC", ++ OBJECT_IDENTIFIER.RSADSI.subBranch(8), 28); ++ ++ public static final HMACAlgorithm SHA256 = new HMACAlgorithm ++ (SEC_OID_HMAC_SHA256, "SHA-256-HMAC", ++ OBJECT_IDENTIFIER.RSADSI.subBranch(9), 32); ++ ++ public static final HMACAlgorithm SHA384 = new HMACAlgorithm ++ (SEC_OID_HMAC_SHA384, "SHA-384-HMAC", ++ OBJECT_IDENTIFIER.RSADSI.subBranch(10), 48); ++ ++ public static final HMACAlgorithm SHA512 = new HMACAlgorithm ++ (SEC_OID_HMAC_SHA512, "SHA-512-HMAC", ++ OBJECT_IDENTIFIER.RSADSI.subBranch(11), 64); ++ + } +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java.jmagne 2016-04-14 16:10:43.930159965 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/KeyWrapper.java 2016-04-14 16:10:55.377081172 -0700 +@@ -133,4 +133,21 @@ public interface KeyWrapper { + throws TokenException, IllegalStateException, + InvalidAlgorithmParameterException; + ++ public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, ++ SymmetricKey.Usage usage, int keyLength) ++ throws TokenException, IllegalStateException, ++ InvalidAlgorithmParameterException; ++ ++ /** ++ * Unwraps a key and allows it to be used for all operations. ++ * @param keyLength The expected length of the key in bytes. This is ++ * only used for variable-length keys (RC4) and non-padding ++ * algorithms. Otherwise, it can be set to anything(like 0). ++ */ ++ public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, ++ int keyLength) ++ throws TokenException, IllegalStateException, ++ InvalidAlgorithmParameterException; ++ ++ + } +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKeyDeriver.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKeyDeriver.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKeyDeriver.java.jmagne 2016-04-14 16:36:36.080464052 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKeyDeriver.java 2016-04-14 16:36:49.784369514 -0700 +@@ -0,0 +1,79 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the Netscape Security Services for Java. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998-2000 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++package org.mozilla.jss.crypto; ++ ++import java.security.spec.AlgorithmParameterSpec; ++import java.security.InvalidAlgorithmParameterException; ++import java.security.PublicKey; ++import java.security.InvalidKeyException; ++ ++public interface SymmetricKeyDeriver { ++ ++ /* Use with the encrypt type mechanisms ++ Example: initDerive( ++ symKey, (PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA) 4354L, derivationData, null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16); ++ */ ++ ++ public abstract void initDerive(SymmetricKey baseKey, ++ long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) ++ throws InvalidKeyException; ++ ++ ++ ++ /* Use with key extraction and key concatanation mechanisms ++ ++ Example: ++ param: byte array that has the bit position of where to extract ++ initDerive( ++ derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, ++ PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8); ++ ++ ++ initDerive( ++ baseSymKey,secondarySymKey, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0); ++ ++ */ ++ ++ public abstract void initDerive(SymmetricKey baseKey, ++ SymmetricKey secondaryKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) ++ throws InvalidKeyException; ++ ++ public abstract SymmetricKey derive() ++ throws TokenException; ++} +diff -up ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java.jmagne ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java +--- ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java.jmagne 2016-04-14 16:11:50.865699222 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/crypto/SymmetricKey.java 2016-04-14 16:12:02.768617289 -0700 +@@ -71,6 +71,10 @@ public interface SymmetricKey { + + String getFormat(); + ++ String getNickName(); ++ ++ void setNickName(String nickName); ++ + public final static class Type { + // all names converted to lowercase for case insensitivity + private static Hashtable nameMap = new Hashtable(); +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn.jmagne 2016-04-14 16:15:59.271989344 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/manifest.mn 2016-04-14 16:16:10.670910881 -0700 +@@ -64,6 +64,7 @@ CSRCS = \ + PK11Store.c \ + PK11SymKey.c \ + PK11Token.c \ ++ PK11SymmetricKeyDeriver.c \ + $(NULL) + + +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c.jmagne 2016-04-14 16:17:29.760366477 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.c 2016-04-14 16:17:58.742166983 -0700 +@@ -519,7 +519,7 @@ JNIEXPORT jobject JNICALL + Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithSym + (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, + jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, +- jint keyLen, jbyteArray ivBA, jint usageEnum) ++ jint keyLen, jbyteArray ivBA, jint usageEnum,jboolean temporary) + { + PK11SymKey *symKey=NULL, *wrappingKey=NULL; + CK_MECHANISM_TYPE wrappingMech, keyTypeMech; +@@ -527,6 +527,7 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapp + jobject keyObj = NULL; + CK_ULONG operation; + CK_FLAGS flags; ++ PRBool isPermanent = PR_FALSE; + + /* get key type */ + keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); +@@ -579,8 +580,21 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapp + flags = 0; + } + +- symKey = PK11_UnwrapSymKeyWithFlags(wrappingKey, wrappingMech, param, +- wrappedKey, keyTypeMech, operation, keyLen, flags); ++ if( temporary ) { ++ isPermanent = PR_FALSE; ++ } else { ++ isPermanent = PR_TRUE; ++ } ++ ++ if( isPermanent == PR_FALSE) { ++ symKey = PK11_UnwrapSymKeyWithFlags(wrappingKey, wrappingMech, param, ++ wrappedKey, keyTypeMech, operation, keyLen, flags); ++ ++ } else { ++ symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrappingKey, wrappingMech, param, ++ wrappedKey, keyTypeMech, operation, keyLen, flags,isPermanent); ++ } ++ + if( symKey == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to unwrap key"); + goto finish; +@@ -702,7 +716,7 @@ finish: + JNIEXPORT jobject JNICALL + Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymPlaintext + (JNIEnv *env, jclass clazz, jobject tokenObj, jbyteArray wrappedBA, +- jobject typeAlgObj, jint usageEnum) ++ jobject typeAlgObj, jint usageEnum,jboolean temporary) + { + PK11SymKey *symKey=NULL; + CK_MECHANISM_TYPE keyTypeMech; +@@ -711,6 +725,8 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapp + PK11SlotInfo *slot = NULL; + CK_ULONG operation; + CK_FLAGS flags; ++ PRBool isPerm = PR_FALSE; ++ + + /* get key type */ + keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); +@@ -740,9 +756,15 @@ Java_org_mozilla_jss_pkcs11_PK11KeyWrapp + flags = 0; + } + ++ if( temporary ) { ++ isPerm = PR_FALSE; ++ } else { ++ isPerm = PR_TRUE; ++ } ++ + /* pull in the key */ + symKey = PK11_ImportSymKeyWithFlags(slot, keyTypeMech, PK11_OriginUnwrap, +- operation, wrappedKey, flags, PR_FALSE /*isPerm*/, NULL); ++ operation, wrappedKey, flags, isPerm, NULL); + if( symKey == NULL ) { + JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to unwrap key"); + goto finish; +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java.jmagne 2016-04-14 16:19:26.998559480 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11KeyWrapper.java 2016-04-14 16:19:40.941463506 -0700 +@@ -498,8 +498,25 @@ final class PK11KeyWrapper implements Ke + return unwrapSymmetric(wrapped, type, -1, keyLen); + } + ++ public SymmetricKey ++ unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, ++ SymmetricKey.Usage usage, int keyLen) ++ throws TokenException, IllegalStateException, ++ InvalidAlgorithmParameterException ++ { ++ return unwrapSymmetricPerm(wrapped, type, usage.getVal(), keyLen); ++ } ++ ++ public SymmetricKey ++ unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, int keyLen) ++ throws TokenException, IllegalStateException, ++ InvalidAlgorithmParameterException ++ { ++ return unwrapSymmetricPerm(wrapped, type, -1, keyLen); ++ } ++ + private SymmetricKey +- unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, ++ unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, + int usageEnum, int keyLen) + throws TokenException, IllegalStateException, + InvalidAlgorithmParameterException +@@ -508,6 +525,10 @@ final class PK11KeyWrapper implements Ke + throw new IllegalStateException(); + } + ++ /* Since we want permanent,make the temporary arg false */ ++ boolean temporary = false; ++ ++ + if( (! algorithm.isPadded()) && (type == SymmetricKey.RC4) ) { + if( keyLen <= 0 ) { + throw new InvalidAlgorithmParameterException( +@@ -521,12 +542,53 @@ final class PK11KeyWrapper implements Ke + + if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { + return nativeUnwrapSymPlaintext(token, wrapped, algFromType(type), +- usageEnum ); ++ usageEnum,temporary ); + } else { + if( symKey != null ) { + Assert._assert(pubKey==null && privKey==null); + return nativeUnwrapSymWithSym(token, symKey, wrapped, algorithm, +- algFromType(type), keyLen, IV, usageEnum); ++ algFromType(type), keyLen, IV, usageEnum,temporary); ++ } else { ++ Assert._assert(privKey!=null && pubKey==null && symKey==null); ++ throw new TokenException("We do not support permnament unwrapping with private key."); ++ } ++ } ++ } ++ ++ ++ private SymmetricKey ++ unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, ++ int usageEnum, int keyLen) ++ throws TokenException, IllegalStateException, ++ InvalidAlgorithmParameterException ++ { ++ if( state != UNWRAP ) { ++ throw new IllegalStateException(); ++ } ++ ++ if( (! algorithm.isPadded()) && (type == SymmetricKey.RC4) ) { ++ if( keyLen <= 0 ) { ++ throw new InvalidAlgorithmParameterException( ++ "RC4 keys wrapped in unpadded algorithms need key length"+ ++ " specified when unwrapping"); ++ } ++ } else { ++ // Don't use the key length ++ //keyLen = 0; ++ } ++ ++ /* Since we DONT want permanent,make the temporary arg true */ ++ boolean temporary = true; ++ ++ ++ if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { ++ return nativeUnwrapSymPlaintext(token, wrapped, algFromType(type), ++ usageEnum, temporary ); ++ } else { ++ if( symKey != null ) { ++ Assert._assert(pubKey==null && privKey==null); ++ return nativeUnwrapSymWithSym(token, symKey, wrapped, algorithm, ++ algFromType(type), keyLen, IV, usageEnum,temporary); + } else { + Assert._assert(privKey!=null && pubKey==null && symKey==null); + return nativeUnwrapSymWithPriv(token, privKey, wrapped, +@@ -586,7 +648,7 @@ final class PK11KeyWrapper implements Ke + private static native SymmetricKey + nativeUnwrapSymWithSym(PK11Token token, SymmetricKey unwrappingKey, + byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, int keyLen, +- byte[] IV, int usageEnum) ++ byte[] IV, int usageEnum,boolean temporary) + throws TokenException; + + /** +@@ -600,7 +662,7 @@ final class PK11KeyWrapper implements Ke + + private static native SymmetricKey + nativeUnwrapSymPlaintext(PK11Token token, byte[] wrappedKey, +- Algorithm type, int usageEnum); ++ Algorithm type, int usageEnum,boolean temporary); + + private void reset() { + state = UNINITIALIZED; +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c.jmagne 2016-05-06 18:10:04.531912407 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11MessageDigest.c 2016-05-06 17:36:19.913933639 -0700 +@@ -99,17 +99,19 @@ Java_org_mozilla_jss_pkcs11_PK11MessageD + } + + /* copy the key, setting the CKA_SIGN attribute */ +- newKey = PK11_CopySymKeyForSigning(origKey, mech); ++/* newKey = PK11_CopySymKeyForSigning(origKey, mech); + if( newKey == NULL ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, + "Unable to set CKA_SIGN attribute on symmetric key"); + goto finish; + } + ++*/ ++ + param.data = NULL; + param.len = 0; + +- context = PK11_CreateContextBySymKey(mech, CKA_SIGN, newKey, ¶m); ++ context = PK11_CreateContextBySymKey(mech, CKA_SIGN, origKey, ¶m); + if( context == NULL ) { + JSS_throwMsg(env, DIGEST_EXCEPTION, + "Unable to initialize digest context"); +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c.jmagne 2016-04-14 16:22:16.174394977 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.c 2016-04-14 16:22:26.605323176 -0700 +@@ -44,13 +44,101 @@ + #include + #include + #include +- + #include + #include + #include "pk11util.h" + #include + #include + ++typedef struct ++{ ++ enum ++ { ++ PW_NONE = 0, ++ PW_FROMFILE = 1, ++ PW_PLAINTEXT = 2, ++ PW_EXTERNAL = 3 ++ } source; ++ char *data; ++} secuPWData; ++ ++/********************************************************************** ++ * PK11Store.putSymKeysInVector ++ */ ++JNIEXPORT void JNICALL ++Java_org_mozilla_jss_pkcs11_PK11Store_putSymKeysInVector ++ (JNIEnv *env, jobject this, jobject keyVector) ++{ ++ PK11SlotInfo *slot; ++ jobject object = NULL; ++ jclass vectorClass; ++ jmethodID addElement; ++ ++ PK11SymKey *firstSymKey= NULL; ++ PK11SymKey *sk = NULL; ++ PK11SymKey *nextSymKey = NULL; ++ secuPWData pwdata; ++ ++ PK11SymKey *freeSymKey = NULL; ++ PK11SymKey *nextFreeSymKey = NULL; ++ ++ pwdata.source = PW_NONE; ++ pwdata.data = (char *) NULL; ++ ++ PR_ASSERT(env!=NULL && this!=NULL && keyVector!=NULL); ++ ++ if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ++ ASSERT_OUTOFMEM(env); ++ goto finish; ++ } ++ PR_ASSERT(slot!=NULL); ++ ++ vectorClass = (*env)->GetObjectClass(env, keyVector); ++ if(vectorClass == NULL) { ++ ASSERT_OUTOFMEM(env); ++ goto finish; ++ } ++ ++ addElement = (*env)->GetMethodID(env, ++ vectorClass, ++ VECTOR_ADD_ELEMENT_NAME, ++ VECTOR_ADD_ELEMENT_SIG); ++ if(addElement == NULL) { ++ ASSERT_OUTOFMEM(env); ++ goto finish; ++ } ++ ++ PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); ++ ++ /* Obtain the symmetric key list. */ ++ firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata ); ++ sk = firstSymKey; ++ ++ while(( sk != NULL )) ++ { ++ if( sk ) { ++ ++ nextSymKey = sk; ++ object = JSS_PK11_wrapSymKey(env, &sk); ++ ++ if(object == NULL) { ++ PR_ASSERT( (*env)->ExceptionOccurred(env) ); ++ goto finish; ++ } ++ ++ /*************************************************** ++ * Insert the key into the vector ++ ***************************************************/ ++ (*env)->CallVoidMethod(env, keyVector, addElement, object); ++ } ++ ++ sk = PK11_GetNextSymKey( nextSymKey ); ++ } ++ ++finish: ++ ++ return; ++} + + /********************************************************************** + * PK11Store.putKeysInVector +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java.jmagne 2016-04-14 16:23:26.997907471 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Store.java 2016-04-14 16:23:34.435856272 -0700 +@@ -66,8 +66,23 @@ public final class PK11Store implements + keys.copyInto( (Object[]) array ); + return array; + } ++ ++ public synchronized SymmetricKey[] ++ getSymmetricKeys() throws TokenException { ++ ++ Vector keys = new Vector(); ++ putSymKeysInVector(keys); ++ SymmetricKey[] array = new SymmetricKey[keys.size()]; ++ keys.copyInto( (Object[]) array); ++ return array; ++ } ++ ++ ++ + protected native void putKeysInVector(Vector keys) throws TokenException; + ++ protected native void putSymKeysInVector(Vector symKeys) throws TokenException; ++ + + public native void deletePrivateKey(PrivateKey key) + throws NoSuchItemOnTokenException, TokenException; +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c.jmagne 2016-04-14 16:24:44.565372557 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.c 2016-05-17 11:37:48.532485104 -0700 +@@ -33,7 +33,6 @@ + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +- + #include "_jni/org_mozilla_jss_pkcs11_SymKeyProxy.h" + + #include +@@ -62,6 +61,8 @@ JSS_PK11_wrapSymKey(JNIEnv *env, PK11Sym + jmethodID constructor; + jbyteArray ptrArray; + jobject Key=NULL; ++ char *nickname = NULL; ++ jstring jnickname = NULL; + + PR_ASSERT(env!=NULL && symKey!=NULL && *symKey!=NULL); + +@@ -72,10 +73,17 @@ JSS_PK11_wrapSymKey(JNIEnv *env, PK11Sym + goto finish; + } + ++ nickname = PK11_GetSymKeyNickname( *symKey ); ++ ++ if (nickname) { ++ jnickname = (*env)->NewStringUTF(env, nickname); ++ } ++ ++ + /* find the constructor */ + constructor = (*env)->GetMethodID(env, keyClass, + PLAIN_CONSTRUCTOR, +- PK11SYMKEY_CONSTRUCTOR_SIG); ++ PK11SYMKEY_CONSTRUCTOR_1_SIG); + if(constructor == NULL) { + ASSERT_OUTOFMEM(env); + goto finish; +@@ -87,12 +95,16 @@ JSS_PK11_wrapSymKey(JNIEnv *env, PK11Sym + goto finish; + } + /* call the constructor */ +- Key = (*env)->NewObject(env, keyClass, constructor, ptrArray); ++ Key = (*env)->NewObject(env, keyClass, constructor, ptrArray,jnickname); + + finish: + if(Key == NULL) { + PK11_FreeSymKey(*symKey); + } ++ if(nickname != NULL) { ++ PORT_Free(nickname); ++ nickname = NULL; ++ } + *symKey = NULL; + return Key; + } +@@ -181,6 +193,49 @@ finish: + + /*********************************************************************** + * ++ * PK11SymKey.setNickNameNative ++ */ ++JNIEXPORT void JNICALL ++Java_org_mozilla_jss_pkcs11_PK11SymKey_setNickNameNative ++ (JNIEnv *env, jobject this,jstring nickname) ++{ ++ PK11SymKey *key=NULL; ++ const char *keyname = NULL; ++ SECStatus status; ++ ++ /* If no nickname provided, we are done */ ++ if( nickname == NULL ) { ++ JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, ++ "Nickname is NULL, will not be set"); ++ goto finish; ++ } ++ ++ /* get the key pointer */ ++ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { ++ goto finish; ++ } ++ ++ /* convert the Java String into a native "C" string */ ++ keyname = (*env)->GetStringUTFChars( env, nickname, 0 ); ++ ++ /* name the key */ ++ status = PK11_SetSymKeyNickname( key, keyname ); ++ if( status != SECSuccess ) { ++ JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, ++ "Failed to name symmetric key"); ++ } ++finish: ++ ++ if( keyname != NULL ) { ++ /* free the native "C" string */ ++ (*env)->ReleaseStringUTFChars(env, nickname, keyname); ++ } ++ ++ return; ++} ++ ++/*********************************************************************** ++ * + * PK11SymKey.getKeyData + */ + JNIEXPORT jbyteArray JNICALL +@@ -279,6 +334,10 @@ Java_org_mozilla_jss_pkcs11_PK11SymKey_g + case CKK_AES: + typeFieldName = AES_KEYTYPE_FIELD; + break; ++ case CKK_DES2: ++ printf("hello des2! \n"); ++ typeFieldName = DES3_KEYTYPE_FIELD; ++ break; + default: + PR_ASSERT(PR_FALSE); + typeFieldName = DES_KEYTYPE_FIELD; +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java.jmagne 2016-04-14 16:58:33.385371633 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymKey.java 2016-05-17 11:41:36.323841045 -0700 +@@ -44,9 +44,17 @@ public final class PK11SymKey implements + protected PK11SymKey(byte[] pointer) { + Assert._assert(pointer!=null); + keyProxy = new SymKeyProxy(pointer); ++ nickName = null; ++ } ++ ++ protected PK11SymKey(byte[] pointer,String nickName) { ++ Assert._assert(pointer!=null); ++ keyProxy = new SymKeyProxy(pointer); ++ this.nickName = nickName; + } + + private SymKeyProxy keyProxy; ++ private String nickName; + + public SymmetricKey.Type getType() { + KeyType kt = getKeyType(); +@@ -108,6 +116,20 @@ public final class PK11SymKey implements + public String getFormat() { + return "RAW"; + } ++ ++ public String getNickName() { ++ return nickName; ++ } ++ ++ public void setNickName(String nickName) { ++ this.nickName = nickName; ++ ++ if( nickName != null) { ++ setNickNameNative(nickName); ++ } ++ } ++ ++ public native void setNickNameNative(String nickName); + } + + class SymKeyProxy extends KeyProxy { +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.c.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.c +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.c.jmagne 2016-04-14 16:26:18.611723763 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.c 2016-05-17 14:13:35.456574082 -0700 +@@ -0,0 +1,364 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the Netscape Security Services for Java. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998-2000 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++#include "_jni/org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "java_ids.h" ++ ++#include "pk11util.h" ++#include ++ ++/*********************************************************************** ++ * Expose the NSS functionality at low level, one should know what to do ++ * at the Java level. ++ */ ++ ++JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver_nativeDeriveSymKey ++ (JNIEnv * env, jobject this,jobject tokenObj, ++ jobject baseKeyObj, jobject secondaryKeyObj, ++ jlong deriveMechanism, jbyteArray param, jbyteArray iv, jlong targetMechanism, jlong operation, jlong keySize) ++{ ++ jobject keyObj = NULL; ++ PK11SlotInfo *slot=NULL; ++ PK11SlotInfo *bestSlot = NULL; ++ PK11SlotInfo *slotForKey = NULL; ++ PK11SlotInfo *slotForSecondaryKey = NULL; ++ PK11SlotInfo *finalSlot = NULL; ++ PK11SlotInfo *finalSecondarySlot = NULL; ++ PK11SlotInfo *finalBaseKeySlot = NULL; ++ ++ PK11SymKey *baseKey = NULL; ++ PK11SymKey *bestBaseKey = NULL; ++ PK11SymKey *finalBaseKey = NULL; ++ PK11SymKey *newKey = NULL; ++ ++ PK11SymKey *secondaryKey = NULL; ++ PK11SymKey *bestSecondaryKey = NULL; ++ PK11SymKey *finalSecondaryKey = NULL; ++ PK11SymKey *derivedKey = NULL; ++ jbyte *paramValue = NULL; ++ int paramLength = 0; ++ jbyte *ivValue = NULL; ++ int ivLength = 0; ++ ++ ++ CK_OBJECT_HANDLE keyhandle = 0; ++ ++ CK_AES_CBC_ENCRYPT_DATA_PARAMS aes; ++ CK_DES_CBC_ENCRYPT_DATA_PARAMS des; ++ CK_KEY_DERIVATION_STRING_DATA string; ++ ++ SECItem paramsItem = { siBuffer, NULL, 0 }; ++ ++ PR_ASSERT(env!=NULL && this!=NULL); ++ ++ if( baseKeyObj == 0) { ++ PR_fprintf(PR_STDOUT,"baseKeyObj can not be null!\n"); ++ goto loser; ++ } ++ ++ if( param != NULL) { ++ paramValue = (*env)->GetByteArrayElements(env,param, NULL); ++ paramLength = (*env)->GetArrayLength(env,param); ++ } ++ ++ if( iv != NULL) { ++ ivValue = (*env)->GetByteArrayElements(env,iv, NULL); ++ ivLength = (*env)->GetArrayLength(env,iv); ++ } ++ ++ /* Set up the params data for the PK11_Derive family */ ++ ++ switch ( deriveMechanism ) { ++ case CKM_DES_ECB_ENCRYPT_DATA: ++ case CKM_DES3_ECB_ENCRYPT_DATA: ++ case CKM_AES_ECB_ENCRYPT_DATA: ++ case CKM_CAMELLIA_ECB_ENCRYPT_DATA: ++ case CKM_SEED_ECB_ENCRYPT_DATA: ++ /* Use CK_KEY_DERIVATION_STRING_DATA */ ++ ++ string.pData = (unsigned char *) paramValue; ++ string.ulLen = paramLength; ++ paramsItem.data = (void *) &string; ++ paramsItem.len = sizeof(string); ++ ++ break; ++ case CKM_DES_CBC_ENCRYPT_DATA: ++ case CKM_DES3_CBC_ENCRYPT_DATA: ++ /* Use CK_DES_CBC_ENCRYPT_DATA_PARAMS */ ++ ++ if( ivValue == NULL) { ++ PR_fprintf(PR_STDOUT, "Need iv param for CKM_DES_CBC_ENCRYPT_DATA or CKM_DES3_CBC_ENCRYPT_DATA. \n"); ++ goto loser; ++ } ++ ++ if( ivLength != 8) { ++ PR_fprintf(PR_STDOUT, "Need iv param for CKM_DES_CBC_ENCRYPT_DATA structure to be 8 bytes!. \n"); ++ goto loser; ++ } ++ ++ des.pData = (unsigned char *) paramValue; ++ des.length = paramLength; ++ PORT_Memcpy(des.iv,ivValue,ivLength); ++ paramsItem.data = (void *) &des; ++ paramsItem.len = sizeof(des); ++ ++ break; ++ ++ case CKM_AES_CBC_ENCRYPT_DATA: ++ case CKM_CAMELLIA_CBC_ENCRYPT_DATA: ++ case CKM_SEED_CBC_ENCRYPT_DATA: ++ /* Use CK_AES_CBC_ENCRYPT_DATA_PARAMS */ ++ ++ if ( ivValue == NULL ) { ++ PR_fprintf(PR_STDOUT, "Need iv param for CBC encrypt derive for AES, or CAMELLIA or SEED. \n"); ++ goto loser; ++ } ++ ++ if( ivLength != 16) { ++ PR_fprintf(PR_STDOUT, "Need iv param for CK_AES_CBC_ENCRYPT_DATA_PARAMS structure to be 16 bytes!. \n"); ++ goto loser; ++ } ++ ++ aes.pData = (unsigned char *) paramValue; ++ aes.length = paramLength; ++ PORT_Memcpy(aes.iv,ivValue,ivLength); ++ paramsItem.data = (void *) &aes; ++ paramsItem.len = sizeof(aes); ++ break; ++ default: ++ paramsItem.data = (unsigned char *) paramValue; ++ paramsItem.len = paramLength; ++ break; ++ } ++ ++ /* Get slot */ ++ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { ++ goto loser; ++ } ++ ++ /* Get base key */ ++ ++ if( JSS_PK11_getSymKeyPtr(env, baseKeyObj, &baseKey) != PR_SUCCESS) { ++ PR_fprintf(PR_STDOUT, "PK11SymmetricKeyDeriver.nativeDeriveSymKey: Unable to extract symmetric base key!"); ++ goto loser; ++ } ++ ++ /* Ask NSS what the best slot for the given mechanism */ ++ ++ bestSlot = PK11_GetBestSlot(deriveMechanism, NULL); ++ ++ if( bestSlot == NULL) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't find suitable slot for sym key derivation! \n"); ++ goto loser; ++ } ++ ++ slotForKey = PK11_GetSlotFromKey(baseKey); ++ ++ int keyOnRequestedSlot = 0; ++ int baseKeyMoved= 0; ++ ++ if(slotForKey != slot) { ++ keyOnRequestedSlot = 0; ++ } else { ++ keyOnRequestedSlot = 1; ++ finalBaseKeySlot = slot; ++ } ++ ++ if ( PK11_DoesMechanism( slot, deriveMechanism)) { ++ if ( keyOnRequestedSlot ) { ++ finalBaseKey = baseKey; ++ } else { ++ bestBaseKey = PK11_MoveSymKey( slot, CKA_ENCRYPT, 0, PR_FALSE, baseKey ); ++ if(bestBaseKey == NULL) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't move Base Key to requested slot!\n"); ++ goto loser; ++ } ++ baseKeyMoved = 1; ++ finalBaseKey = bestBaseKey; ++ finalBaseKeySlot = slot; ++ } ++ ++ } else { ++ bestBaseKey = PK11_MoveSymKey( bestSlot, CKA_ENCRYPT, 0, PR_FALSE, baseKey ); ++ if(bestBaseKey == NULL) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't move Base Key to best slot!\n"); ++ goto loser; ++ } ++ baseKeyMoved = 1; ++ finalBaseKey = bestBaseKey; ++ finalBaseKeySlot = bestSlot; ++ } ++ ++ /* Assume we want to do a concatenation family here */ ++ ++ if( secondaryKeyObj != NULL) { ++ if( JSS_PK11_getSymKeyPtr(env, secondaryKeyObj, &secondaryKey) != PR_SUCCESS) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't find secondary sym key!\n"); ++ goto loser; ++ } ++ ++ /* Make sure the secondary key is in the proper slot to do concatenation */ ++ ++ slotForSecondaryKey = PK11_GetSlotFromKey( secondaryKey ); ++ ++ if( finalBaseKeySlot != slotForSecondaryKey ) { ++ ++ finalSecondaryKey = PK11_MoveSymKey (finalBaseKeySlot, CKA_ENCRYPT, 0, PR_FALSE, secondaryKey); ++ ++ if( finalSecondaryKey == NULL) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey, Problem moving secondary key to proper slot.\n"); ++ goto loser; ++ } ++ } else { ++ finalSecondaryKey = secondaryKey; ++ } ++ ++ if( paramValue == NULL) { ++ keyhandle = PK11_GetSymKeyHandle(finalSecondaryKey); ++ ++ if( keyhandle == 0) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey, can't get handle for secondary sym key.\n"); ++ goto loser; ++ } ++ ++ paramsItem.data=(unsigned char *) &keyhandle; ++ paramsItem.len=sizeof(keyhandle); ++ ++ } else { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: incorrect input parameter provided!\n"); ++ goto loser; ++ } ++ } ++ ++ derivedKey = PK11_Derive(finalBaseKey, deriveMechanism, ¶msItem, targetMechanism, ++ operation, keySize); ++ if(derivedKey == NULL) { ++ PR_fprintf(PR_STDOUT, ++ "ERROR: Can't derive symmetric key, error: %d \n",PR_GetError()); ++ goto loser; ++ } ++ ++ if ( (finalSlot = PK11_GetSlotFromKey(derivedKey )) != slot) { ++ newKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, derivedKey); ++ ++ if ( newKey == NULL ) { ++ PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: error moving key to original slot, return anyway. \n"); ++ newKey = derivedKey; ++ derivedKey = NULL; ++ } ++ ++ } else { ++ newKey = derivedKey; ++ derivedKey = NULL; ++ } ++ ++ keyObj = JSS_PK11_wrapSymKey(env, &newKey); ++ ++loser: ++ ++ if ( bestBaseKey != NULL ) { ++ PK11_FreeSymKey ( bestBaseKey ); ++ bestBaseKey = NULL; ++ } ++ ++ if ( bestSecondaryKey != NULL ) { ++ PK11_FreeSymKey ( bestSecondaryKey ); ++ bestSecondaryKey = NULL; ++ } ++ ++ if ( derivedKey != NULL) { ++ PK11_FreeSymKey ( derivedKey ); ++ derivedKey = NULL; ++ } ++ ++ if (bestSlot != NULL ) { ++ PK11_FreeSlot(bestSlot); ++ bestSlot = NULL; ++ } ++ ++ if ( slotForKey != NULL ) { ++ PK11_FreeSlot( slotForKey ); ++ slotForKey = NULL; ++ } ++ ++ if ( finalSlot != NULL ) { ++ PK11_FreeSlot( finalSlot ); ++ finalSlot = NULL; ++ } ++ ++ if ( finalSecondarySlot != NULL ) { ++ PK11_FreeSlot( finalSecondarySlot ); ++ finalSecondarySlot = NULL; ++ } ++ ++ if ( slotForSecondaryKey != NULL ) { ++ PK11_FreeSlot( slotForSecondaryKey ); ++ slotForSecondaryKey = NULL; ++ } ++ ++ if(paramValue) { ++ (*env)->ReleaseByteArrayElements(env, param, (jbyte*)paramValue, ++ JNI_ABORT); ++ } ++ if(ivValue) { ++ (*env)->ReleaseByteArrayElements(env, iv, (jbyte*)ivValue, ++ JNI_ABORT); ++ } ++ ++ if( keyObj == NULL) { ++ JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to derive symmetric key! " ++ "failure!"); ++ } ++ ++ return keyObj; ++} +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.java.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.java +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.java.jmagne 2016-04-14 16:28:29.179823017 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.java 2016-04-14 16:28:36.186774680 -0700 +@@ -0,0 +1,158 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the Netscape Security Services for Java. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998-2000 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++package org.mozilla.jss.pkcs11; ++ ++import org.mozilla.jss.crypto.*; ++import org.mozilla.jss.util.Assert; ++import sun.security.pkcs11.wrapper.*; ++import java.security.InvalidKeyException; ++ ++ ++/*This operation is pkcs11 based only */ ++ ++public class PK11SymmetricKeyDeriver implements SymmetricKeyDeriver { ++ ++ private PK11Token token = null; ++ private SymmetricKey baseKey = null; ++ private SymmetricKey secondaryKey = null; ++ private long deriveMechanism = 0; ++ private long targetMechanism = 0; ++ private long operation = 0; ++ private long keySize = 0; ++ private byte[] param = null; ++ private byte[] iv = null; ++ ++ public PK11SymmetricKeyDeriver(PK11Token token) ++ { ++ this.token = token; ++ } ++ ++ /* Use with the encrypt type mechanisms ++ ++ Example: initDerive( ++ symKey, (PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA) 4354L, derivationData, null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16); ++ ++ ++ */ ++ public void initDerive(SymmetricKey baseKey, long deriveMech, byte[] param, byte[] iv, ++ long targetMech, long operation, long keySize) throws InvalidKeyException ++ { ++ reset(); ++ ++ if(baseKey == null) { ++ throw new InvalidKeyException("Key is null"); ++ } ++ ++ this.baseKey = baseKey; ++ this.deriveMechanism = deriveMech; ++ this.targetMechanism = targetMech; ++ this.operation = operation; ++ ++ if ( param != null) { ++ this.param = new byte[param.length]; ++ System.arraycopy(param,0,this.param,0,param.length); ++ } ++ ++ if ( iv != null) { ++ this.iv = new byte[iv.length]; ++ System.arraycopy(iv,0,this.iv,0,iv.length); ++ } ++ ++ this.keySize = keySize; ++ ++ } ++ ++ /* Use with key extraction and key concatanation mechanisms ++ ++ Example Extraction: ++ param: byte array that has the bit position of where to extract ++ initDerive( ++ derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, ++ PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8); ++ ++ Example Concat: ++ ++ initDerive( ++ baseSymKey,secondarySymKey, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0); ++ ++ */ ++ ++ public void initDerive(SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMech, ++ byte[] param, byte[] iv, long targetMech, long operation, long keySize) throws InvalidKeyException ++ { ++ reset(); ++ ++ if ( baseKey == null || secondaryKey == null) { ++ throw new InvalidKeyException("Key is null"); ++ } ++ ++ initDerive(baseKey, deriveMech, param,iv,targetMech,operation,keySize); ++ this.secondaryKey = secondaryKey; ++ ++ } ++ ++ ++ public SymmetricKey derive() ++ throws TokenException ++ { ++ SymmetricKey result = deriveSymKey(this.baseKey,this.secondaryKey,this.deriveMechanism, this.param, this.iv, this.targetMechanism, this.operation,this.keySize); ++ return result; ++ } ++ ++ private SymmetricKey ++ deriveSymKey(SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMechanism, byte[] param, byte[] iv, long targetMechanism, long operation, long keySize) ++ throws TokenException, IllegalStateException ++ { ++ return nativeDeriveSymKey(token, baseKey, secondaryKey,deriveMechanism, param, iv, targetMechanism, operation, keySize); ++ } ++ ++ public native SymmetricKey nativeDeriveSymKey(PK11Token token, SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMechanism, byte[] param, byte[] iv, ++ long targetMechanism, long operation, long keySize); ++ ++ private void reset() { ++ baseKey = null; ++ secondaryKey = null; ++ deriveMechanism = 0; ++ targetMechanism = 0; ++ operation = 0; ++ keySize = 0; ++ param = null; ++ iv = null; ++ } ++} +diff -up ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java.jmagne ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java +--- ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java.jmagne 2016-04-14 16:30:46.098878459 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/pkcs11/PK11Token.java 2016-04-14 17:27:30.918367372 -0700 +@@ -131,6 +131,11 @@ public final class PK11Token implements + return PK11KeyGenerator.clone(key, this); + } + ++ public PK11SymmetricKeyDeriver getSymmetricKeyDeriver() ++ { ++ return new PK11SymmetricKeyDeriver(this); ++ } ++ + public KeyWrapper + getKeyWrapper(KeyWrapAlgorithm algorithm) + throws NoSuchAlgorithmException, TokenException +diff -up ./mozilla/security/jss/org/mozilla/jss/tests/SymKeyDeriving.java.jmagne ./mozilla/security/jss/org/mozilla/jss/tests/SymKeyDeriving.java +--- ./mozilla/security/jss/org/mozilla/jss/tests/SymKeyDeriving.java.jmagne 2016-04-14 16:32:58.529964860 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/tests/SymKeyDeriving.java 2016-05-17 11:43:51.858862556 -0700 +@@ -0,0 +1,516 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the Netscape Security Services for Java. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998-2000 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++package org.mozilla.jss.tests; ++ ++import org.mozilla.jss.crypto.*; ++import org.mozilla.jss.CryptoManager; ++import org.mozilla.jss.util.Assert; ++import org.mozilla.jss.pkcs11.*; ++import sun.security.pkcs11.wrapper.PKCS11Constants; ++import java.nio.ByteBuffer; ++import java.util.Arrays; ++import java.util.Vector; ++import java.util.Enumeration; ++ ++/** ++ * Sym Key deriving tests.. ++ * ++ */ ++ ++public class SymKeyDeriving { ++ ++ private static final byte[] iv8 = new byte [] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 }; ++ private static final byte[] iv16 = new byte [] { 0x1, 0x2, 0x3, 0x4, ++ 0x5, 0x6, 0x7, 0x8, ++ 0x9,0xa, 0xb, 0xc,0xd,0xe, 0xf,0x10 }; ++ ++ private static final byte[] derivationData1 = new byte[] { 0x11, 0x11, 0x13, ++ 0x14, 0x15, 0x16, 0x17, 0x18 }; ++ ++ private static final byte[] derivationData2 = new byte [] { 0x9, 0xa, 0xb, 0xc, 0xd, ++ 0xe, 0xf, 0x10 }; ++ ++ private static final byte[] derivationData16 = new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,0x7, 0x8, ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10 }; ++ ++ ++ public static void main(String args[]) { ++ ++ SymmetricKey macKeyDev = null; ++ try { ++ ++ CryptoManager.InitializationValues vals = ++ new CryptoManager.InitializationValues("./" ++ ); ++ CryptoManager.initialize(vals); ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalCryptoToken(); ++ CryptoToken keyToken = cm.getInternalKeyStorageToken(); ++ System.out.println("interal token name: " + keyToken.getName()); ++ KeyGenerator keyKg = keyToken.getKeyGenerator(KeyGenAlgorithm.DES3); ++ SymmetricKey baseKey = keyKg.generate(); ++ ++ ++ KeyGenerator keyKgDes = keyToken.getKeyGenerator(KeyGenAlgorithm.DES); ++ SymmetricKey baseKeyDes = keyKgDes.generate(); ++ System.out.println("strength: " + baseKeyDes.getStrength()); ++ ++ ++ KeyGenerator keyKgAES = keyToken.getKeyGenerator(KeyGenAlgorithm.AES); ++ keyKgAES.initialize(128); ++ SymmetricKey baseKeyAES = keyKgAES.generate(); ++ ++ ++ ++ System.out.println("baseKey bytes: "); ++ byte[] baseBytes = baseKey.getEncoded(); ++ displayByteArray(baseBytes,true); ++ ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_EXTRACT_KEY_FROM_KEY test 16 bytes. \n"); ++ ++ ++ SymmetricKeyDeriver deriver = token.getSymmetricKeyDeriver(); ++ System.out.println("deriver: " + deriver); ++ System.out.println("CKM_EXTRACT_KEY_FROM_KEY : " + PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY); ++ ++ long bitPosition = 0; ++ ++ byte[] param = longToBytes(bitPosition); ++ ++ deriver.initDerive( ++ baseKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, ++ PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,(long) 16); ++ ++ ++ SymmetricKey extracted16 = deriver.derive(); ++ ++ System.out.println("Derived key: " + extracted16); ++ ++ if(extracted16 == null) { ++ System.out.println("Failed to derive 16 byte key with mechanism: CKM_EXTRACT_KEY_FROM_KEY \n"); ++ } ++ ++ System.out.println("derivedKey 16 bytes: "); ++ byte[] derivedBytes = extracted16.getEncoded(); ++ displayByteArray(derivedBytes,true); ++ ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_EXTRACT_KEY_FROM_KEY test 8 bytes. \n"); ++ ++ ++ SymmetricKeyDeriver extract8 = token.getSymmetricKeyDeriver(); ++ extract8.initDerive( ++ extracted16, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, ++ PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,(long) 8); ++ ++ ++ SymmetricKey extracted8 = extract8.derive(); ++ System.out.println("Derived key: " + extracted8); ++ ++ if(extracted8 == null) { ++ System.out.println("Failed to derive key extracted 8 bytes with mechanism: CKM_EXTRACT_KEY_FROM_KEY \n"); ++ } ++ ++ byte[] extracted8Bytes = extracted8.getEncoded(); ++ System.out.println("derived extracted 8 bytes of key: "); ++ displayByteArray(extracted8Bytes,true); ++ ++ ++ /*****************************************************************************************************/ ++ ++ ++ System.out.println("\n Mechanism CKM_CONCATENATE_BASE_AND_KEY test 16 + 8 = 24 byte key. \n"); ++ ++ SymmetricKeyDeriver concat = keyToken.getSymmetricKeyDeriver(); ++ concat.initDerive( ++ extracted16,extracted8, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,(long) 0); ++ ++ SymmetricKey concated24 = concat.derive(); ++ ++ if( concated24 == null) { ++ System.out.println("Failed to derive key concated 8 bytes to 16 bytes key: CKM_CONCATENATE_BASE_AND_KEY \n"); ++ } ++ ++ byte[] concated24Bytes = concated24.getEncoded(); ++ System.out.println("derived concated 16 + 8 = 24 byte key: "); ++ displayByteArray(concated24Bytes,true); ++ ++ /*****************************************************************************************************/ ++ ++ // Now lets try more complex derivation ++ ++ // tmp2 = PK11_Derive( master , CKM_DES_ECB_ENCRYPT_DATA , ¶m , CKM_CONCATENATE_BASE_AND_KEY , CKA_DERIVE , 0); ++ ++ System.out.println("\n Mechanism CKM_DES_ECB_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encrypt = token.getSymmetricKeyDeriver(); ++ ++ encrypt.initDerive( ++ baseKeyDes, /* PKCS11Constants.CKM_DES_ECB_ENCRYPT_DATA */ 4352L,derivationData1 ,null, ++ PKCS11Constants.CKM_DES_ECB, PKCS11Constants.CKA_DERIVE,(long) 8); ++ ++ SymmetricKey encrypted8 = encrypt.derive(); ++ ++ if( encrypted8 == null) { ++ System.out.println("Failed to derive 8 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encrypted8Bytes = encrypted8.getEncoded(); ++ System.out.println("derived encrypted 8 bytes: " + encrypted8Bytes.length); ++ displayByteArray(encrypted8Bytes,true); ++ ++ Cipher cipher = null; ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES_ECB); ++ ++ cipher.initEncrypt(baseKeyDes); ++ ++ byte[] ciphertext = cipher.doFinal(derivationData1); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encrypted8Bytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encrypted8Bytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encrypted8Bytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ ++ /*****************************************************************************************************/ ++ ++ // Try ecnrypted des3 derivation ++ ++ System.out.println("\n Mechanism CKM_DES3_ECB_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encryptDes3 = token.getSymmetricKeyDeriver(); ++ ++ encryptDes3.initDerive( ++ baseKey, /* PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA */ 4354L ,derivationData16 ,null, ++ PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,(long) 16); ++ ++ ++ SymmetricKey encrypted16 = encryptDes3.derive(); ++ ++ if ( encrypted16 == null) { ++ System.out.println("Failed to derive 16 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encrypted16Bytes = encrypted16.getEncoded(); ++ ++ System.out.println("derived encrypted 16 bytes: " + encrypted16Bytes.length); ++ displayByteArray(encrypted16Bytes,true); ++ ++ ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES3_ECB); ++ cipher.initEncrypt(baseKey); ++ ciphertext = cipher.doFinal(derivationData16); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encrypted16Bytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encrypted16Bytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encrypted16Bytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_DES_CBC_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encryptDesCBC = token.getSymmetricKeyDeriver(); ++ ++ encryptDesCBC.initDerive( ++ baseKeyDes, /* PKCS11Constants.CKM_DES_CBC_ENCRYPT_DATA */ 4353L ,derivationData1 ,iv8, ++ PKCS11Constants.CKM_DES_CBC, PKCS11Constants.CKA_DERIVE,(long) 8); ++ ++ ++ SymmetricKey encryptedDesCBC = encryptDesCBC.derive(); ++ ++ if ( encryptedDesCBC == null) { ++ System.out.println("Failed to derive 8 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encryptedDesCBCBytes = encryptedDesCBC.getEncoded(); ++ ++ System.out.println("derived encrypted 8 bytes: " + encryptedDesCBCBytes.length); ++ displayByteArray(encryptedDesCBCBytes,true); ++ ++ ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES_CBC); ++ cipher.initEncrypt(baseKeyDes,new IVParameterSpec(iv8)); ++ ciphertext = cipher.doFinal(derivationData1); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encryptedDesCBCBytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encryptedDesCBCBytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encryptedDesCBCBytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_DES3_CBC_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encryptDes3CBC = token.getSymmetricKeyDeriver(); ++ ++ encryptDes3CBC.initDerive( ++ baseKey, /* PKCS11Constants.CKM_DES3_CBC_ENCRYPT_DATA */ 4355L ,derivationData16 ,iv8, ++ PKCS11Constants.CKM_DES3_CBC, PKCS11Constants.CKA_DERIVE,(long) 16); ++ ++ ++ SymmetricKey encryptedDes3CBC = encryptDes3CBC.derive(); ++ ++ if ( encryptedDes3CBC == null) { ++ System.out.println("Failed to derive 16 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encryptedDes3CBCBytes = encryptedDes3CBC.getEncoded(); ++ ++ System.out.println("derived encrypted 16 bytes: " + encryptedDes3CBCBytes.length); ++ displayByteArray(encryptedDes3CBCBytes,true); ++ ++ ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES3_CBC); ++ cipher.initEncrypt(baseKey,new IVParameterSpec(iv8)); ++ ciphertext = cipher.doFinal(derivationData16); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encryptedDes3CBCBytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encryptedDes3CBCBytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encryptedDes3CBCBytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_AES_ECB_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encryptAESECB = token.getSymmetricKeyDeriver(); ++ ++ //System.in.read(); ++ encryptAESECB.initDerive( ++ baseKeyAES, /* PKCS11Constants.CKM_AES_ECB_ENCRYPT_DATA */ 4356L ,derivationData16 ,null, ++ PKCS11Constants.CKM_AES_ECB, PKCS11Constants.CKA_DERIVE,(long) 16); ++ ++ ++ SymmetricKey encryptedAESECB = encryptAESECB.derive(); ++ ++ if ( encryptedAESECB == null) { ++ System.out.println("Failed to derive 16 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encryptedAESECBBytes = encryptedAESECB.getEncoded(); ++ ++ System.out.println("derived encrypted 16 bytes: " + encryptedAESECBBytes.length); ++ displayByteArray(encryptedAESECBBytes,true); ++ ++ ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.AES_128_ECB); ++ cipher.initEncrypt(baseKeyAES); ++ ciphertext = cipher.doFinal(derivationData16); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encryptedAESECBBytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encryptedAESECBBytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encryptedAESECBBytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ ++ /*****************************************************************************************************/ ++ ++ System.out.println("\n Mechanism CKM_AES_CBC_ENCRYPT_DATA test. \n"); ++ ++ SymmetricKeyDeriver encryptAESCBC= token.getSymmetricKeyDeriver(); ++ ++ //System.in.read(); ++ encryptAESCBC.initDerive( ++ baseKeyAES, /* PKCS11Constants.CKM_AES_CBC_ENCRYPT_DATA */ 4357L ,derivationData16 ,iv16, ++ PKCS11Constants.CKM_AES_CBC, PKCS11Constants.CKA_DERIVE,(long) 16); ++ ++ ++ SymmetricKey encryptedAESCBC = encryptAESCBC.derive(); ++ ++ if ( encryptedAESCBC == null) { ++ System.out.println("Failed to derive 16 bytes from encrypted derivation data."); ++ } ++ ++ byte[] encryptedAESCBCBytes = encryptedAESCBC.getEncoded(); ++ ++ System.out.println("derived encrypted 16 bytes: " + encryptedAESCBCBytes.length); ++ displayByteArray(encryptedAESCBCBytes,true); ++ ++ ++ cipher = keyToken.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ cipher.initEncrypt(baseKeyAES,new IVParameterSpec(iv16)); ++ ciphertext = cipher.doFinal(derivationData16); ++ displayByteArray(ciphertext,true); ++ ++ if ( ciphertext.length != encryptedAESCBCBytes.length ) { ++ System.out.println("FAILED: encrypted data length not equal to derived key length."); ++ } else { ++ for ( int i = 0; i < ciphertext.length ; i ++) { ++ ciphertext[i]&=0xfe; ++ encryptedAESCBCBytes[i]&=0xfe; ++ } ++ if ( Arrays.equals(ciphertext, encryptedAESCBCBytes)) { ++ System.out.println("PASSED: derived key the same as encrypted data."); ++ } else { ++ ++ System.out.println("FAILED: derived key not the same as encrypted data."); ++ } ++ } ++ ++ // get vector of symkeys ++ ++ Enumeration ect = null; ++ ect = (Enumeration) cm.getAllTokens(); ++ CryptoToken ct = null; //ct = cm.getTokenByName("ePass Token"); ++ while (ect.hasMoreElements()) ++ { ++ ct = ect.nextElement(); ++ System.out.println("CryptoToken.name= " + ct.getName()); ++ } ++ ++ SymmetricKey[] keys = keyToken.getCryptoStore().getSymmetricKeys(); ++ ++ SymmetricKey macKey = getSymKeyByName(keys, "defKeySet-macKey"); ++ ++ System.out.println("macKey: " + macKey); ++ ++ } catch(Exception e) { ++ e.printStackTrace(); ++ } ++ } ++ ++ public static void ++ displayByteArray(byte[] ba, boolean has_check_sum) { ++ char mask = 0xff; ++ ++ if ( has_check_sum == true ) ++ mask = 0xfe; ++ ++ for(int i=0; i < ba.length; i++) { ++ ++ System.out.print( Integer.toHexString(ba[i]&mask) + " " ); ++ if( (i % 26) == 25 ) { ++ System.out.println(""); ++ } ++ } ++ System.out.println(""); ++ } ++ ++ public static byte[] longToBytes(long x) { ++ ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); ++ buffer.putLong(x); ++ return buffer.array(); ++ } ++ ++ public static byte[] concatByteArrays(byte[] a, byte[] b) { ++ byte[] result = new byte[a.length + b.length]; ++ System.arraycopy(a, 0, result, 0, a.length); ++ System.arraycopy(b, 0, result, a.length, b.length); ++ return result; ++ } ++ ++ public static SymmetricKey getSymKeyByName( SymmetricKey[] keys, String name) { ++ if ( keys == null || name == null ) { ++ return null; ++ } ++ ++ int len = keys.length; ++ for(int i = 0 ; i < len ; i++ ) { ++ SymmetricKey cur = keys[i]; ++ if ( cur != null ) { ++ if( name.equals(cur.getNickName())) { ++ System.out.println("Found key: " + name + "\n"); ++ return cur; ++ } ++ } ++ } ++ ++ return null; ++ } ++} +diff -up ./mozilla/security/jss/org/mozilla/jss/util/java_ids.h.jmagne ./mozilla/security/jss/org/mozilla/jss/util/java_ids.h +--- ./mozilla/security/jss/org/mozilla/jss/util/java_ids.h.jmagne 2016-04-14 16:34:36.729287416 -0700 ++++ ./mozilla/security/jss/org/mozilla/jss/util/java_ids.h 2016-04-14 16:34:45.608226163 -0700 +@@ -243,6 +243,7 @@ PR_BEGIN_EXTERN_C + */ + #define PK11SYMKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11SymKey" + #define PK11SYMKEY_CONSTRUCTOR_SIG "([B)V" ++#define PK11SYMKEY_CONSTRUCTOR_1_SIG "([BLjava/lang/String;)V" + + /* + * PK11Token diff --git a/jss.spec b/jss.spec index b4aa19e..869eab4 100644 --- a/jss.spec +++ b/jss.spec @@ -1,6 +1,6 @@ Name: jss Version: 4.2.6 -Release: 38%{?dist} +Release: 39%{?dist} Summary: Java Security Services (JSS) Group: System Environment/Libraries @@ -16,11 +16,11 @@ Source2: http://pki.fedoraproject.org/pki/sources/%{name}/%{name}-%{versi Source3: http://pki.fedoraproject.org/pki/sources/%{name}/%{name}-%{version}-%{release}/lgpl.txt BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: nss-devel >= 3.14.3 -BuildRequires: nspr-devel >= 4.9.5 +BuildRequires: nss-devel >= 3.21.0 +BuildRequires: nspr-devel >= 4.11.0 BuildRequires: java-devel Requires: java-headless -Requires: nss >= 3.14.3 +Requires: nss >= 3.21.0 Patch1: jss-key_pair_usage_with_op_flags.patch Patch2: jss-javadocs-param.patch @@ -49,6 +49,9 @@ Patch24: jss-SHA-OID-fix.patch Patch25: jss-RC4-strengh-verify.patch Patch26: jss-support-TLS1_1-TLS1_2.patch Patch27: jss-Fixed-build-failures.patch +Patch28: jss-VerifyCertificate-enhancement.patch +Patch29: jss-lunasaUnwrap.patch +Patch30: jss-symkey-enhancements.patch %description @@ -93,6 +96,9 @@ This package contains the API documentation for JSS. %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 %build [ -z "$JAVA_HOME" ] && export JAVA_HOME=%{_jvmdir}/java @@ -197,6 +203,14 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu May 19 2016 Christina Fu - 4.2.6-39 +- Bugzilla 1074208 - pass up exact JSS certificate validation errors from NSS + (edewata) +- Bugzilla 1331596 - Key archival fails when KRA is configured with lunasa. + (cfu) +- PKI ticket 801 - Merge pki-symkey into jss (phase 1) + (jmagne) + * Wed Dec 09 2015 Endi Dewata - 4.2.6-38 - Bugzilla Bug #1289799 - JSS build failure on F23 and Rawhide (edewata)