commit d4767398bfa837a9b98c2121095df6535a377003 Author: CentOS Sources Date: Mon Nov 11 07:59:15 2019 -0500 import jss-4.6.0-5.module+el8.1.0+4218+3fd65c36 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52b077b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/jss-4.6.0.tar.gz diff --git a/.jss.metadata b/.jss.metadata new file mode 100644 index 0000000..cb4e805 --- /dev/null +++ b/.jss.metadata @@ -0,0 +1 @@ +3d6d2d885129e0d7d8ebac5dfe9055c693a7a9b1 SOURCES/jss-4.6.0.tar.gz diff --git a/SOURCES/0001-Disable-buffer-based-tests.patch b/SOURCES/0001-Disable-buffer-based-tests.patch new file mode 100644 index 0000000..f39763a --- /dev/null +++ b/SOURCES/0001-Disable-buffer-based-tests.patch @@ -0,0 +1,71 @@ +From d7d6d769b510118e40d9c0919317665c4c9feb8d Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 12 Jun 2019 17:17:45 -0400 +Subject: [PATCH] Disable buffer-based tests + +Signed-off-by: Alexander Scheel +--- + cmake/JSSTests.cmake | 33 --------------------------------- + 1 file changed, 33 deletions(-) + +diff --git a/cmake/JSSTests.cmake b/cmake/JSSTests.cmake +index b389be5c..473d7d4d 100644 +--- a/cmake/JSSTests.cmake ++++ b/cmake/JSSTests.cmake +@@ -78,24 +78,6 @@ macro(jss_tests) + NAME "BigObjectIdentifier" + COMMAND "org.mozilla.jss.tests.BigObjectIdentifier" + ) +- jss_test_java( +- NAME "JSS_Test_PR_FileDesc" +- COMMAND "org.mozilla.jss.tests.TestPRFD" +- ) +- jss_test_java( +- NAME "JSS_Test_Raw_SSL" +- COMMAND "org.mozilla.jss.tests.TestRawSSL" "${RESULTS_NSSDB_OUTPUT_DIR}" +- DEPENDS "Setup_DBs" +- ) +- jss_test_java( +- NAME "JSS_Test_Buffer" +- COMMAND "org.mozilla.jss.tests.TestBuffer" +- ) +- jss_test_java( +- NAME "JSS_Test_BufferPRFD" +- COMMAND "org.mozilla.jss.tests.TestBufferPRFD" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}" +- DEPENDS "List_CA_certs" +- ) + if ((${Java_VERSION_MAJOR} EQUAL 1) AND (${Java_VERSION_MINOR} LESS 9)) + jss_test_java( + NAME "Test_PKCS11Constants.java_for_Sun_compatibility" +@@ -126,16 +108,6 @@ macro(jss_tests) + NAME "JUnit_UTF8StringTest" + COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UTF8StringTest" + ) +- jss_test_exec( +- NAME "buffer_size_1" +- COMMAND "${BIN_OUTPUT_DIR}/buffer_size_1" +- DEPENDS "generate_c_buffer_size_1" +- ) +- jss_test_exec( +- NAME "buffer_size_4" +- COMMAND "${BIN_OUTPUT_DIR}/buffer_size_4" +- DEPENDS "generate_c_buffer_size_4" +- ) + jss_test_java( + NAME "JUnit_ChainSortingTest" + COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.ChainSortingTest" +@@ -180,11 +152,6 @@ macro(jss_tests) + COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH}" "50" + DEPENDS "List_CA_certs" + ) +- jss_test_exec( +- NAME "TestBufferPRFD" +- COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFD" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}" +- DEPENDS "List_CA_certs" "generate_c_TestBufferPRFD" +- ) + jss_test_java( + NAME "Key_Generation" + COMMAND "org.mozilla.jss.tests.TestKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" +-- +2.21.0 + diff --git a/SOURCES/0002-Support-LD_FLAGS-from-environment.patch b/SOURCES/0002-Support-LD_FLAGS-from-environment.patch new file mode 100644 index 0000000..eaa0e60 --- /dev/null +++ b/SOURCES/0002-Support-LD_FLAGS-from-environment.patch @@ -0,0 +1,39 @@ +From 731b62d4c456a3e1a70519c24eb0df2c59d943b4 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Mon, 17 Jun 2019 08:48:01 -0400 +Subject: [PATCH] Support LD_FLAGS from environment + +Signed-off-by: Alexander Scheel +--- + cmake/JSSConfig.cmake | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/cmake/JSSConfig.cmake b/cmake/JSSConfig.cmake +index f045850a..e63dd5fa 100644 +--- a/cmake/JSSConfig.cmake ++++ b/cmake/JSSConfig.cmake +@@ -174,6 +174,11 @@ macro(jss_config_ldflags) + list(APPEND JSS_LD_FLAGS "-lpthread") + list(APPEND JSS_LD_FLAGS "-ldl") + ++ separate_arguments(PASSED_LD_FLAGS UNIX_COMMAND "${CMAKE_SHARED_LINKER_FLAGS}") ++ foreach(PASSED_LD_FLAG ${PASSED_LD_FLAGS}) ++ list(INSERT JSS_LD_FLAGS 0 "${PASSED_LD_FLAG}") ++ endforeach() ++ + # This set of flags is specific to building the libjss library. + list(APPEND JSS_LIBRARY_FLAGS "-shared") + list(APPEND JSS_LIBRARY_FLAGS "-Wl,-z,defs") +@@ -181,6 +186,9 @@ macro(jss_config_ldflags) + list(APPEND JSS_LIBRARY_FLAGS "-Wl,${JSS_SO}") + + set(JSS_VERSION_SCRIPT "-Wl,--version-script,${PROJECT_SOURCE_DIR}/lib/jss.map") ++ ++ message(STATUS "JSS LD FLAGS: ${JSS_LD_FLAGS}") ++ message(STATUS "JSS LIBRARY FLAGS: ${JSS_LIBRARY_FLAGS}") + endmacro() + + macro(jss_config_java) +-- +2.20.1 + diff --git a/SOURCES/0003-Remove-legacy-DSA-implementation.patch b/SOURCES/0003-Remove-legacy-DSA-implementation.patch new file mode 100644 index 0000000..9915a51 --- /dev/null +++ b/SOURCES/0003-Remove-legacy-DSA-implementation.patch @@ -0,0 +1,2197 @@ +From 34e52cf538fab7786be6298de05d7a1ad0b652b7 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 14 Aug 2019 14:38:39 -0400 +Subject: [PATCH] Remove legacy DSA implementation + +This is better suited for NSS via the Mozilla-JSS provider. This entire +provider could eventually be removed if we wished, but certain +functionality required by PKI transitively depends on it. It is never +explicitly added though, so I'm not convinced those places truly use it +via the intended APIs. However, various classes inside the provider are +used directly (such as RSAPublicKey and DSAPublicKey). + +Signed-off-by: Alexander Scheel +--- + .../jss/netscape/security/provider/DSA.java | 664 ------------------ + .../provider/DSAKeyPairGenerator.java | 389 ---------- + .../provider/DSAParameterGenerator.java | 298 -------- + .../jss/netscape/security/provider/MD5.java | 378 ---------- + .../jss/netscape/security/provider/SHA.java | 349 --------- + .../jss/netscape/security/provider/Sun.java | 43 -- + 6 files changed, 2121 deletions(-) + delete mode 100644 org/mozilla/jss/netscape/security/provider/DSA.java + delete mode 100644 org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java + delete mode 100644 org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java + delete mode 100644 org/mozilla/jss/netscape/security/provider/MD5.java + delete mode 100644 org/mozilla/jss/netscape/security/provider/SHA.java + +diff --git a/org/mozilla/jss/netscape/security/provider/DSA.java b/org/mozilla/jss/netscape/security/provider/DSA.java +deleted file mode 100644 +index abc320f4..00000000 +--- a/org/mozilla/jss/netscape/security/provider/DSA.java ++++ /dev/null +@@ -1,664 +0,0 @@ +-// --- BEGIN COPYRIGHT BLOCK --- +-// This program is free software; you can redistribute it and/or modify +-// it under the terms of the GNU General Public License as published by +-// the Free Software Foundation; version 2 of the License. +-// +-// This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of +-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-// GNU General Public License for more details. +-// +-// You should have received a copy of the GNU General Public License along +-// with this program; if not, write to the Free Software Foundation, Inc., +-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-// +-// (C) 2007 Red Hat, Inc. +-// All rights reserved. +-// --- END COPYRIGHT BLOCK --- +-package org.mozilla.jss.netscape.security.provider; +- +-import java.io.IOException; +-import java.io.PrintStream; +-import java.math.BigInteger; +-import java.security.InvalidKeyException; +-import java.security.InvalidParameterException; +-import java.security.MessageDigest; +-import java.security.NoSuchAlgorithmException; +-import java.security.PrivateKey; +-import java.security.PublicKey; +-import java.security.SecureRandom; +-import java.security.Signature; +-import java.security.SignatureException; +-import java.security.interfaces.DSAParams; +- +-import org.mozilla.jss.netscape.security.util.BigInt; +-import org.mozilla.jss.netscape.security.util.DerInputStream; +-import org.mozilla.jss.netscape.security.util.DerOutputStream; +-import org.mozilla.jss.netscape.security.util.DerValue; +- +-/** +- * The Digital Signature Standard (using the Digital Signature +- * Algorithm), as described in fips186 of the National Instute of +- * Standards and Technology (NIST), using fips180-1 (SHA-1). +- * +- * @author Benjamin Renaud +- * +- * @version 1.86, 97/09/17 +- * +- * @see DSAPublicKey +- * @see DSAPrivateKey +- */ +- +-public final class DSA extends Signature { +- +- /* Are we debugging? */ +- private static boolean debug = false; +- +- /* The parameter object */ +- @SuppressWarnings("unused") +- private DSAParams params; +- +- /* algorithm parameters */ +- private BigInteger presetP, presetQ, presetG; +- +- /* The public key, if any */ +- private BigInteger presetY; +- +- /* The private key, if any */ +- private BigInteger presetX; +- +- /* The SHA hash for the data */ +- private MessageDigest dataSHA; +- +- /* The random seed used to generate k */ +- private int[] Kseed; +- +- /* The random seed used to generate k (specified by application) */ +- private byte[] KseedAsByteArray; +- +- /* +- * The random seed used to generate k +- * (prevent the same Kseed from being used twice in a row +- */ +- private int[] previousKseed; +- +- /* The RNG used to output a seed for generating k */ +- private SecureRandom signingRandom; +- +- /** +- * Construct a blank DSA object. It can generate keys, but must be +- * initialized before being usable for signing or verifying. +- */ +- public DSA() throws NoSuchAlgorithmException { +- super("SHA/DSA"); +- dataSHA = MessageDigest.getInstance("SHA"); +- } +- +- /** +- * Initialize the DSA object with a DSA private key. +- * +- * @param privateKey the DSA private key +- * +- * @exception InvalidKeyException if the key is not a valid DSA private +- * key. +- */ +- protected void engineInitSign(PrivateKey privateKey) +- throws InvalidKeyException { +- if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) { +- throw new InvalidKeyException("not a DSA private key: " + +- privateKey); +- } +- java.security.interfaces.DSAPrivateKey priv = +- (java.security.interfaces.DSAPrivateKey) privateKey; +- +- this.presetX = priv.getX(); +- initialize(priv.getParams()); +- } +- +- /** +- * Initialize the DSA object with a DSA public key. +- * +- * @param publicKey the DSA public key. +- * +- * @exception InvalidKeyException if the key is not a valid DSA public +- * key. +- */ +- protected void engineInitVerify(PublicKey publicKey) +- throws InvalidKeyException { +- if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) { +- throw new InvalidKeyException("not a DSA public key: " + +- publicKey); +- } +- java.security.interfaces.DSAPublicKey pub = +- (java.security.interfaces.DSAPublicKey) publicKey; +- this.presetY = pub.getY(); +- initialize(pub.getParams()); +- } +- +- private void initialize(DSAParams params) { +- dataSHA.reset(); +- setParams(params); +- } +- +- /** +- * Sign all the data thus far updated. The signature is formatted +- * according to the Canonical Encoding Rules, returned as a DER +- * sequence of Integer, r and s. +- * +- * @return a signature block formatted according to the Canonical +- * Encoding Rules. +- * +- * @exception SignatureException if the signature object was not +- * properly initialized, or if another exception occurs. +- * +- * @see org.mozilla.jss.netscape.security.provider.DSA#engineUpdate +- * @see org.mozilla.jss.netscape.security.provider.DSA#engineVerify +- */ +- protected byte[] engineSign() throws SignatureException { +- BigInteger k = generateK(presetQ); +- BigInteger r = generateR(presetP, presetQ, presetG, k); +- BigInteger s = generateS(presetX, presetQ, r, k); +- +- // got to convert to BigInt... +- BigInt rAsBigInt = new BigInt(r.toByteArray()); +- BigInt sAsBigInt = new BigInt(s.toByteArray()); +- +- try (DerOutputStream outseq = new DerOutputStream(100)) { +- outseq.putInteger(rAsBigInt); +- outseq.putInteger(sAsBigInt); +- DerValue result = new DerValue(DerValue.tag_Sequence, +- outseq.toByteArray()); +- +- return result.toByteArray(); +- +- } catch (IOException e) { +- throw new SignatureException("error encoding signature"); +- } +- } +- +- /** +- * Verify all the data thus far updated. +- * +- * @param signature the alledged signature, encoded using the +- * Canonical Encoding Rules, as a sequence of integers, r and s. +- * +- * @exception SignatureException if the signature object was not +- * properly initialized, or if another exception occurs. +- * +- * @see org.mozilla.jss.netscape.security.provider.DSA#engineUpdate +- * @see org.mozilla.jss.netscape.security.provider.DSA#engineSign +- */ +- protected boolean engineVerify(byte[] signature) +- throws SignatureException { +- +- BigInteger r = null; +- BigInteger s = null; +- // first decode the signature. +- try { +- DerInputStream in = new DerInputStream(signature); +- DerValue[] values = in.getSequence(2); +- +- r = values[0].getInteger().toBigInteger(); +- s = values[1].getInteger().toBigInteger(); +- +- } catch (IOException e) { +- throw new SignatureException("invalid encoding for signature"); +- } +- BigInteger w = generateW(presetP, presetQ, presetG, s); +- BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r); +- +- return v.equals(r); +- } +- +- BigInteger generateR(BigInteger p, BigInteger q, BigInteger g, +- BigInteger k) { +- BigInteger temp = g.modPow(k, p); +- return temp.remainder(q); +- +- } +- +- BigInteger generateS(BigInteger x, BigInteger q, +- BigInteger r, BigInteger k) { +- +- byte[] s2 = dataSHA.digest(); +- BigInteger temp = new BigInteger(1, s2); +- BigInteger k1 = k.modInverse(q); +- +- BigInteger s = x.multiply(r); +- s = temp.add(s); +- s = k1.multiply(s); +- return s.remainder(q); +- } +- +- BigInteger generateW(BigInteger p, BigInteger q, +- BigInteger g, BigInteger s) { +- return s.modInverse(q); +- } +- +- BigInteger generateV(BigInteger y, BigInteger p, +- BigInteger q, BigInteger g, +- BigInteger w, BigInteger r) { +- +- byte[] s2 = dataSHA.digest(); +- BigInteger temp = new BigInteger(1, s2); +- +- temp = temp.multiply(w); +- BigInteger u1 = temp.remainder(q); +- +- BigInteger u2 = (r.multiply(w)).remainder(q); +- +- BigInteger t1 = g.modPow(u1, p); +- BigInteger t2 = y.modPow(u2, p); +- BigInteger t3 = t1.multiply(t2); +- BigInteger t5 = t3.remainder(p); +- return t5.remainder(q); +- } +- +- /* +- * Please read bug report 4044247 for an alternative, faster, +- * NON-FIPS approved method to generate K +- */ +- BigInteger generateK(BigInteger q) { +- +- BigInteger k = null; +- +- // The application specified a Kseed for us to use. +- // Note that we do not allow usage of the same Kseed twice in a row +- if (Kseed != null && compareSeeds(Kseed, previousKseed) != 0) { +- k = generateK(Kseed, q); +- if (k.signum() > 0 && k.compareTo(q) < 0) { +- previousKseed = new int[Kseed.length]; +- System.arraycopy(Kseed, 0, previousKseed, 0, Kseed.length); +- return k; +- } +- } +- +- // The application did not specify a Kseed for us to use. +- // We'll generate a new Kseed by getting random bytes from +- // a SecureRandom object. +- SecureRandom random = getSigningRandom(); +- +- while (true) { +- int[] seed = new int[5]; +- +- for (int i = 0; i < 5; i++) +- seed[i] = random.nextInt(); +- k = generateK(seed, q); +- if (k.signum() > 0 && k.compareTo(q) < 0) { +- previousKseed = new int[seed.length]; +- System.arraycopy(seed, 0, previousKseed, 0, seed.length); +- return k; +- } +- } +- } +- +- // Use the application-specified SecureRandom Object if provided. +- // Otherwise, use our default SecureRandom Object. +- private SecureRandom getSigningRandom() { +- if (signingRandom == null) { +- if (appRandom != null) +- signingRandom = appRandom; +- else +- signingRandom = new SecureRandom(); +- } +- return signingRandom; +- } +- +- /* +- * return 0 if equal +- * return 1 if not equal +- */ +- private int compareSeeds(int[] seed1, int[] seed2) { +- +- if (seed1 == null || seed2 == null) { +- return 1; +- } +- if (seed1.length != seed2.length) { +- return 1; +- } +- +- for (int i = 0; i < seed1.length; i++) { +- if (seed1[i] != seed2[i]) +- return 1; +- } +- +- return 0; +- +- } +- +- /** +- * Compute k for a DSA signature. +- * +- * @param seed the seed for generating k. This seed should be +- * secure. This is what is refered to as the KSEED in the DSA +- * specification. +- * +- * @param g the g parameter from the DSA key pair. +- */ +- BigInteger generateK(int[] seed, BigInteger q) { +- +- // check out t in the spec. +- int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476, +- 0xC3D2E1F0, 0x67452301 }; +- // +- int[] tmp = DSA.SHA_7(seed, t); +- byte[] tmpBytes = new byte[tmp.length * 4]; +- for (int i = 0; i < tmp.length; i++) { +- int k = tmp[i]; +- for (int j = 0; j < 4; j++) { +- tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8))); +- } +- } +- BigInteger k = new BigInteger(1, tmpBytes).mod(q); +- return k; +- } +- +- // Constants for each round +- private static final int round1_kt = 0x5a827999; +- private static final int round2_kt = 0x6ed9eba1; +- private static final int round3_kt = 0x8f1bbcdc; +- private static final int round4_kt = 0xca62c1d6; +- +- /** +- * Computes set 1 thru 7 of SHA-1 on m1. +- */ +- static int[] SHA_7(int[] m1, int[] h) { +- +- int[] W = new int[80]; +- System.arraycopy(m1, 0, W, 0, m1.length); +- int temp = 0; +- +- for (int t = 16; t <= 79; t++) { +- temp = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; +- W[t] = ((temp << 1) | (temp >>> (32 - 1))); +- } +- +- int a = h[0], b = h[1], c = h[2], d = h[3], e = h[4]; +- for (int i = 0; i < 20; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- ((b & c) | ((~b) & d)) + e + W[i] + round1_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 2 +- for (int i = 20; i < 40; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- (b ^ c ^ d) + e + W[i] + round2_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 3 +- for (int i = 40; i < 60; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- ((b & c) | (b & d) | (c & d)) + e + W[i] + round3_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 4 +- for (int i = 60; i < 80; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- (b ^ c ^ d) + e + W[i] + round4_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- int[] md = new int[5]; +- md[0] = h[0] + a; +- md[1] = h[1] + b; +- md[2] = h[2] + c; +- md[3] = h[3] + d; +- md[4] = h[4] + e; +- return md; +- } +- +- /** +- * This implementation recognizes the following parameter: +- *
+- * +- *
Kseed +- * +- *
a byte array. +- * +- *
+- * +- * @deprecated Replaced by engineSetParameter(AlgorithmParameterSpec params) +- */ +- @Deprecated +- protected void engineSetParameter(String key, Object param) { +- +- if (key.equals("KSEED")) { +- +- if (param instanceof byte[]) { +- +- Kseed = byteArray2IntArray((byte[]) param); +- KseedAsByteArray = (byte[]) param; +- +- } else { +- debug("unrecognized param: " + key); +- throw new InvalidParameterException("Kseed not a byte array"); +- } +- +- } else { +- throw new InvalidParameterException("invalid parameter"); +- } +- } +- +- /** +- * Return the value of the requested parameter. Recognized +- * parameters are: +- * +- *
+- * +- *
Kseed +- * +- *
a byte array. +- * +- *
+- * +- * @return the value of the requested parameter. +- * +- * @deprecated no replacent given +- * @see https://docs.oracle.com/javase/10/docs/api/java/security/SignatureSpi.html#engineGetParameter(java.lang.String) +- */ +- @Deprecated +- protected Object engineGetParameter(String key) { +- if (key.equals("KSEED")) { +- return KseedAsByteArray; +- } else { +- return null; +- } +- } +- +- /** +- * Set the algorithm object. +- */ +- private void setParams(DSAParams params) { +- this.params = params; +- this.presetP = params.getP(); +- this.presetQ = params.getQ(); +- this.presetG = params.getG(); +- } +- +- /** +- * Update a byte to be signed or verified. +- * +- * @param b the byte to updated. +- */ +- protected void engineUpdate(byte b) { +- dataSHA.update(b); +- } +- +- /** +- * Update an array of bytes to be signed or verified. +- * +- * @param data the bytes to be updated. +- */ +- protected void engineUpdate(byte[] data, int off, int len) { +- dataSHA.update(data, off, len); +- } +- +- /** +- * Return a human readable rendition of the engine. +- */ +- public String toString() { +- String printable = "DSA Signature"; +- if (presetP != null && presetQ != null && presetG != null) { +- printable += "\n\tp: " + presetP.toString(16); +- printable += "\n\tq: " + presetQ.toString(16); +- printable += "\n\tg: " + presetG.toString(16); +- } else { +- printable += "\n\t P, Q or G not initialized."; +- } +- if (presetY != null) { +- printable += "\n\ty: " + presetY.toString(16); +- } +- if (presetY == null && presetX == null) { +- printable += "\n\tUNINIIALIZED"; +- } +- return printable; +- } +- +- /* +- * Utility routine for converting a byte array into an int array +- */ +- private int[] byteArray2IntArray(byte[] byteArray) { +- +- int j = 0; +- byte[] newBA; +- int mod = byteArray.length % 4; +- +- // guarantee that the incoming byteArray is a multiple of 4 +- // (pad with 0's) +- switch (mod) { +- case 3: +- newBA = new byte[byteArray.length + 1]; +- break; +- case 2: +- newBA = new byte[byteArray.length + 2]; +- break; +- case 1: +- newBA = new byte[byteArray.length + 3]; +- break; +- default: +- newBA = new byte[byteArray.length + 0]; +- break; +- } +- System.arraycopy(byteArray, 0, newBA, 0, byteArray.length); +- +- // copy each set of 4 bytes in the byte array into an integer +- int[] newSeed = new int[newBA.length / 4]; +- for (int i = 0; i < newBA.length; i += 4) { +- newSeed[j] = newBA[i + 3] & 0xFF; +- newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00; +- newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000; +- newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000; +- j++; +- } +- +- return newSeed; +- } +- +- /* We include the test vectors from the DSA specification, FIPS +- 186, and the FIPS 186 Change No 1, which updates the test +- vector using SHA-1 instead of SHA (for both the G function and +- the message hash. */ +- +- static void testDSA() throws Exception { +- PrintStream p = System.out; +- +- DSA dsa = new DSA(); +- int[] Kseed = { 0x687a66d9, 0x0648f993, 0x867e121f, +- 0x4ddf9ddb, 0x1205584 }; +- BigInteger k = dsa.generateK(Kseed, q512); +- p.println("k: " + k.toString(16)); +- BigInteger r = dsa.generateR(p512, q512, g512, k); +- p.println("r: " + r.toString(16)); +- byte[] abc = { 0x61, 0x62, 0x63 }; +- dsa.dataSHA.update(abc); +- BigInteger s = dsa.generateS(x512, q512, r, k); +- p.println("s: " + s.toString(16)); +- +- dsa.dataSHA.update(abc); +- BigInteger w = dsa.generateW(p512, q512, g512, s); +- p.println("w: " + w.toString(16)); +- BigInteger v = dsa.generateV(y512, p512, q512, g512, w, r); +- p.println("v: " + v.toString(16)); +- if (v.equals(r)) { +- p.println("signature verifies."); +- } else { +- p.println("signature does not verify."); +- } +- } +- +- /* Test vector: 512-bit keys generated by our key generator. */ +- +- static BigInteger p512 = +- new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecb" + +- "cd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e1" + +- "2ed0899bcd132acd50d99151bdc43ee737592e17", 16); +- +- static BigInteger q512 = +- new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16); +- +- static BigInteger g512 = +- new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a43" + +- "4d6486931d2d14271b9e35030b71fd73da179069b32e" + +- "2935630e1c2062354d0da20a6c416e50be794ca4", 16); +- +- static BigInteger x512 = +- new BigInteger("3406c2d71b04b5fc0db62afcad58a6607d3de688", 16); +- +- static BigInteger y512 = +- new BigInteger("2d335d76b8ec9d610aa8f2cbb4b149fd96fdd" + +- "3a9a6e62bd6c2e01d406be4d1d72718a2fe08bea6d12f5e452474461f70f4" + +- "dea60508e9fe2eaec23d2ec5d1a866", 16); +- +- /* Official NIST 512-bit test keys */ +- +- static String pString = "8df2a494492276aa3d25759bb06869cbeac0d83afb8d0" + +- "cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec" + +- "0736ee31c80291"; +- +- static BigInteger testP = new BigInteger(pString, 16); +- +- static String gString = "626d027839ea0a13413163a55b4cb500299d5522956ce" + +- "fcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc5" + +- "72af53e6d78802"; +- +- static BigInteger testG = new BigInteger(gString, 16); +- +- static BigInteger testQ = new BigInteger("c773218c737ec8ee993b4f2ded30" + +- "f48edace915f", 16); +- +- static BigInteger testX = new BigInteger("2070b3223dba372fde1c0ffc7b2e" + +- "3b498b260614", 16); +- +- static String yString = "19131871d75b1612a819f29d78d1b0d7346f7aa77" + +- "bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06" + +- "699630a76b030ee333"; +- +- static BigInteger testY = new BigInteger(yString, 16); +- +- /* End test vector values */ +- +- private static void debug(String s) { +- if (debug) { +- System.err.println(s); +- } +- } +- +-} +diff --git a/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java b/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java +deleted file mode 100644 +index c4942dea..00000000 +--- a/org/mozilla/jss/netscape/security/provider/DSAKeyPairGenerator.java ++++ /dev/null +@@ -1,389 +0,0 @@ +-// --- BEGIN COPYRIGHT BLOCK --- +-// This program is free software; you can redistribute it and/or modify +-// it under the terms of the GNU General Public License as published by +-// the Free Software Foundation; version 2 of the License. +-// +-// This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of +-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-// GNU General Public License for more details. +-// +-// You should have received a copy of the GNU General Public License along +-// with this program; if not, write to the Free Software Foundation, Inc., +-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-// +-// (C) 2007 Red Hat, Inc. +-// All rights reserved. +-// --- END COPYRIGHT BLOCK --- +-package org.mozilla.jss.netscape.security.provider; +- +-import java.math.BigInteger; +-import java.security.AlgorithmParameterGenerator; +-import java.security.InvalidAlgorithmParameterException; +-import java.security.InvalidKeyException; +-import java.security.InvalidParameterException; +-import java.security.KeyPair; +-import java.security.KeyPairGenerator; +-import java.security.NoSuchAlgorithmException; +-import java.security.NoSuchProviderException; +-import java.security.ProviderException; +-import java.security.SecureRandom; +-import java.security.interfaces.DSAParams; +-import java.security.spec.AlgorithmParameterSpec; +-import java.security.spec.DSAParameterSpec; +-import java.security.spec.InvalidParameterSpecException; +-import java.util.Hashtable; +- +-import org.mozilla.jss.netscape.security.x509.AlgIdDSA; +- +-/** +- * This class generates DSA key parameters and public/private key +- * pairs according to the DSS standard NIST FIPS 186. It uses the +- * updated version of SHA, SHA-1 as described in FIPS 180-1. +- * +- * @author Benjamin Renaud +- * +- * @version 1.23, 97/12/10 +- */ +- +-public class DSAKeyPairGenerator extends KeyPairGenerator +- implements java.security.interfaces.DSAKeyPairGenerator { +- +- private static Hashtable precomputedParams; +- +- static { +- +- /* We support precomputed parameter for 512, 768 and 1024 bit +- moduli. In this file we provide both the seed and counter +- value of the generation process for each of these seeds, +- for validation purposes. We also include the test vectors +- from the DSA specification, FIPS 186, and the FIPS 186 +- Change No 1, which updates the test vector using SHA-1 +- instead of SHA (for both the G function and the message +- hash. +- */ +- +- precomputedParams = new Hashtable(); +- +- /* +- * L = 512 +- * SEED = b869c82b35d70e1b1ff91b28e37a62ecdc34409b +- * counter = 123 +- */ +- BigInteger p512 = +- new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecb" + +- "cd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e1" + +- "2ed0899bcd132acd50d99151bdc43ee737592e17", 16); +- +- BigInteger q512 = +- new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16); +- +- BigInteger g512 = +- new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a43" + +- "4d6486931d2d14271b9e35030b71fd73da179069b32e" + +- "2935630e1c2062354d0da20a6c416e50be794ca4", 16); +- +- /* +- * L = 768 +- * SEED = 77d0f8c4dad15eb8c4f2f8d6726cefd96d5bb399 +- * counter = 263 +- */ +- BigInteger p768 = +- new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e" + +- "927b3a9670fbec5d890141922d2c3b3ad24800937" + +- "99869d1e846aab49fab0ad26d2ce6a22219d470bc" + +- "e7d777d4a21fbe9c270b57f607002f3cef8393694" + +- "cf45ee3688c11a8c56ab127a3daf", 16); +- +- BigInteger q768 = +- new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", +- 16); +- +- BigInteger g768 = +- new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5fac" + +- "baecbe95f190aa7a31d23c4dbbcbe06174544401a" + +- "5b2c020965d8c2bd2171d3668445771f74ba084d2" + +- "029d83c1c158547f3a9f1a2715be23d51ae4d3e5a" + +- "1f6a7064f316933a346d3f529252", 16); +- +- /* +- * L = 1024 +- * SEED = 8d5155894229d5e689ee01e6018a237e2cae64cd +- * counter = 92 +- */ +- BigInteger p1024 = +- new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523c" + +- "ef4400c31e3f80b6512669455d402251fb593d8d58" + +- "fabfc5f5ba30f6cb9b556cd7813b801d346ff26660" + +- "b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c6" + +- "1bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554" + +- "135a169132f675f3ae2b61d72aeff22203199dd148" + +- "01c7", 16); +- +- BigInteger q1024 = +- new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", +- 16); +- +- BigInteger g1024 = +- new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa" + +- "3aea82f9574c0b3d0782675159578ebad4594fe671" + +- "07108180b449167123e84c281613b7cf09328cc8a6" + +- "e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f" + +- "0bfa213562f1fb627a01243bcca4f1bea8519089a8" + +- "83dfe15ae59f06928b665e807b552564014c3bfecf" + +- "492a", 16); +- +- try { +- AlgIdDSA alg512 = new AlgIdDSA(p512, q512, g512); +- AlgIdDSA alg768 = new AlgIdDSA(p768, q768, g768); +- AlgIdDSA alg1024 = new AlgIdDSA(p1024, q1024, g1024); +- +- precomputedParams.put(Integer.valueOf(512), alg512); +- precomputedParams.put(Integer.valueOf(768), alg768); +- precomputedParams.put(Integer.valueOf(1024), alg1024); +- +- } catch (Exception e) { +- throw new InternalError("initializing precomputed " + +- "algorithm parameters for Sun DSA"); +- } +- } +- +- /* The modulus length */ +- private int modlen = 1024; +- +- /* Generate new parameters, even if we have precomputed ones. */ +- boolean generateNewParameters = false; +- +- /* preset algorithm parameters. */ +- private BigInteger presetP, presetQ, presetG; +- +- /* The source of random bits to use */ +- SecureRandom random; +- +- public DSAKeyPairGenerator() { +- super("DSA"); +- } +- +- public void initialize(int strength, SecureRandom random) { +- if ((strength < 512) || (strength > 1024) || (strength % 64 != 0)) { +- throw new InvalidParameterException("Modulus size must range from 512 to 1024 " +- + "and be a multiple of 64"); +- } +- +- /* Set the random */ +- this.random = random; +- if (this.random == null) { +- this.random = new SecureRandom(); +- } +- +- this.modlen = strength; +- DSAParams params = null; +- +- /* Find the precomputed parameters, if any */ +- if (!generateNewParameters) { +- Integer mod = Integer.valueOf(this.modlen); +- params = precomputedParams.get(mod); +- } +- if (params != null) { +- setParams(params); +- } +- } +- +- /** +- * Initializes the DSA key pair generator. If genParams is false, a set of pre-computed parameters is +- * used. In this case, modelen must be 512, 768, or 1024. +- */ +- public void initialize(int modlen, boolean genParams, SecureRandom random) +- throws InvalidParameterException { +- if (genParams == false && modlen != 512 && modlen != 768 +- && modlen != 1024) { +- throw new InvalidParameterException("No precomputed parameters for requested modulus size " +- + "available"); +- } +- this.generateNewParameters = genParams; +- initialize(modlen, random); +- } +- +- /** +- * Initializes the DSA object using a DSA parameter object. +- * +- * @param params a fully initialized DSA parameter object. +- */ +- public void initialize(DSAParams params, SecureRandom random) +- throws InvalidParameterException { +- initialize(params.getP().bitLength(), random); +- setParams(params); +- } +- +- /** +- * Initializes the DSA object using a parameter object. +- * +- * @param params the parameter set to be used to generate +- * the keys. +- * @param random the source of randomness for this generator. +- * +- * @exception InvalidAlgorithmParameterException if the given parameters +- * are inappropriate for this key pair generator +- */ +- public void initialize(AlgorithmParameterSpec params, SecureRandom random) +- throws InvalidAlgorithmParameterException { +- if (!(params instanceof DSAParameterSpec)) { +- throw new InvalidAlgorithmParameterException("Inappropriate parameter"); +- } +- initialize(((DSAParameterSpec) params).getP().bitLength(), +- random); +- setParams((DSAParameterSpec) params); +- } +- +- /** +- * Generates a pair of keys usable by any JavaSecurity compliant +- * DSA implementation. +- * +- * @param rnd the source of random bits from which the random key +- * generation parameters are drawn. In particular, this includes +- * the XSEED parameter. +- * +- * @exception InvalidParameterException if the modulus is not +- * between 512 and 1024. +- */ +- public KeyPair generateKeyPair() { +- +- // set random if initialize() method has been skipped +- if (this.random == null) { +- this.random = new SecureRandom(); +- } +- +- if (presetP == null || presetQ == null || presetG == null || +- generateNewParameters) { +- +- AlgorithmParameterGenerator dsaParamGen; +- +- try { +- dsaParamGen = AlgorithmParameterGenerator.getInstance("DSA", +- "SUN"); +- } catch (NoSuchAlgorithmException e) { +- // this should never happen, because we provide it +- throw new RuntimeException(e.getMessage()); +- } catch (NoSuchProviderException e) { +- // this should never happen, because we provide it +- throw new RuntimeException(e.getMessage()); +- } +- +- dsaParamGen.init(modlen, random); +- +- DSAParameterSpec dsaParamSpec; +- try { +- dsaParamSpec = dsaParamGen.generateParameters().getParameterSpec +- (DSAParameterSpec.class); +- } catch (InvalidParameterSpecException e) { +- // this should never happen +- throw new RuntimeException(e.getMessage()); +- } +- presetP = dsaParamSpec.getP(); +- presetQ = dsaParamSpec.getQ(); +- presetG = dsaParamSpec.getG(); +- } +- +- return generateKeyPair(presetP, presetQ, presetG, random); +- } +- +- public KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g, +- SecureRandom random) { +- +- BigInteger x = generateX(random, q); +- BigInteger y = generateY(x, p, g); +- +- try { +- DSAPublicKey pub = new DSAPublicKey(y, p, q, g); +- DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g); +- +- KeyPair pair = new KeyPair(pub, priv); +- return pair; +- +- } catch (InvalidKeyException e) { +- throw new ProviderException(e.getMessage()); +- } +- } +- +- /** +- * Generate the private key component of the key pair using the +- * provided source of random bits. This method uses the random but +- * source passed to generate a seed and then calls the seed-based +- * generateX method. +- */ +- private BigInteger generateX(SecureRandom random, BigInteger q) { +- BigInteger x = null; +- while (true) { +- int[] seed = new int[5]; +- for (int i = 0; i < 5; i++) { +- seed[i] = random.nextInt(); +- } +- x = generateX(seed, q); +- if (x.signum() > 0 && (x.compareTo(q) < 0)) { +- break; +- } +- } +- return x; +- } +- +- /** +- * Given a seed, generate the private key component of the key +- * pair. In the terminology used in the DSA specification +- * (FIPS-186) seed is the XSEED quantity. +- * +- * @param seed the seed to use to generate the private key. +- */ +- BigInteger generateX(int[] seed, BigInteger q) { +- +- /* Test vector +- int[] tseed = { 0xbd029bbe, 0x7f51960b, 0xcf9edb2b, +- 0x61f06f0f, 0xeb5a38b6 }; +- seed = tseed; +- */ +- // check out t in the spec. +- int[] t = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, +- 0x10325476, 0xC3D2E1F0 }; +- // +- +- int[] tmp = DSA.SHA_7(seed, t); +- byte[] tmpBytes = new byte[tmp.length * 4]; +- for (int i = 0; i < tmp.length; i++) { +- int k = tmp[i]; +- for (int j = 0; j < 4; j++) { +- tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8))); +- } +- } +- BigInteger x = new BigInteger(1, tmpBytes).mod(q); +- return x; +- } +- +- /** +- * Generate the public key component y of the key pair. +- * +- * @param x the private key component. +- * +- * @param p the base parameter. +- */ +- BigInteger generateY(BigInteger x, BigInteger p, BigInteger g) { +- BigInteger y = g.modPow(x, p); +- return y; +- } +- +- /** +- * Set the parameters. +- */ +- private void setParams(DSAParams params) { +- presetP = params.getP(); +- presetQ = params.getQ(); +- presetG = params.getG(); +- } +- +- /** +- * Set the parameters. +- */ +- private void setParams(DSAParameterSpec params) { +- presetP = params.getP(); +- presetQ = params.getQ(); +- presetG = params.getG(); +- } +-} +diff --git a/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java b/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java +deleted file mode 100644 +index 5cd86c79..00000000 +--- a/org/mozilla/jss/netscape/security/provider/DSAParameterGenerator.java ++++ /dev/null +@@ -1,298 +0,0 @@ +-// --- BEGIN COPYRIGHT BLOCK --- +-// This program is free software; you can redistribute it and/or modify +-// it under the terms of the GNU General Public License as published by +-// the Free Software Foundation; version 2 of the License. +-// +-// This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of +-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-// GNU General Public License for more details. +-// +-// You should have received a copy of the GNU General Public License along +-// with this program; if not, write to the Free Software Foundation, Inc., +-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-// +-// (C) 2007 Red Hat, Inc. +-// All rights reserved. +-// --- END COPYRIGHT BLOCK --- +-package org.mozilla.jss.netscape.security.provider; +- +-import java.math.BigInteger; +-import java.security.AlgorithmParameterGeneratorSpi; +-import java.security.AlgorithmParameters; +-import java.security.InvalidAlgorithmParameterException; +-import java.security.InvalidParameterException; +-import java.security.NoSuchAlgorithmException; +-import java.security.NoSuchProviderException; +-import java.security.SecureRandom; +-import java.security.spec.AlgorithmParameterSpec; +-import java.security.spec.DSAParameterSpec; +-import java.security.spec.InvalidParameterSpecException; +- +-/* +- * This class generates parameters for the DSA algorithm. It uses a default +- * prime modulus size of 1024 bits, which can be overwritten during +- * initialization. +- * +- * @author Jan Luehe +- * +- * @version 1.4, 97/12/10 +- * +- * @see java.security.AlgorithmParameters +- * @see java.security.spec.AlgorithmParameterSpec +- * @see DSAParameters +- * +- * @since JDK1.2 +- */ +- +-public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi { +- +- // the modulus length +- private int modLen = 1024; // default +- +- // the source of randomness +- private SecureRandom random; +- +- // useful constants +- private static final BigInteger ONE = BigInteger.valueOf(1); +- private static final BigInteger TWO = BigInteger.valueOf(2); +- +- // Make a SHA-1 hash function +- private SHA sha; +- +- public DSAParameterGenerator() { +- this.sha = new SHA(); +- } +- +- /** +- * Initializes this parameter generator for a certain strength +- * and source of randomness. +- * +- * @param strength the strength (size of prime) in bits +- * @param random the source of randomness +- */ +- protected void engineInit(int strength, SecureRandom random) { +- /* +- * Bruce Schneier, "Applied Cryptography", 2nd Edition, +- * Description of DSA: +- * [...] The algorithm uses the following parameter: +- * p=a prime number L bits long, when L ranges from 512 to 1024 and is +- * a multiple of 64. [...] +- */ +- if ((strength < 512) || (strength > 1024) || (strength % 64 != 0)) { +- throw new InvalidParameterException("Prime size must range from 512 to 1024 " +- + "and be a multiple of 64"); +- } +- this.modLen = strength; +- this.random = random; +- } +- +- /** +- * Initializes this parameter generator with a set of +- * algorithm-specific parameter generation values. +- * +- * @param params the set of algorithm-specific parameter generation values +- * @param random the source of randomness +- * +- * @exception InvalidAlgorithmParameterException if the given parameter +- * generation values are inappropriate for this parameter generator +- */ +- protected void engineInit(AlgorithmParameterSpec genParamSpec, +- SecureRandom random) +- throws InvalidAlgorithmParameterException { +- throw new InvalidAlgorithmParameterException("Invalid parameter"); +- } +- +- /** +- * Generates the parameters. +- * +- * @return the new AlgorithmParameters object +- */ +- protected AlgorithmParameters engineGenerateParameters() { +- AlgorithmParameters algParams = null; +- try { +- if (this.random == null) { +- this.random = new SecureRandom(); +- } +- +- BigInteger[] pAndQ = generatePandQ(this.random, this.modLen); +- BigInteger paramP = pAndQ[0]; +- BigInteger paramQ = pAndQ[1]; +- BigInteger paramG = generateG(paramP, paramQ); +- +- DSAParameterSpec dsaParamSpec = new DSAParameterSpec(paramP, +- paramQ, +- paramG); +- algParams = AlgorithmParameters.getInstance("DSA", "SUN"); +- algParams.init(dsaParamSpec); +- } catch (InvalidParameterSpecException e) { +- // this should never happen +- throw new RuntimeException(e.getMessage()); +- } catch (NoSuchAlgorithmException e) { +- // this should never happen, because we provide it +- throw new RuntimeException(e.getMessage()); +- } catch (NoSuchProviderException e) { +- // this should never happen, because we provide it +- throw new RuntimeException(e.getMessage()); +- } +- +- return algParams; +- } +- +- /* +- * Generates the prime and subprime parameters for DSA, +- * using the provided source of randomness. +- * This method will generate new seeds until a suitable +- * seed has been found. +- * +- * @param random the source of randomness to generate the +- * seed +- * @param L the size of p, in bits. +- * +- * @return an array of BigInteger, with p at index 0 and +- * q at index 1. +- */ +- BigInteger[] generatePandQ(SecureRandom random, int L) { +- BigInteger[] result = null; +- byte[] seed = new byte[20]; +- +- while (result == null) { +- for (int i = 0; i < 20; i++) { +- seed[i] = (byte) random.nextInt(); +- } +- result = generatePandQ(seed, L); +- } +- return result; +- } +- +- /* +- * Generates the prime and subprime parameters for DSA. +- * +- *

The seed parameter corresponds to the SEED parameter +- * referenced in the FIPS specification of the DSA algorithm, +- * and L is the size of p, in bits. +- * +- * @param seed the seed to generate the parameters +- * @param L the size of p, in bits. +- * +- * @return an array of BigInteger, with p at index 0, +- * q at index 1, the seed at index 2, and the counter value +- * at index 3, or null if the seed does not yield suitable numbers. +- */ +- BigInteger[] generatePandQ(byte[] seed, int L) { +- +- /* Useful variables */ +- int g = seed.length * 8; +- int n = (L - 1) / 160; +- int b = (L - 1) % 160; +- +- BigInteger SEED = new BigInteger(1, seed); +- BigInteger TWOG = TWO.pow(2 * g); +- +- /* Step 2 (Step 1 is getting seed). */ +- byte[] U1 = SHA(seed); +- byte[] U2 = SHA(toByteArray((SEED.add(ONE)).mod(TWOG))); +- +- xor(U1, U2); +- byte[] U = U1; +- +- /* Step 3: For q by setting the msb and lsb to 1 */ +- U[0] |= 0x80; +- U[19] |= 1; +- BigInteger q = new BigInteger(1, U); +- +- /* Step 5 */ +- if (!q.isProbablePrime(40)) { +- return null; +- +- } else { +- BigInteger V[] = new BigInteger[n + 1]; +- BigInteger offset = TWO; +- +- /* Step 6 */ +- for (int counter = 0; counter < 4096; counter++) { +- +- /* Step 7 */ +- for (int k = 0; k <= n; k++) { +- BigInteger K = BigInteger.valueOf(k); +- BigInteger tmp = (SEED.add(offset).add(K)).mod(TWOG); +- V[k] = new BigInteger(1, SHA(toByteArray(tmp))); +- } +- +- /* Step 8 */ +- BigInteger W = V[0]; +- for (int i = 1; i < n; i++) { +- W = W.add(V[i].multiply(TWO.pow(i * 160))); +- } +- W = W.add((V[n].mod(TWO.pow(b))).multiply(TWO.pow(n * 160))); +- +- BigInteger TWOLm1 = TWO.pow(L - 1); +- BigInteger X = W.add(TWOLm1); +- +- /* Step 9 */ +- BigInteger c = X.mod(q.multiply(TWO)); +- BigInteger p = X.subtract(c.subtract(ONE)); +- +- /* Step 10 - 13 */ +- if (p.compareTo(TWOLm1) > -1 && p.isProbablePrime(15)) { +- BigInteger[] result = { p, q, SEED, +- BigInteger.valueOf(counter) }; +- return result; +- } +- offset = offset.add(BigInteger.valueOf(n)).add(ONE); +- } +- return null; +- } +- } +- +- /* +- * Generates the g parameter for DSA. +- * +- * @param p the prime, p. +- * @param q the subprime, q. +- * +- * @param the g +- */ +- BigInteger generateG(BigInteger p, BigInteger q) { +- BigInteger h = ONE; +- BigInteger pMinusOneOverQ = (p.subtract(ONE)).divide(q); +- BigInteger g = ONE; +- while (g.compareTo(TWO) < 0) { +- g = h.modPow(pMinusOneOverQ, p); +- h = h.add(ONE); +- } +- return g; +- } +- +- /* +- * Returns the SHA-1 digest of some data +- */ +- private byte[] SHA(byte[] array) { +- sha.engineReset(); +- sha.engineUpdate(array, 0, array.length); +- return sha.engineDigest(); +- } +- +- /* +- * Converts the result of a BigInteger.toByteArray call to an exact +- * signed magnitude representation for any positive number. +- */ +- private byte[] toByteArray(BigInteger bigInt) { +- byte[] result = bigInt.toByteArray(); +- if (result[0] == 0) { +- byte[] tmp = new byte[result.length - 1]; +- System.arraycopy(result, 1, tmp, 0, tmp.length); +- result = tmp; +- } +- return result; +- } +- +- /* +- * XORs U2 into U1 +- */ +- private void xor(byte[] U1, byte[] U2) { +- for (int i = 0; i < U1.length; i++) { +- U1[i] ^= U2[i]; +- } +- } +-} +diff --git a/org/mozilla/jss/netscape/security/provider/MD5.java b/org/mozilla/jss/netscape/security/provider/MD5.java +deleted file mode 100644 +index d46da4fc..00000000 +--- a/org/mozilla/jss/netscape/security/provider/MD5.java ++++ /dev/null +@@ -1,378 +0,0 @@ +-// --- BEGIN COPYRIGHT BLOCK --- +-// This program is free software; you can redistribute it and/or modify +-// it under the terms of the GNU General Public License as published by +-// the Free Software Foundation; version 2 of the License. +-// +-// This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of +-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-// GNU General Public License for more details. +-// +-// You should have received a copy of the GNU General Public License along +-// with this program; if not, write to the Free Software Foundation, Inc., +-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-// +-// (C) 2007 Red Hat, Inc. +-// All rights reserved. +-// --- END COPYRIGHT BLOCK --- +-package org.mozilla.jss.netscape.security.provider; +- +-import java.security.DigestException; +-import java.security.MessageDigestSpi; +- +-/** +- * The MD5 class is used to compute an MD5 message digest over a given +- * buffer of bytes. It is an implementation of the RSA Data Security Inc +- * MD5 algorithim as described in internet RFC 1321. +- * +- * @version 1.24 97/12/10 +- * @author Chuck McManis +- * @author Benjamin Renaud +- */ +- +-public final class MD5 extends MessageDigestSpi implements Cloneable { +- +- /** contains the computed message digest */ +- private byte[] digestBits; +- +- private int state[]; +- private long count; // bit count AND buffer[] index aid +- private byte buffer[]; +- private int transformBuffer[]; +- +- private static final int S11 = 7; +- private static final int S12 = 12; +- private static final int S13 = 17; +- private static final int S14 = 22; +- private static final int S21 = 5; +- private static final int S22 = 9; +- private static final int S23 = 14; +- private static final int S24 = 20; +- private static final int S31 = 4; +- private static final int S32 = 11; +- private static final int S33 = 16; +- private static final int S34 = 23; +- private static final int S41 = 6; +- private static final int S42 = 10; +- private static final int S43 = 15; +- private static final int S44 = 21; +- +- private static final int MD5_LENGTH = 16; +- +- /** +- * Standard constructor, creates a new MD5 instance, allocates its +- * buffers from the heap. +- */ +- public MD5() { +- init(); +- } +- +- /* ********************************************************** +- * The MD5 Functions. These are copied verbatim from +- * the RFC to insure accuracy. The results of this +- * implementation were checked against the RSADSI version. +- * ********************************************************** +- */ +- +- private int F(int x, int y, int z) { +- return ((x & y) | ((~x) & z)); +- } +- +- private int G(int x, int y, int z) { +- return ((x & z) | (y & (~z))); +- } +- +- private int H(int x, int y, int z) { +- return ((x ^ y) ^ z); +- } +- +- private int I(int x, int y, int z) { +- return (y ^ (x | (~z))); +- } +- +- private int rotateLeft(int a, int n) { +- return ((a << n) | (a >>> (32 - n))); +- } +- +- private int FF(int a, int b, int c, int d, int x, int s, int ac) { +- a += F(b, c, d) + x + ac; +- a = rotateLeft(a, s); +- a += b; +- return a; +- } +- +- private int GG(int a, int b, int c, int d, int x, int s, int ac) { +- a += G(b, c, d) + x + ac; +- a = rotateLeft(a, s); +- a += b; +- return a; +- } +- +- private int HH(int a, int b, int c, int d, int x, int s, int ac) { +- a += H(b, c, d) + x + ac; +- a = rotateLeft(a, s); +- a += b; +- return a; +- } +- +- private int II(int a, int b, int c, int d, int x, int s, int ac) { +- a += I(b, c, d) + x + ac; +- a = rotateLeft(a, s); +- a += b; +- return a; +- } +- +- /** +- * This is where the functions come together as the generic MD5 +- * transformation operation, it is called by update() which is +- * synchronized (to protect transformBuffer). It consumes sixteen +- * bytes from the buffer, beginning at the specified offset. +- */ +- void transform(byte buf[], int offset) { +- int a, b, c, d; +- int x[] = transformBuffer; +- +- a = state[0]; +- b = state[1]; +- c = state[2]; +- d = state[3]; +- +- for (int i = 0; i < 16; i++) { +- x[i] = buf[i * 4 + offset] & 0xff; +- for (int j = 1; j < 4; j++) { +- x[i] += (buf[i * 4 + j + offset] & 0xff) << (j * 8); +- } +- } +- +- /* Round 1 */ +- a = FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ +- d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ +- c = FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ +- b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ +- a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ +- d = FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ +- c = FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ +- b = FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ +- a = FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ +- d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ +- c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ +- b = FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ +- a = FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ +- d = FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ +- c = FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ +- b = FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ +- +- /* Round 2 */ +- a = GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ +- d = GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ +- c = GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ +- b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ +- a = GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ +- d = GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ +- c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ +- b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ +- a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ +- d = GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ +- c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ +- b = GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ +- a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ +- d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ +- c = GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ +- b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ +- +- /* Round 3 */ +- a = HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ +- d = HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ +- c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ +- b = HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ +- a = HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ +- d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ +- c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ +- b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ +- a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ +- d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ +- c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ +- b = HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ +- a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ +- d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ +- c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ +- b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ +- +- /* Round 4 */ +- a = II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ +- d = II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ +- c = II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ +- b = II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ +- a = II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ +- d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ +- c = II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ +- b = II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ +- a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ +- d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ +- c = II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ +- b = II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ +- a = II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ +- d = II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ +- c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ +- b = II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ +- +- state[0] += a; +- state[1] += b; +- state[2] += c; +- state[3] += d; +- } +- +- /** +- * Initialize the MD5 state information and reset the bit count +- * to 0. Given this implementation you are constrained to counting +- * 2^64 bits. +- */ +- public void init() { +- state = new int[4]; +- transformBuffer = new int[16]; +- synchronized (this) { +- buffer = new byte[64]; +- } +- digestBits = new byte[16]; +- count = 0; +- // Load magic initialization constants. +- state[0] = 0x67452301; +- state[1] = 0xefcdab89; +- state[2] = 0x98badcfe; +- state[3] = 0x10325476; +- for (int i = 0; i < digestBits.length; i++) +- digestBits[i] = 0; +- } +- +- protected void engineReset() { +- init(); +- } +- +- /** +- * Return the digest length in bytes +- */ +- protected int engineGetDigestLength() { +- return (MD5_LENGTH); +- } +- +- /** +- * Update adds the passed byte to the digested data. +- */ +- protected synchronized void engineUpdate(byte b) { +- int index; +- +- index = (int) ((count >>> 3) & 0x3f); +- count += 8; +- buffer[index] = b; +- if (index >= 63) { +- transform(buffer, 0); +- } +- } +- +- /** +- * Update adds the selected part of an array of bytes to the digest. +- * This version is more efficient than the byte-at-a-time version; +- * it avoids data copies and reduces per-byte call overhead. +- */ +- protected synchronized void engineUpdate(byte input[], int offset, +- int len) { +- int i; +- +- for (i = offset; len > 0;) { +- int index = (int) ((count >>> 3) & 0x3f); +- +- if (index == 0 && len > 64) { +- count += (64 * 8); +- transform(input, i); +- len -= 64; +- i += 64; +- } else { +- count += 8; +- buffer[index] = input[i]; +- if (index >= 63) +- transform(buffer, 0); +- i++; +- len--; +- } +- } +- } +- +- /** +- * Perform the final computations, any buffered bytes are added +- * to the digest, the count is added to the digest, and the resulting +- * digest is stored. After calling final you will need to call +- * init() again to do another digest. +- */ +- private void finish() { +- byte bits[] = new byte[8]; +- byte padding[]; +- int i, index, padLen; +- +- for (i = 0; i < 8; i++) { +- bits[i] = (byte) ((count >>> (i * 8)) & 0xff); +- } +- +- index = (int) (count >> 3) & 0x3f; +- padLen = (index < 56) ? (56 - index) : (120 - index); +- padding = new byte[padLen]; +- padding[0] = (byte) 0x80; +- engineUpdate(padding, 0, padding.length); +- engineUpdate(bits, 0, bits.length); +- +- for (i = 0; i < 4; i++) { +- for (int j = 0; j < 4; j++) { +- digestBits[i * 4 + j] = (byte) ((state[i] >>> (j * 8)) & 0xff); +- } +- } +- } +- +- /** +- */ +- protected byte[] engineDigest() { +- finish(); +- +- byte[] result = new byte[MD5_LENGTH]; +- System.arraycopy(digestBits, 0, result, 0, MD5_LENGTH); +- +- init(); +- +- return result; +- } +- +- /** +- */ +- protected int engineDigest(byte[] buf, int offset, int len) +- throws DigestException { +- finish(); +- +- if (len < MD5_LENGTH) +- throw new DigestException("partial digests not returned"); +- if (buf.length - offset < MD5_LENGTH) +- throw new DigestException("insufficient space in the output " + +- "buffer to store the digest"); +- +- System.arraycopy(digestBits, 0, buf, offset, MD5_LENGTH); +- +- init(); +- +- return MD5_LENGTH; +- } +- +- /* +- * Clones this object. +- */ +- public Object clone() { +- MD5 that = null; +- try { +- that = (MD5) super.clone(); +- that.state = this.state.clone(); +- that.transformBuffer = this.transformBuffer.clone(); +- that.buffer = this.buffer.clone(); +- that.digestBits = this.digestBits.clone(); +- that.count = this.count; +- return that; +- } catch (CloneNotSupportedException e) { +- } +- return that; +- } +-} +diff --git a/org/mozilla/jss/netscape/security/provider/SHA.java b/org/mozilla/jss/netscape/security/provider/SHA.java +deleted file mode 100644 +index a911e386..00000000 +--- a/org/mozilla/jss/netscape/security/provider/SHA.java ++++ /dev/null +@@ -1,349 +0,0 @@ +-// --- BEGIN COPYRIGHT BLOCK --- +-// This program is free software; you can redistribute it and/or modify +-// it under the terms of the GNU General Public License as published by +-// the Free Software Foundation; version 2 of the License. +-// +-// This program is distributed in the hope that it will be useful, +-// but WITHOUT ANY WARRANTY; without even the implied warranty of +-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-// GNU General Public License for more details. +-// +-// You should have received a copy of the GNU General Public License along +-// with this program; if not, write to the Free Software Foundation, Inc., +-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-// +-// (C) 2007 Red Hat, Inc. +-// All rights reserved. +-// --- END COPYRIGHT BLOCK --- +-package org.mozilla.jss.netscape.security.provider; +- +-import java.security.DigestException; +-import java.security.MessageDigestSpi; +- +-/** +- * This class implements the Secure Hash Algorithm (SHA) developed by +- * the National Institute of Standards and Technology along with the +- * National Security Agency. This is the updated version of SHA +- * fip-180 as superseded by fip-180-1. +- * +- *

+- * It implement JavaSecurity MessageDigest, and can be used by in the Java Security framework, as a pluggable +- * implementation, as a filter for the digest stream classes. +- * +- * @version 1.30 97/12/10 +- * @author Roger Riggs +- * @author Benjamin Renaud +- */ +- +-public class SHA extends MessageDigestSpi implements Cloneable { +- +- /* This private hookm controlled by the appropriate constructor, +- causes this class to implement the first version of SHA, +- as defined in FIPS 180, as opposed to FIPS 180-1. This was +- useful for DSA testing. */ +- private int version = 1; +- +- private static final int SHA_LENGTH = 20; +- +- // Buffer of int's and count of characters accumulated +- // 64 bytes are included in each hash block so the low order +- // bits of count are used to know how to pack the bytes into ints +- // and to know when to compute the block and start the next one. +- private int W[] = new int[80]; +- private long count = 0; +- private final int countmax = 64; +- private final int countmask = (countmax - 1); +- +- private int AA, BB, CC, DD, EE; +- +- SHA(int version) { +- this(); +- this.version = version; +- } +- +- /** +- * Creates a new SHA object. +- */ +- public SHA() { +- init(); +- } +- +- /** +- * Return the length of the digest in bytes +- */ +- protected int engineGetDigestLength() { +- return (SHA_LENGTH); +- } +- +- public void engineUpdate(byte b) { +- engineUpdate((int) b); +- } +- +- /** +- * Update a byte. +- * +- * @param b the byte +- */ +- private void engineUpdate(int b) { +- int word; +- int offset; +- +- /* compute word offset and bit offset within word the low bits +- of count are inverted to make put the bytes in the write +- order */ +- word = ((int) count & countmask) >>> 2; +- offset = (~(int) count & 3) << 3; +- +- W[word] = (W[word] & ~(0xff << offset)) | ((b & 0xff) << offset); +- +- /* If this is the last byte of a block, compute the partial hash */ +- if (((int) count & countmask) == countmask) { +- computeBlock(); +- } +- count++; +- } +- +- /** +- * Update a buffer. +- * +- * @param b the data to be updated. +- * @param off the start offset in the data +- * @param len the number of bytes to be updated. +- */ +- public void engineUpdate(byte b[], int off, int len) { +- int word; +- +- if ((off < 0) || (len < 0) || (off + len > b.length)) +- throw new ArrayIndexOutOfBoundsException(); +- +- // Use single writes until integer aligned +- while ((len > 0) && +- ((int) count & 3) != 0) { +- engineUpdate(b[off]); +- off++; +- len--; +- } +- +- /* Assemble groups of 4 bytes to be inserted in integer array */ +- for (; len >= 4; len -= 4, off += 4) { +- +- word = ((int) count & countmask) >> 2; +- +- W[word] = ((b[off] & 0xff) << 24) | +- ((b[off + 1] & 0xff) << 16) | +- ((b[off + 2] & 0xff) << 8) | +- ((b[off + 3] & 0xff)); +- +- count += 4; +- if (((int) count & countmask) == 0) { +- computeBlock(); +- } +- } +- +- /* Use single writes for last few bytes */ +- for (; len > 0; len--, off++) { +- engineUpdate(b[off]); +- } +- } +- +- /** +- * Resets the buffers and hash value to start a new hash. +- */ +- public void init() { +- AA = 0x67452301; +- BB = 0xefcdab89; +- CC = 0x98badcfe; +- DD = 0x10325476; +- EE = 0xc3d2e1f0; +- +- for (int i = 0; i < 80; i++) +- W[i] = 0; +- count = 0; +- } +- +- /** +- * Resets the buffers and hash value to start a new hash. +- */ +- public void engineReset() { +- init(); +- } +- +- /** +- * Computes the final hash and returns the final value as a +- * byte[20] array. The object is reset to be ready for further +- * use, as specified in the JavaSecurity MessageDigest +- * specification. +- */ +- public byte[] engineDigest() { +- byte hashvalue[] = new byte[SHA_LENGTH]; +- +- try { +- engineDigest(hashvalue, 0, hashvalue.length); +- } catch (DigestException e) { +- throw new InternalError(""); +- } +- return hashvalue; +- } +- +- /** +- * Computes the final hash and returns the final value as a +- * byte[20] array. The object is reset to be ready for further +- * use, as specified in the JavaSecurity MessageDigest +- * specification. +- */ +- public int engineDigest(byte[] hashvalue, int offset, int len) +- throws DigestException { +- +- if (len < SHA_LENGTH) +- throw new DigestException("partial digests not returned"); +- if (hashvalue.length - offset < SHA_LENGTH) +- throw new DigestException("insufficient space in the output " + +- "buffer to store the digest"); +- +- /* The number of bits before padding occurs */ +- long bits = count << 3; +- +- engineUpdate(0x80); +- +- /* Pad with zeros until length is a multiple of 448 (the last two +- 32 ints are used a holder for bits (see above). */ +- while ((int) (count & countmask) != 56) { +- engineUpdate(0); +- } +- +- W[14] = (int) (bits >>> 32); +- W[15] = (int) (bits & 0xffffffff); +- +- count += 8; +- computeBlock(); +- +- // Copy out the result +- hashvalue[offset + 0] = (byte) (AA >>> 24); +- hashvalue[offset + 1] = (byte) (AA >>> 16); +- hashvalue[offset + 2] = (byte) (AA >>> 8); +- hashvalue[offset + 3] = (byte) (AA >>> 0); +- +- hashvalue[offset + 4] = (byte) (BB >>> 24); +- hashvalue[offset + 5] = (byte) (BB >>> 16); +- hashvalue[offset + 6] = (byte) (BB >>> 8); +- hashvalue[offset + 7] = (byte) (BB >>> 0); +- +- hashvalue[offset + 8] = (byte) (CC >>> 24); +- hashvalue[offset + 9] = (byte) (CC >>> 16); +- hashvalue[offset + 10] = (byte) (CC >>> 8); +- hashvalue[offset + 11] = (byte) (CC >>> 0); +- +- hashvalue[offset + 12] = (byte) (DD >>> 24); +- hashvalue[offset + 13] = (byte) (DD >>> 16); +- hashvalue[offset + 14] = (byte) (DD >>> 8); +- hashvalue[offset + 15] = (byte) (DD >>> 0); +- +- hashvalue[offset + 16] = (byte) (EE >>> 24); +- hashvalue[offset + 17] = (byte) (EE >>> 16); +- hashvalue[offset + 18] = (byte) (EE >>> 8); +- hashvalue[offset + 19] = (byte) (EE >>> 0); +- +- engineReset(); // remove the evidence +- +- return SHA_LENGTH; +- } +- +- // Constants for each round +- private final int round1_kt = 0x5a827999; +- private final int round2_kt = 0x6ed9eba1; +- private final int round3_kt = 0x8f1bbcdc; +- private final int round4_kt = 0xca62c1d6; +- +- /** +- * Compute a the hash for the current block. +- * +- * This is in the same vein as Peter Gutmann's algorithm listed in +- * the back of Applied Cryptography, Compact implementation of +- * "old" NIST Secure Hash Algorithm. +- * +- */ +- private void computeBlock() { +- int temp, a, b, c, d, e; +- +- // The first 16 ints have the byte stream, compute the rest of +- // the buffer +- for (int t = 16; t <= 79; t++) { +- if (version == 0) { +- W[t] = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; +- } else { +- temp = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; +- W[t] = ((temp << 1) | (temp >>> (32 - 1))); +- } +- } +- +- a = AA; +- b = BB; +- c = CC; +- d = DD; +- e = EE; +- +- // Round 1 +- for (int i = 0; i < 20; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- ((b & c) | ((~b) & d)) + e + W[i] + round1_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 2 +- for (int i = 20; i < 40; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- (b ^ c ^ d) + e + W[i] + round2_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 3 +- for (int i = 40; i < 60; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- ((b & c) | (b & d) | (c & d)) + e + W[i] + round3_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- +- // Round 4 +- for (int i = 60; i < 80; i++) { +- temp = ((a << 5) | (a >>> (32 - 5))) + +- (b ^ c ^ d) + e + W[i] + round4_kt; +- e = d; +- d = c; +- c = ((b << 30) | (b >>> (32 - 30))); +- b = a; +- a = temp; +- } +- AA += a; +- BB += b; +- CC += c; +- DD += d; +- EE += e; +- } +- +- /* +- * Clones this object. +- */ +- public Object clone() { +- SHA that = null; +- try { +- that = (SHA) super.clone(); +- that.W = new int[80]; +- System.arraycopy(this.W, 0, that.W, 0, W.length); +- return that; +- } catch (CloneNotSupportedException e) { +- } +- return that; +- } +-} +diff --git a/org/mozilla/jss/netscape/security/provider/Sun.java b/org/mozilla/jss/netscape/security/provider/Sun.java +index 94e72ef4..dd12d26d 100644 +--- a/org/mozilla/jss/netscape/security/provider/Sun.java ++++ b/org/mozilla/jss/netscape/security/provider/Sun.java +@@ -68,54 +68,11 @@ public final class Sun extends Provider { + + // AccessController.beginPrivileged(); + +- /* +- * Signature engines +- */ +- put("Signature.DSA", "org.mozilla.jss.netscape.security.provider.DSA"); +- +- put("Alg.Alias.Signature.SHA/DSA", "DSA"); +- put("Alg.Alias.Signature.SHA1/DSA", "DSA"); +- put("Alg.Alias.Signature.SHA-1/DSA", "DSA"); +- put("Alg.Alias.Signature.DSS", "DSA"); +- put("Alg.Alias.Signature.OID.1.3.14.3.2.13", "DSA"); +- put("Alg.Alias.Signature.OID.1.3.14.3.2.27", "DSA"); +- put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "DSA"); +- // the following are not according to our formal spec but +- // are still supported +- put("Alg.Alias.Signature.1.3.14.3.2.13", "DSA"); +- put("Alg.Alias.Signature.1.3.14.3.2.27", "DSA"); +- put("Alg.Alias.Signature.1.2.840.10040.4.3", "DSA"); +- put("Alg.Alias.Signature.SHAwithDSA", "DSA"); +- put("Alg.Alias.Signature.SHA1withDSA", "DSA"); +- +- /* +- * Key Pair Generator engines +- */ +- put("KeyPairGenerator.DSA", +- "org.mozilla.jss.netscape.security.provider.DSAKeyPairGenerator"); +- +- put("Alg.Alias.KeyPairGenerator.OID.1.3.14.3.2.12", "DSA"); +- put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA"); + // the following are not according to our formal spec but + // are still supported + put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA"); + put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA"); + +- /* +- * Digest engines +- */ +- put("MessageDigest.MD5", "org.mozilla.jss.netscape.security.provider.MD5"); +- put("MessageDigest.SHA-1", "org.mozilla.jss.netscape.security.provider.SHA"); +- +- put("Alg.Alias.MessageDigest.SHA", "SHA-1"); +- put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); +- +- /* +- * Algorithm Parameter Generator engines +- */ +- put("AlgorithmParameterGenerator.DSA", +- "org.mozilla.jss.netscape.security.provider.DSAParameterGenerator"); +- + /* + * Algorithm Parameter engines + */ +-- +2.21.0 + diff --git a/SOURCES/0004-JSS-CVE-2019-14823-fix.patch b/SOURCES/0004-JSS-CVE-2019-14823-fix.patch new file mode 100644 index 0000000..10218a0 --- /dev/null +++ b/SOURCES/0004-JSS-CVE-2019-14823-fix.patch @@ -0,0 +1,346 @@ +From 233795b098a17269f8495fee312fe6df404a236d Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 4 Sep 2019 08:33:14 -0400 +Subject: [PATCH] Fix root certificate validation + +When the Leaf and Chain OCSP checking policy is enabled in +CryptoManager, JSS will switch to alternative certificate verification +logic in JSSL_DefaultCertAuthCallback. In this method, the root +certificate was incorrectly trusted without being verified to exist in +the trust store. + +This patch cleans up the logic in JSSL_verifyCertPKIX and makes it +more explicit in addition to fixing the error. + +Fixes CVE-2019-14823 + +Signed-off-by: Alexander Scheel +--- + org/mozilla/jss/ssl/common.c | 239 ++++++++++++++++++++--------------- + 1 file changed, 136 insertions(+), 103 deletions(-) + +diff --git a/org/mozilla/jss/ssl/common.c b/org/mozilla/jss/ssl/common.c +index 1bbfed45..2db9fda1 100644 +--- a/org/mozilla/jss/ssl/common.c ++++ b/org/mozilla/jss/ssl/common.c +@@ -904,7 +904,6 @@ finish: + } + + /* Get the trusted anchor for pkix */ +- + CERTCertificate *getRoot(CERTCertificate *cert, + SECCertUsage certUsage) + { +@@ -938,79 +937,84 @@ finish: + return root; + } + +-/* Verify a cert using explicit PKIX call. +- * For now only used in OCSP AIA context. +- * The result of this call will be a full chain +- * and leaf network AIA ocsp validation. +- * The policy param will be used in the future to +- * handle more scenarios. +- */ +- +-SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert, +- SECCertificateUsage certificateUsage,secuPWData *pwdata, int ocspPolicy, +- CERTVerifyLog *log, SECCertificateUsage *usage) ++/* Internal helper for the below call. */ ++static SECStatus ++JSSL_verifyCertPKIXInternal(CERTCertificate *cert, ++ SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy, ++ CERTVerifyLog *log, SECCertificateUsage *usage, ++ CERTCertList *trustedCertList) + { +- +- /* put the first set of possible flags internally here first */ +- /* later there could be a more complete list to choose from */ +- /* support our hard core fetch aia ocsp policy for now */ +- +- static PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = { ++ /* Put the first set of possible flags internally here first. Later ++ * there could be a more complete list to choose from; for now we only ++ * support our hard core fetch AIA OCSP policy. Note that we disable ++ * CRL fetching as Dogtag doesn't support it. Additionally, enable OCSP ++ * checking on the chained CA certificates. Since NSS/PKIX's ++ * CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't do what we want, ++ * we construct the policy ourselves. */ ++ PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = { + /* crl */ +- 0, ++ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, + /* ocsp */ + CERT_REV_M_TEST_USING_THIS_METHOD | +- CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO ++ CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO + }; + +- static PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = { ++ PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = { + /* crl */ +- 0, ++ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, + /* ocsp */ + CERT_REV_M_TEST_USING_THIS_METHOD | +- CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO ++ CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO + }; + +- static CERTRevocationMethodIndex +- ocsp_Enabled_Hard_Policy_Method_Preference = { +- cert_revocation_method_ocsp +- }; +- +- static CERTRevocationFlags ocsp_Enabled_Hard_Policy = { +- { /* leafTests */ +- 2, +- ocsp_Enabled_Hard_Policy_LeafFlags, +- 1, +- &ocsp_Enabled_Hard_Policy_Method_Preference, +- 0 }, +- { /* chainTests */ +- 2, +- ocsp_Enabled_Hard_Policy_ChainFlags, +- 1, +- &ocsp_Enabled_Hard_Policy_Method_Preference, +- 0 } ++ CERTRevocationMethodIndex ocsp_Enabled_Hard_Policy_Method_Preference[1] = { ++ cert_revocation_method_ocsp + }; + +- /* for future expansion */ ++ CERTRevocationFlags ocsp_Enabled_Hard_Policy = { ++ /* CERTRevocationTests - leafTests */ ++ { ++ /* number_of_defined_methods */ ++ 2, ++ /* cert_rev_flags_per_method */ ++ ocsp_Enabled_Hard_Policy_LeafFlags, ++ /* number_of_preferred_methods */ ++ 1, ++ /* preferred_methods */ ++ ocsp_Enabled_Hard_Policy_Method_Preference, ++ /* cert_rev_method_independent_flags */ ++ 0 ++ }, ++ /* CERTRevocationTests - chainTests */ ++ { ++ /* number_of_defined_methods */ ++ 2, ++ /* cert_rev_flags_per_method */ ++ ocsp_Enabled_Hard_Policy_ChainFlags, ++ /* number_of_preferred_methods */ ++ 1, ++ /* preferred_methods */ ++ ocsp_Enabled_Hard_Policy_Method_Preference, ++ /* cert_rev_method_independent_flags */ ++ 0 ++ } ++ }; + +- CERTValOutParam cvout[20] = {{0}}; +- CERTValInParam cvin[20] = {{0}}; ++ /* The size of these objects are defined here based upon maximum possible ++ * inputs. A dynamic allocation could reallocate based upon actual usage, ++ * however this would affect the size by at most one or two. Note that, ++ * due to the required usage of cert_pi_end/cert_po_end, these sizes are ++ * inflated by one. */ ++ CERTValOutParam cvout[3] = {{0}}; ++ CERTValInParam cvin[6] = {{0}}; + ++ int usageIndex = -1; + int inParamIndex = 0; + int outParamIndex = 0; +- CERTRevocationFlags *rev = NULL; +- +- CERTCertList *trustedCertList = NULL; +- +- PRBool fetchCerts = PR_FALSE; + +- SECCertUsage certUsage = certUsageSSLClient /* 0 */; +- + SECStatus res = SECFailure; + +- CERTCertificate *root = NULL; +- +- if(cert == NULL) { ++ if (cert == NULL) { + goto finish; + } + +@@ -1018,93 +1022,122 @@ SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert, + goto finish; + } + +- /* Force the strict ocsp network check on chain +- and leaf. +- */ +- +- fetchCerts = PR_TRUE; +- rev = &ocsp_Enabled_Hard_Policy; +- +- /* fetch aia over net */ +- ++ /* Enable live AIA fetching over the network. */ + cvin[inParamIndex].type = cert_pi_useAIACertFetch; +- cvin[inParamIndex].value.scalar.b = fetchCerts; +- inParamIndex++; +- +- /* time */ ++ cvin[inParamIndex].value.scalar.b = PR_TRUE; ++ inParamIndex++; + ++ /* By setting the time to zero, we choose the current time when the ++ * check is performed. */ + cvin[inParamIndex].type = cert_pi_date; +- cvin[inParamIndex].value.scalar.time = PR_Now(); ++ cvin[inParamIndex].value.scalar.time = 0; + inParamIndex++; + +- /* flags */ +- ++ /* Force the strict OCSP check on both the leaf and its chain. */ + cvin[inParamIndex].type = cert_pi_revocationFlags; +- cvin[inParamIndex].value.pointer.revocation = rev; ++ cvin[inParamIndex].value.pointer.revocation = &ocsp_Enabled_Hard_Policy; + inParamIndex++; + +- /* establish trust anchor */ +- +- /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain +- * the root. +- */ +- +- SECCertificateUsage testUsage = certificateUsage; +- while (0 != (testUsage = testUsage >> 1)) { certUsage++; } +- +- root = getRoot(cert,certUsage); +- +- /* Try to add the root as the trust anchor so all the +- other memebers of the ca chain will get validated. +- */ +- +- if( root != NULL ) { +- trustedCertList = CERT_NewCertList(); +- CERT_AddCertToListTail(trustedCertList, root); +- ++ /* Establish a trust anchor if it is passed to us. NOTE: this trust anchor ++ * must previously be validated before it is passed to us here. */ ++ if (trustedCertList != NULL) { + cvin[inParamIndex].type = cert_pi_trustAnchors; + cvin[inParamIndex].value.pointer.chain = trustedCertList; +- + inParamIndex++; + } + ++ /* Done establishing input parameters. */ + cvin[inParamIndex].type = cert_pi_end; + +- if(log != NULL) { ++ /* When we need to log rationale for failure, pass it as an output ++ * parameter. */ ++ if (log != NULL) { + cvout[outParamIndex].type = cert_po_errorLog; + cvout[outParamIndex].value.pointer.log = log; + outParamIndex ++; + } + +- int usageIndex = 0; +- if(usage != NULL) { ++ /* When we need to inquire about the resulting certificate usage, pass it ++ * here. */ ++ if (usage != NULL) { + usageIndex = outParamIndex; + cvout[outParamIndex].type = cert_po_usages; + cvout[outParamIndex].value.scalar.usages = 0; + outParamIndex ++; + } + ++ /* Done establishing output parameters. */ + cvout[outParamIndex].type = cert_po_end; + ++ /* Call into NSS's PKIX library to validate our certificate. */ + res = CERT_PKIXVerifyCert(cert, certificateUsage, cvin, cvout, &pwdata); + + finish: +- /* clean up any trusted cert list */ +- ++ /* Clean up any certificates in the trusted certificate list. This was ++ * a passed input parameter, but by taking ownership of it and clearing it, ++ * we enable tail calls to this function. */ + if (trustedCertList) { ++ /* CERT_DestroyCertList destroys interior certs for us. */ + CERT_DestroyCertList(trustedCertList); + trustedCertList = NULL; + } + +- /* CERT_DestroyCertList destroys interior certs for us. */ +- +- if(root) { +- root = NULL; +- } +- +- if(res == SECSuccess && usage) { ++ if (res == SECSuccess && usage && usageIndex != -1) { + *usage = cvout[usageIndex].value.scalar.usages; + } + + return res; + } ++ ++/* Verify a cert using an explicit PKIX call. For now only perform this call ++ * when the OCSP policy is set to leaf and chain. Performs a blocking, online ++ * OCSP status refresh. The result of this call will be a full-chain OCSP ++ * validation. ++ * ++ * In the future, we'll use ocspPolicy to condition around additional policies ++ * and handle them all with this method (and a call to PKIX). ++ * ++ * Note that this currently requires the certificate to be added directly ++ * to the NSS DB. We can't otherwise validate against root certificates in ++ * the default NSS DB. ++ */ ++SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert, ++ SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy, ++ CERTVerifyLog *log, SECCertificateUsage *usage) ++{ ++ SECCertUsage certUsage = certUsageSSLClient /* 0 */; ++ ++ /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain ++ * the root. ++ */ ++ ++ SECCertificateUsage testUsage = certificateUsage; ++ while (0 != (testUsage = testUsage >> 1)) { certUsage++; } ++ ++ CERTCertificate *root = getRoot(cert, certUsage); ++ ++ // Two cases: either the root is present, or it isn't. ++ if (root == NULL) { ++ /* In this case, we've had a hard time finding the root. In all ++ * likelihood, the following call will fail to validate the end cert ++ * as well and thus fail to validate. I don't believe there's a risk ++ * in trying it however. */ ++ return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata, ++ ocspPolicy, log, usage, NULL); ++ } else { ++ /* In this case, we've found the root certificate. Before passing it ++ * to the leaf, explicitly validate it with strict OCSP checking. Then ++ * validate the leaf certificate with a known and trusted root ++ * certificate. */ ++ SECStatus ret = JSSL_verifyCertPKIXInternal(root, certificateUsageSSLCA, ++ pwdata, ocspPolicy, log, usage, NULL); ++ if (ret != SECSuccess) { ++ return ret; ++ } ++ ++ CERTCertList *rootList = CERT_NewCertList(); ++ CERT_AddCertToListTail(rootList, root); ++ return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata, ++ ocspPolicy, log, usage, rootList); ++ } ++} +-- +2.21.0 + diff --git a/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch b/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch new file mode 100644 index 0000000..586a687 --- /dev/null +++ b/SOURCES/0005-Add-helper-to-run-a-single-test-case.patch @@ -0,0 +1,91 @@ +From 7d1c481e947edf0786223ef43a359c8d5771a214 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 28 Aug 2019 09:23:41 -0400 +Subject: [PATCH 1/3] Add helper to run a single test case + +run_test.sh.in is templated by CMake to build/run_test.sh, fully +configured to your test execution environment. In particular, it writes +the classpath and loads the JSS native library. + +Signed-off-by: Alexander Scheel +--- + cmake/JSSConfig.cmake | 29 +++++++++++++++++++---------- + tools/run_test.sh.in | 15 +++++++++++++++ + 2 files changed, 34 insertions(+), 10 deletions(-) + create mode 100755 tools/run_test.sh.in + +diff --git a/cmake/JSSConfig.cmake b/cmake/JSSConfig.cmake +index 27b2a9bf..6295a6e3 100644 +--- a/cmake/JSSConfig.cmake ++++ b/cmake/JSSConfig.cmake +@@ -13,6 +13,9 @@ macro(jss_config) + + # Configure java-related flags + jss_config_java() ++ ++ # Template auto-generated files ++ jss_config_template() + endmacro() + + macro(jss_config_version MAJOR MINOR PATCH BETA) +@@ -45,16 +48,6 @@ macro(jss_config_version MAJOR MINOR PATCH BETA) + set(JSS_VERSION "${JSS_VERSION} beta ${JSS_VERSION_BETA}") + set(JSS_VERSION_STR "${JSS_VERSION_STR}_b${JSS_VERSION_BETA}") + endif() +- +- # Template files +- configure_file( +- "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h.in" +- "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h" +- ) +- configure_file( +- "${PROJECT_SOURCE_DIR}/lib/MANIFEST.MF.in" +- "${CMAKE_BINARY_DIR}/MANIFEST.MF" +- ) + endmacro() + + macro(jss_config_outputs) +@@ -326,3 +319,19 @@ macro(jss_config_java) + math(EXPR JSS_TEST_PORT_CLIENTAUTH ${JSS_BASE_PORT}+0) + math(EXPR JSS_TEST_PORT_CLIENTAUTH_FIPS ${JSS_BASE_PORT}+1) + endmacro() ++ ++macro(jss_config_template) ++ # Template files ++ configure_file( ++ "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h.in" ++ "${PROJECT_SOURCE_DIR}/org/mozilla/jss/util/jssver.h" ++ ) ++ configure_file( ++ "${PROJECT_SOURCE_DIR}/lib/MANIFEST.MF.in" ++ "${CMAKE_BINARY_DIR}/MANIFEST.MF" ++ ) ++ configure_file( ++ "${PROJECT_SOURCE_DIR}/tools/run_test.sh.in" ++ "${CMAKE_BINARY_DIR}/run_test.sh" ++ ) ++endmacro() +diff --git a/tools/run_test.sh.in b/tools/run_test.sh.in +new file mode 100755 +index 00000000..60233c05 +--- /dev/null ++++ b/tools/run_test.sh.in +@@ -0,0 +1,15 @@ ++#!/bin/bash ++ ++# This utility gets templated to build/run_test.sh to help with running a ++# single test after building JSS. This gives the caller more flexibility ++# with command line arguments and ensures that the correct build artifacts ++# get used. ++ ++export LD_LIBRARY_PATH="${CMAKE_BINARY_DIR}" ++ ++if [ "$1" == "--gdb" ]; then ++ shift ++ gdb --args "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="${CMAKE_BINARY_DIR}" "$@" ++else ++ "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="${CMAKE_BINARY_DIR}" "$@" ++fi +-- +2.21.0 + diff --git a/SOURCES/0006-Add-script-to-add-common-root-CAs.patch b/SOURCES/0006-Add-script-to-add-common-root-CAs.patch new file mode 100644 index 0000000..cde61fe --- /dev/null +++ b/SOURCES/0006-Add-script-to-add-common-root-CAs.patch @@ -0,0 +1,59 @@ +From 61985f642b0b5cc75fc3f254ef6c99aeb56acbe2 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Thu, 29 Aug 2019 16:14:08 -0400 +Subject: [PATCH 2/3] Add script to add common root CAs + +When given an NSS DB, common_roots.sh uses the trust command to extract +the root CAs trusted by the local system and add them to said NSS DB. + +Signed-off-by: Alexander Scheel +--- + tools/common_roots.sh | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + create mode 100755 tools/common_roots.sh + +diff --git a/tools/common_roots.sh b/tools/common_roots.sh +new file mode 100755 +index 00000000..97341c4c +--- /dev/null ++++ b/tools/common_roots.sh +@@ -0,0 +1,36 @@ ++#!/bin/bash ++ ++# This script reads the contents of the OS CA bundle store, ++# /usr/share/pki/ca-trust-source/ca-bundle.trust.p11-kit ++# and places the contained CAs into the specified NSS DB. ++# ++# This NSS DB is used by various JSS tests that aren't enabled ++# by default because they require an active internet connection. ++ ++nssdb="$1" ++ ++if [ -z "$nssdb" ] && [ -e "build" ]; then ++ nssdb="build/results/cadb" ++elif [ -z "$nssdb" ] && [ -e "../build" ]; then ++ nssdb="../build/results/cadb" ++else ++ echo "Must provide path to NSS DB!" 1>&2 ++ exit 1 ++fi ++ ++if [ -e "$nssdb" ]; then ++ rm -rf "$nssdb" ++fi ++ ++mkdir -p "$nssdb" ++echo "" > "$nssdb/password.txt" ++certutil -N -d "$nssdb" -f "$nssdb/password.txt" ++ ++trust extract --format=pem-bundle --filter=ca-anchors "$nssdb/complete.pem" ++ ++# From: https://serverfault.com/questions/391396/how-to-split-a-pem-file ++csplit -f "$nssdb/individual-" "$nssdb/complete.pem" '/-----BEGIN CERTIFICATE-----/' '{*}' ++ ++for cert in "$nssdb"/individual*; do ++ certutil -A -a -i "$cert" -n "$cert" -t CT,C,C -d "$nssdb" -f "$nssdb/password.txt" ++done +-- +2.21.0 + diff --git a/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch b/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch new file mode 100644 index 0000000..ba155f1 --- /dev/null +++ b/SOURCES/0007-Add-optional-test-case-against-badssl.com.patch @@ -0,0 +1,233 @@ +From 7b4c0fa04f5e4469fc8bc442c9f12f975c5e1610 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 28 Aug 2019 09:23:41 -0400 +Subject: [PATCH 3/3] Add optional test case against badssl.com + +badssl.com maintains a number of subdomains with valid and invalid TLS +configurations. A number of these test certificates which fail in +certain scenarios (revoked, expired, etc). Add a test runner which +validates SSLSocket's implementation against badssl.com. + +Signed-off-by: Alexander Scheel +--- + org/mozilla/jss/tests/BadSSL.java | 208 ++++++++++++++++++++++++++++++ + 1 file changed, 208 insertions(+) + create mode 100644 org/mozilla/jss/tests/BadSSL.java + +diff --git a/org/mozilla/jss/tests/BadSSL.java b/org/mozilla/jss/tests/BadSSL.java +new file mode 100644 +index 00000000..60bfe820 +--- /dev/null ++++ b/org/mozilla/jss/tests/BadSSL.java +@@ -0,0 +1,208 @@ ++package org.mozilla.jss.tests; ++ ++import org.mozilla.jss.CryptoManager; ++ ++import org.mozilla.jss.ssl.SSLSocket; ++import org.mozilla.jss.ssl.SSLSocketException; ++ ++import org.mozilla.jss.util.NativeErrcodes; ++ ++/** ++ * The BadSSL test case maintains an internal mapping from badssl.com ++ * subdomains to expected exceptions and validates they occur. ++ * ++ * Since badssl.com offers no guaranteed SLA or availability, we likely ++ * shouldn't add this site to automated tests. ++ */ ++ ++public class BadSSL { ++ public static void main(String[] args) throws Exception { ++ boolean ocsp = false; ++ ++ if (args.length < 1) { ++ System.out.println("Usage: BadSSL nssdb [LEAF_AND_CHAIN]"); ++ return; ++ } ++ ++ if (args.length >= 2 && args[1].equals("LEAF_AND_CHAIN")) { ++ System.out.println("Enabling leaf and chain policy..."); ++ ocsp = true; ++ } ++ ++ CryptoManager.initialize(args[0]); ++ CryptoManager cm = CryptoManager.getInstance(); ++ ++ if (ocsp) { ++ cm.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN); ++ } ++ ++ ++ // Test cases which should fail due to various certificate errors. ++ testExpired(); ++ testWrongHost(); ++ testSelfSigned(); ++ testUntrustedRoot(); ++ ++ // The following test cases depend on crypto-policies or local NSS ++ // configuration. ++ testSHA1(); ++ testRC4MD5(); ++ testRC4(); ++ test3DES(); ++ testNULL(); ++ ++ // The following test cases depend on OCSP being enabled. ++ if (ocsp) { ++ testRevoked(); ++ } ++ ++ // Test cases which should pass given the correct root certs. ++ testSHA256(); ++ testSHA384(); ++ testSHA512(); ++ ++ testECC256(); ++ testECC384(); ++ ++ testRSA2048(); ++ testRSA4096(); ++ testRSA8192(); ++ ++ testExtendedValidation(); ++ } ++ ++ /* Test cases whose handshakes should fail below. */ ++ ++ public static void testExpired() throws Exception { ++ testHelper("expired.badssl.com", 443, new String[]{ "(-8181)", "has expired" }); ++ } ++ ++ public static void testWrongHost() throws Exception { ++ testHelper("wrong.host.badssl.com", 443, new String[]{ "(-12276)", "domain name does not match" }); ++ } ++ ++ public static void testSelfSigned() throws Exception { ++ testHelper("self-signed.badssl.com", 443, new String[]{ "(-8101)", "(-8156)", "type not approved", "issuer certificate is invalid" }); ++ } ++ ++ public static void testUntrustedRoot() throws Exception { ++ testHelper("untrusted-root.badssl.com", 443, new String[]{ "(-8172)", "certificate issuer has been marked as not trusted" }); ++ } ++ ++ public static void testRevoked() throws Exception { ++ testHelper("revoked.badssl.com", 443, new String[]{ "(-8180)", "has been revoked" }); ++ } ++ ++ public static void testSHA1() throws Exception { ++ testHelper("sha1-intermediate.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); ++ } ++ ++ public static void testRC4MD5() throws Exception { ++ testHelper("rc4-md5.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); ++ } ++ ++ public static void testRC4() throws Exception { ++ testHelper("rc4.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); ++ } ++ ++ public static void test3DES() throws Exception { ++ testHelper("3des.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); ++ } ++ ++ public static void testNULL() throws Exception { ++ testHelper("null.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); ++ } ++ ++ /* Test cases which should handshake successfully below. */ ++ ++ public static void testSHA256() throws Exception { ++ testHelper("sha256.badssl.com", 443); ++ } ++ ++ public static void testSHA384() throws Exception { ++ testHelper("sha384.badssl.com", 443); ++ } ++ ++ public static void testSHA512() throws Exception { ++ testHelper("sha512.badssl.com", 443); ++ } ++ ++ public static void testECC256() throws Exception { ++ testHelper("ecc256.badssl.com", 443); ++ } ++ ++ public static void testECC384() throws Exception { ++ testHelper("ecc384.badssl.com", 443); ++ } ++ ++ public static void testRSA2048() throws Exception { ++ testHelper("rsa2048.badssl.com", 443); ++ } ++ ++ public static void testRSA4096() throws Exception { ++ testHelper("rsa4096.badssl.com", 443); ++ } ++ ++ public static void testRSA8192() throws Exception { ++ testHelper("rsa8192.badssl.com", 443); ++ } ++ ++ public static void testExtendedValidation() throws Exception { ++ testHelper("extended-validation.badssl.com", 443); ++ } ++ ++ /* Test case helpers. */ ++ ++ public static void testHelper(String host, int port) throws Exception { ++ testSite(host, port); ++ System.out.println("\t...ok"); ++ } ++ ++ public static void testHelper(String host, int port, String[] substrs) throws Exception { ++ try { ++ testSite(host, port); ++ } catch (SSLSocketException sse) { ++ String actual = sse.getMessage().toLowerCase(); ++ ++ for (String expected : substrs) { ++ if (actual.contains(expected.toLowerCase())) { ++ System.out.println("\t...got expected error message."); ++ return; ++ } ++ } ++ ++ System.err.println("\tUnexpected error message: " + actual); ++ throw sse; ++ } ++ ++ throw new RuntimeException("Expected to get an exception, but didn't!"); ++ } ++ ++ public static void testHelper(String host, int port, int[] codes) throws Exception { ++ try { ++ testSite(host, port); ++ } catch (SSLSocketException sse) { ++ int actual = sse.getErrcode(); ++ for (int expected : codes) { ++ if (actual == expected) { ++ System.out.println("\t...got expected error code."); ++ return; ++ } ++ } ++ ++ System.err.println("\tUnexpected error code: " + actual); ++ throw sse; ++ } ++ ++ throw new RuntimeException("Expected to get an exception, but didn't!"); ++ } ++ ++ public static void testSite(String host, int port) throws Exception { ++ System.out.println("Testing connection to " + host + ":" + port); ++ SSLSocket sock = new SSLSocket(host, 443); ++ sock.forceHandshake(); ++ sock.shutdownOutput(); ++ sock.shutdownInput(); ++ sock.close(); ++ } ++} +-- +2.21.0 + diff --git a/SPECS/jss.spec b/SPECS/jss.spec new file mode 100644 index 0000000..330bc8d --- /dev/null +++ b/SPECS/jss.spec @@ -0,0 +1,205 @@ +################################################################################ +Name: jss +################################################################################ + +Summary: Java Security Services (JSS) +URL: http://www.dogtagpki.org/wiki/JSS +License: MPLv1.1 or GPLv2+ or LGPLv2+ + +Version: 4.6.0 +Release: 5%{?_timestamp}%{?_commit_id}%{?dist} +# global _phase -a1 + +# To generate the source tarball: +# $ git clone https://github.com/dogtagpki/jss.git +# $ cd jss +# $ git tag v4.5. +# $ git push origin v4.5. +# Then go to https://github.com/dogtagpki/jss/releases and download the source +# tarball. +Source: https://github.com/dogtagpki/%{name}/archive/v%{version}%{?_phase}/%{name}-%{version}%{?_phase}.tar.gz + +# To create a patch for all changes since a version tag: +# $ git format-patch \ +# --stdout \ +# \ +# > jss-VERSION-RELEASE.patch +# Patch: jss-VERSION-RELEASE.patch +Patch1: 0001-Disable-buffer-based-tests.patch +Patch2: 0002-Support-LD_FLAGS-from-environment.patch +Patch3: 0003-Remove-legacy-DSA-implementation.patch +Patch4: 0004-JSS-CVE-2019-14823-fix.patch +Patch5: 0005-Add-helper-to-run-a-single-test-case.patch +Patch6: 0006-Add-script-to-add-common-root-CAs.patch +Patch7: 0007-Add-optional-test-case-against-badssl.com.patch + +################################################################################ +# Build Dependencies +################################################################################ + +# autosetup +BuildRequires: git +BuildRequires: make +BuildRequires: cmake + +BuildRequires: gcc-c++ +BuildRequires: nspr-devel >= 4.13.1 +BuildRequires: nss-devel >= 3.30 +BuildRequires: nss-tools >= 3.30 +BuildRequires: java-devel +BuildRequires: jpackage-utils +BuildRequires: slf4j +BuildRequires: glassfish-jaxb-api +%if 0%{?rhel} && 0%{?rhel} <= 7 +# no slf4j-jdk14 +%else +BuildRequires: slf4j-jdk14 +%endif +BuildRequires: apache-commons-lang +BuildRequires: apache-commons-codec + +BuildRequires: junit + +Requires: nss >= 3.30 +Requires: java-headless +Requires: jpackage-utils +Requires: slf4j +Requires: glassfish-jaxb-api +%if 0%{?rhel} && 0%{?rhel} <= 7 +# no slf4j-jdk14 +%else +Requires: slf4j-jdk14 +%endif +Requires: apache-commons-lang +Requires: apache-commons-codec + +Conflicts: ldapjdk < 4.20 +Conflicts: idm-console-framework < 1.2 +Conflicts: tomcatjss < 7.3.4 +Conflicts: pki-base < 10.6.5 + +%description +Java Security Services (JSS) is a java native interface which provides a bridge +for java-based applications to use native Network Security Services (NSS). +This only works with gcj. Other JREs require that JCE providers be signed. + +################################################################################ +%package javadoc +################################################################################ + +Summary: Java Security Services (JSS) Javadocs +Group: Documentation +Requires: jss = %{version}-%{release} + +%description javadoc +This package contains the API documentation for JSS. + +################################################################################ +%prep + +%autosetup -n %{name}-%{version}%{?_phase} -p 1 -S git + +################################################################################ +%build + +%set_build_flags + +[ -z "$JAVA_HOME" ] && export JAVA_HOME=%{_jvmdir}/java + +# Enable compiler optimizations +export BUILD_OPT=1 + +# Generate symbolic info for debuggers +CFLAGS="-g $RPM_OPT_FLAGS" +export CFLAGS + +# The Makefile is not thread-safe +rm -rf build && mkdir -p build && cd build +%cmake \ + -DJAVA_HOME=%{java_home} \ + -DJAVA_LIB_INSTALL_DIR=%{_jnidir} \ + .. + +%{__make} all +%{__make} javadoc || true +ctest --output-on-failure + +################################################################################ +%install + +# There is no install target so we'll do it by hand + +# jars +install -d -m 0755 $RPM_BUILD_ROOT%{_jnidir} +install -m 644 build/jss4.jar ${RPM_BUILD_ROOT}%{_jnidir}/jss4.jar + +# We have to use the name libjss4.so because this is dynamically +# loaded by the jar file. +install -d -m 0755 $RPM_BUILD_ROOT%{_libdir}/jss +install -m 0755 build/libjss4.so ${RPM_BUILD_ROOT}%{_libdir}/jss/ +pushd ${RPM_BUILD_ROOT}%{_libdir}/jss + ln -fs %{_jnidir}/jss4.jar jss4.jar +popd + +# javadoc +install -d -m 0755 $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} +cp -rp build/docs/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} +cp -p jss.html $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} +cp -p *.txt $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} + +# No ldconfig is required since this library is loaded by Java itself. +################################################################################ +%files + +%defattr(-,root,root,-) +%doc jss.html MPL-1.1.txt gpl.txt lgpl.txt +%{_libdir}/* +%{_jnidir}/* + +################################################################################ +%files javadoc + +%defattr(-,root,root,-) +%{_javadocdir}/%{name}-%{version}/ + +################################################################################ +%changelog +* Wed Sep 11 2019 Red Hat PKI Team 4.6.0-5 +- Bugzilla #1747987 - CVE 2019-14823 jss: OCSP policy "Leaf and Chain" implicitly trusts the root certificate + +* Wed Aug 14 2019 Red Hat PKI Team 4.6.0-4 +- Red Hat Bugzilla #1698059 - pki-core implements crypto + +* Tue Jul 16 2019 Red Hat PKI Team 4.6.0-3 +- Red Hat Bugilla #1721135 - JSS - LD_FLAGS support + +* Wed Jun 12 2019 Red Hat PKI Team 4.6.0-2 +- Minor updates to release + +* Wed Jun 12 2019 Red Hat PKI Team 4.6.0-1 +- Rebased to JSS 4.6.0 + +* Thu Apr 25 2019 Red Hat PKI Team 4.5.3-1 +- Rebased to JSS 4.5.3 + +* Fri Aug 10 2018 Red Hat PKI Team 4.5.0-1 +- Rebased to JSS 4.5.0 + +* Tue Aug 07 2018 Red Hat PKI Team 4.5.0-0.6 +- Rebased to JSS 4.5.0-b1 + +* Tue Aug 07 2018 Red Hat PKI Team 4.5.0-0.5 +- Red Hat Bugzilla #1612063 - Do not override system crypto policy (support TLS 1.3) + +* Fri Jul 20 2018 Red Hat PKI Team 4.5.0-0.4 +- Rebased to JSS 4.5.0-a4 +- Red Hat Bugzilla #1604462 - jss: FTBFS in Fedora rawhide + +* Thu Jul 05 2018 Red Hat PKI Team 4.5.0-0.3 +- Rebased to JSS 4.5.0-a3 + +* Fri Jun 22 2018 Red Hat PKI Team 4.5.0-0.2 +- Rebased to JSS 4.5.0-a2 + +* Fri Jun 15 2018 Red Hat PKI Team 4.5.0-0.1 +- Rebased to JSS 4.5.0-a1