diff --git a/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java b/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java index 3c3ef229111..0ae68957c43 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/AESCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,18 +47,122 @@ import javax.crypto.BadPaddingException; * @see OutputFeedback */ -public final class AESCipher extends CipherSpi { +abstract class AESCipher extends CipherSpi { + public static final class General extends AESCipher { + public General() { + super(-1); + } + } + abstract static class OidImpl extends AESCipher { + protected OidImpl(int keySize, String mode, String padding) { + super(keySize); + try { + engineSetMode(mode); + engineSetPadding(padding); + } catch (GeneralSecurityException gse) { + // internal error; re-throw as provider exception + ProviderException pe =new ProviderException("Internal Error"); + pe.initCause(gse); + throw pe; + } + } + } + public static final class AES128_ECB_NoPadding extends OidImpl { + public AES128_ECB_NoPadding() { + super(16, "ECB", "NOPADDING"); + } + } + public static final class AES192_ECB_NoPadding extends OidImpl { + public AES192_ECB_NoPadding() { + super(24, "ECB", "NOPADDING"); + } + } + public static final class AES256_ECB_NoPadding extends OidImpl { + public AES256_ECB_NoPadding() { + super(32, "ECB", "NOPADDING"); + } + } + public static final class AES128_CBC_NoPadding extends OidImpl { + public AES128_CBC_NoPadding() { + super(16, "CBC", "NOPADDING"); + } + } + public static final class AES192_CBC_NoPadding extends OidImpl { + public AES192_CBC_NoPadding() { + super(24, "CBC", "NOPADDING"); + } + } + public static final class AES256_CBC_NoPadding extends OidImpl { + public AES256_CBC_NoPadding() { + super(32, "CBC", "NOPADDING"); + } + } + public static final class AES128_OFB_NoPadding extends OidImpl { + public AES128_OFB_NoPadding() { + super(16, "OFB", "NOPADDING"); + } + } + public static final class AES192_OFB_NoPadding extends OidImpl { + public AES192_OFB_NoPadding() { + super(24, "OFB", "NOPADDING"); + } + } + public static final class AES256_OFB_NoPadding extends OidImpl { + public AES256_OFB_NoPadding() { + super(32, "OFB", "NOPADDING"); + } + } + public static final class AES128_CFB_NoPadding extends OidImpl { + public AES128_CFB_NoPadding() { + super(16, "CFB", "NOPADDING"); + } + } + public static final class AES192_CFB_NoPadding extends OidImpl { + public AES192_CFB_NoPadding() { + super(24, "CFB", "NOPADDING"); + } + } + public static final class AES256_CFB_NoPadding extends OidImpl { + public AES256_CFB_NoPadding() { + super(32, "CFB", "NOPADDING"); + } + } + + // utility method used by AESCipher and AESWrapCipher + static final void checkKeySize(Key key, int fixedKeySize) + throws InvalidKeyException { + if (fixedKeySize != -1) { + if (key == null) { + throw new InvalidKeyException("The key must not be null"); + } + byte[] value = key.getEncoded(); + if (value == null) { + throw new InvalidKeyException("Key encoding must not be null"); + } else if (value.length != fixedKeySize) { + throw new InvalidKeyException("The key must be " + + fixedKeySize*8 + " bits"); + } + } + } + /* * internal CipherCore object which does the real work. */ private CipherCore core = null; + /* + * needed to support AES oids which associates a fixed key size + * to the cipher object. + */ + private final int fixedKeySize; // in bytes, -1 if no restriction + /** * Creates an instance of AES cipher with default ECB mode and * PKCS5Padding. */ - public AESCipher() { + protected AESCipher(int keySize) { core = new CipherCore(new AESCrypt(), AESConstants.AES_BLOCK_SIZE); + fixedKeySize = keySize; } /** @@ -183,6 +287,7 @@ public final class AESCipher extends CipherSpi { */ protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { + checkKeySize(key, fixedKeySize); core.init(opmode, key, random); } @@ -214,6 +319,7 @@ public final class AESCipher extends CipherSpi { AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + checkKeySize(key, fixedKeySize); core.init(opmode, key, params, random); } @@ -221,6 +327,7 @@ public final class AESCipher extends CipherSpi { AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + checkKeySize(key, fixedKeySize); core.init(opmode, key, params, random); } diff --git a/jdk/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java b/jdk/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java index 21327dd09f7..29a22ad64b6 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,27 @@ import javax.crypto.spec.*; * * @see AESCipher */ -public final class AESWrapCipher extends CipherSpi { - +abstract class AESWrapCipher extends CipherSpi { + public static final class General extends AESWrapCipher { + public General() { + super(-1); + } + } + public static final class AES128 extends AESWrapCipher { + public AES128() { + super(16); + } + } + public static final class AES192 extends AESWrapCipher { + public AES192() { + super(24); + } + } + public static final class AES256 extends AESWrapCipher { + public AES256() { + super(32); + } + } private static final byte[] IV = { (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6 @@ -62,12 +81,20 @@ public final class AESWrapCipher extends CipherSpi { */ private boolean decrypting = false; + /* + * needed to support AES oids which associates a fixed key size + * to the cipher object. + */ + private final int fixedKeySize; // in bytes, -1 if no restriction + /** * Creates an instance of AES KeyWrap cipher with default * mode, i.e. "ECB" and padding scheme, i.e. "NoPadding". */ - public AESWrapCipher() { + public AESWrapCipher(int keySize) { cipher = new AESCrypt(); + fixedKeySize = keySize; + } /** @@ -170,6 +197,7 @@ public final class AESWrapCipher extends CipherSpi { throw new UnsupportedOperationException("This cipher can " + "only be used for key wrapping and unwrapping"); } + AESCipher.checkKeySize(key, fixedKeySize); cipher.init(decrypting, key.getAlgorithm(), key.getEncoded()); } diff --git a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java index 1813bf260e9..533d80d49af 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,10 +80,10 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { * @param random the source of randomness */ public void initialize(int keysize, SecureRandom random) { - if ((keysize < 512) || (keysize > 1024) || (keysize % 64 != 0)) { + if ((keysize < 512) || (keysize > 2048) || (keysize % 64 != 0)) { throw new InvalidParameterException("Keysize must be multiple " + "of 64, and can only range " - + "from 512 to 1024 " + + "from 512 to 2048 " + "(inclusive)"); } this.pSize = keysize; @@ -115,11 +115,11 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { params = (DHParameterSpec)algParams; pSize = params.getP().bitLength(); - if ((pSize < 512) || (pSize > 1024) || + if ((pSize < 512) || (pSize > 2048) || (pSize % 64 != 0)) { throw new InvalidAlgorithmParameterException ("Prime size must be multiple of 64, and can only range " - + "from 512 to 1024 (inclusive)"); + + "from 512 to 2048 (inclusive)"); } // exponent size is optional, could be 0 @@ -156,10 +156,11 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { BigInteger g = params.getG(); if (lSize <= 0) { + lSize = pSize >> 1; // use an exponent size of (pSize / 2) but at least 384 bits - lSize = Math.max(384, pSize >> 1); - // if lSize is larger than pSize, limit by pSize - lSize = Math.min(lSize, pSize); + if (lSize < 384) { + lSize = 384; + } } BigInteger x; diff --git a/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java b/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java index 0d2eec7c776..0088729d27d 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,10 +67,10 @@ extends AlgorithmParameterGeneratorSpi { * @param random the source of randomness */ protected void engineInit(int keysize, SecureRandom random) { - if ((keysize < 512) || (keysize > 1024) || (keysize % 64 != 0)) { + if ((keysize < 512) || (keysize > 2048) || (keysize % 64 != 0)) { throw new InvalidParameterException("Keysize must be multiple " + "of 64, and can only range " - + "from 512 to 1024 " + + "from 512 to 2048 " + "(inclusive)"); } this.primeSize = keysize; @@ -99,10 +99,10 @@ extends AlgorithmParameterGeneratorSpi { DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec; primeSize = dhParamSpec.getPrimeSize(); - if ((primeSize<512) || (primeSize>1024) || (primeSize%64 != 0)) { + if ((primeSize<512) || (primeSize>2048) || (primeSize%64 != 0)) { throw new InvalidAlgorithmParameterException ("Modulus size must be multiple of 64, and can only range " - + "from 512 to 1024 (inclusive)"); + + "from 512 to 2048 (inclusive)"); } exponentSize = dhParamSpec.getExponentSize(); diff --git a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java index e7a815283b5..925343e51f0 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/SunJCE.java @@ -167,17 +167,67 @@ public final class SunJCE extends Provider { put("Cipher.Blowfish SupportedPaddings", BLOCK_PADS); put("Cipher.Blowfish SupportedKeyFormats", "RAW"); - put("Cipher.AES", "com.sun.crypto.provider.AESCipher"); + put("Cipher.AES", "com.sun.crypto.provider.AESCipher$General"); put("Alg.Alias.Cipher.Rijndael", "AES"); put("Cipher.AES SupportedModes", BLOCK_MODES128); put("Cipher.AES SupportedPaddings", BLOCK_PADS); put("Cipher.AES SupportedKeyFormats", "RAW"); - put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher"); + put("Cipher.AES_128/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding"); + put("Cipher.AES_128/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding"); + put("Cipher.AES_128/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding"); + put("Cipher.AES_128/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding"); + + put("Cipher.AES_192/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding"); + put("Cipher.AES_192/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding"); + put("Cipher.AES_192/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding"); + put("Cipher.AES_192/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding"); + + + put("Cipher.AES_256/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding"); + put("Cipher.AES_256/CBC/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding"); + put("Cipher.AES_256/OFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding"); + put("Cipher.AES_256/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding"); + + put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher$General"); put("Cipher.AESWrap SupportedModes", "ECB"); put("Cipher.AESWrap SupportedPaddings", "NOPADDING"); put("Cipher.AESWrap SupportedKeyFormats", "RAW"); + put("Cipher.AESWrap_128", "com.sun.crypto.provider.AESWrapCipher$AES128"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.5", "AESWrap_128"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.5", "AESWrap_128"); + put("Cipher.AESWrap_192", "com.sun.crypto.provider.AESWrapCipher$AES192"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.25", "AESWrap_192"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.25", "AESWrap_192"); + put("Cipher.AESWrap_256", "com.sun.crypto.provider.AESWrapCipher$AES256"); + put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.45", "AESWrap_256"); + put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.45", "AESWrap_256"); + put("Cipher.RC2", "com.sun.crypto.provider.RC2Cipher"); put("Cipher.RC2 SupportedModes", BLOCK_MODES); @@ -192,7 +242,7 @@ public final class SunJCE extends Provider { put("Cipher.ARCFOUR SupportedKeyFormats", "RAW"); /* - * Key(pair) Generator engines + * Key(pair) Generator engines */ put("KeyGenerator.DES", "com.sun.crypto.provider.DESKeyGenerator"); @@ -221,6 +271,8 @@ public final class SunJCE extends Provider { put("KeyGenerator.HmacSHA1", "com.sun.crypto.provider.HmacSHA1KeyGenerator"); + put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.7", "HmacSHA1"); + put("Alg.Alias.KeyGenerator.1.2.840.113549.2.7", "HmacSHA1"); put("KeyGenerator.HmacSHA224", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA224"); @@ -326,14 +378,12 @@ public final class SunJCE extends Provider { "com.sun.crypto.provider.AESParameters"); put("Alg.Alias.AlgorithmParameters.Rijndael", "AES"); - put("AlgorithmParameters.RC2", "com.sun.crypto.provider.RC2Parameters"); put("AlgorithmParameters.OAEP", "com.sun.crypto.provider.OAEPParameters"); - /* * Key factories */ @@ -403,6 +453,8 @@ public final class SunJCE extends Provider { */ put("Mac.HmacMD5", "com.sun.crypto.provider.HmacMD5"); put("Mac.HmacSHA1", "com.sun.crypto.provider.HmacSHA1"); + put("Alg.Alias.Mac.OID.1.2.840.113549.2.7", "HmacSHA1"); + put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1"); put("Mac.HmacSHA224", "com.sun.crypto.provider.HmacCore$HmacSHA224"); put("Alg.Alias.Mac.OID.1.2.840.113549.2.8", "HmacSHA224"); diff --git a/jdk/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java b/jdk/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java index d86bbbc6a4e..96a091ef84a 100644 --- a/jdk/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java +++ b/jdk/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,6 +62,9 @@ import java.security.*; * interface is all that is needed when you accept defaults for algorithm-specific * parameters. * + *
Note: Some earlier implementations of this interface may not support
+ * larger sizes of DSA parameters such as 2048 and 3072-bit.
+ *
* @see java.security.KeyPairGenerator
*/
public interface DSAKeyPairGenerator {
@@ -78,7 +81,7 @@ public interface DSAKeyPairGenerator {
* can be null.
*
* @exception InvalidParameterException if the params
- * value is invalid or null.
+ * value is invalid, null, or unsupported.
*/
public void initialize(DSAParams params, SecureRandom random)
throws InvalidParameterException;
@@ -97,7 +100,7 @@ public interface DSAKeyPairGenerator {
* default parameters for modulus lengths of 512 and 1024 bits.
*
* @param modlen the modulus length in bits. Valid values are any
- * multiple of 8 between 512 and 1024, inclusive.
+ * multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
*
* @param random the random bit source to use to generate key bits;
* can be null.
@@ -105,10 +108,9 @@ public interface DSAKeyPairGenerator {
* @param genParams whether or not to generate new parameters for
* the modulus length requested.
*
- * @exception InvalidParameterException if modlen
is not
- * between 512 and 1024, or if genParams
is false and
- * there are no precomputed parameters for the requested modulus
- * length.
+ * @exception InvalidParameterException if modlen
is
+ * invalid, or unsupported, or if genParams
is false and there
+ * are no precomputed parameters for the requested modulus length.
*/
public void initialize(int modlen, boolean genParams, SecureRandom random)
throws InvalidParameterException;
diff --git a/jdk/src/share/classes/java/security/spec/DSAGenParameterSpec.java b/jdk/src/share/classes/java/security/spec/DSAGenParameterSpec.java
new file mode 100644
index 00000000000..a354c4807ac
--- /dev/null
+++ b/jdk/src/share/classes/java/security/spec/DSAGenParameterSpec.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+/**
+ * This immutable class specifies the set of parameters used for
+ * generating DSA parameters as specified in
+ * FIPS 186-3 Digital Signature Standard (DSS).
+ *
+ * @see AlgorithmParameterSpec
+ *
+ * @since 8
+ */
+public final class DSAGenParameterSpec implements AlgorithmParameterSpec {
+
+ private final int pLen;
+ private final int qLen;
+ private final int seedLen;
+
+ /**
+ * Creates a domain parameter specification for DSA parameter
+ * generation using primePLen
and subprimeQLen
.
+ * The value of subprimeQLen
is also used as the default
+ * length of the domain parameter seed in bits.
+ * @param primePLen the desired length of the prime P in bits.
+ * @param subprimeQLen the desired length of the sub-prime Q in bits.
+ * @exception IllegalArgumentException if primePLen
+ * or subprimeQLen
is illegal per the specification of
+ * FIPS 186-3.
+ */
+ public DSAGenParameterSpec(int primePLen, int subprimeQLen) {
+ this(primePLen, subprimeQLen, subprimeQLen);
+ }
+
+ /**
+ * Creates a domain parameter specification for DSA parameter
+ * generation using primePLen
, subprimeQLen
,
+ * and seedLen
.
+ * @param primePLen the desired length of the prime P in bits.
+ * @param subprimeQLen the desired length of the sub-prime Q in bits.
+ * @param seedLen the desired length of the domain parameter seed in bits,
+ * shall be equal to or greater than subprimeQLen
.
+ * @exception IllegalArgumentException if primePLenLen
,
+ * subprimeQLen
, or seedLen
is illegal per the
+ * specification of FIPS 186-3.
+ */
+ public DSAGenParameterSpec(int primePLen, int subprimeQLen, int seedLen) {
+ switch (primePLen) {
+ case 1024:
+ if (subprimeQLen != 160) {
+ throw new IllegalArgumentException
+ ("subprimeQLen must be 160 when primePLen=1024");
+ }
+ break;
+ case 2048:
+ if (subprimeQLen != 224 && subprimeQLen != 256) {
+ throw new IllegalArgumentException
+ ("subprimeQLen must be 224 or 256 when primePLen=2048");
+ }
+ break;
+ case 3072:
+ if (subprimeQLen != 256) {
+ throw new IllegalArgumentException
+ ("subprimeQLen must be 256 when primePLen=3072");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException
+ ("primePLen must be 1024, 2048, or 3072");
+ }
+ if (seedLen < subprimeQLen) {
+ throw new IllegalArgumentException
+ ("seedLen must be equal to or greater than subprimeQLen");
+ }
+ this.pLen = primePLen;
+ this.qLen = subprimeQLen;
+ this.seedLen = seedLen;
+ }
+
+ /**
+ * Returns the desired length of the prime P of the
+ * to-be-generated DSA domain parameters in bits.
+ * @return the length of the prime P.
+ */
+ public int getPrimePLength() {
+ return pLen;
+ }
+
+ /**
+ * Returns the desired length of the sub-prime Q of the
+ * to-be-generated DSA domain parameters in bits.
+ * @return the length of the sub-prime Q.
+ */
+ public int getSubprimeQLength() {
+ return qLen;
+ }
+
+ /**
+ * Returns the desired length of the domain parameter seed in bits.
+ * @return the length of the domain parameter seed.
+ */
+ public int getSeedLength() {
+ return seedLen;
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/ec/SunECEntries.java b/jdk/src/share/classes/sun/security/ec/SunECEntries.java
index e359ccc79f1..fe810ee8abf 100644
--- a/jdk/src/share/classes/sun/security/ec/SunECEntries.java
+++ b/jdk/src/share/classes/sun/security/ec/SunECEntries.java
@@ -134,6 +134,9 @@ final class SunECEntries {
"sun.security.ec.ECDSASignature$Raw");
map.put("Signature.SHA1withECDSA",
"sun.security.ec.ECDSASignature$SHA1");
+ map.put("Alg.Alias.Signature.OID.1.2.840.10045.4.1", "SHA1withECDSA");
+ map.put("Alg.Alias.Signature.1.2.840.10045.4.1", "SHA1withECDSA");
+
map.put("Signature.SHA224withECDSA",
"sun.security.ec.ECDSASignature$SHA224");
map.put("Alg.Alias.Signature.OID.1.2.840.10045.4.3.1", "SHA224withECDSA");
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
index 8179dc01682..c7d62ff6b46 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -164,6 +164,10 @@ final class P11Cipher extends CipherSpi {
// if we do the padding
private int bytesBuffered;
+ // length of key size in bytes; currently only used by AES given its oid
+ // specification mandates a fixed size of the key
+ private int fixedKeySize = -1;
+
P11Cipher(Token token, String algorithm, long mechanism)
throws PKCS11Exception, NoSuchAlgorithmException {
super();
@@ -172,19 +176,26 @@ final class P11Cipher extends CipherSpi {
this.mechanism = mechanism;
String algoParts[] = algorithm.split("/");
- keyAlgorithm = algoParts[0];
- if (keyAlgorithm.equals("AES")) {
+ if (algoParts[0].startsWith("AES")) {
blockSize = 16;
- } else if (keyAlgorithm.equals("RC4") ||
- keyAlgorithm.equals("ARCFOUR")) {
- blockSize = 0;
- } else { // DES, DESede, Blowfish
- blockSize = 8;
- }
- this.blockMode =
+ int index = algoParts[0].indexOf('_');
+ if (index != -1) {
+ // should be well-formed since we specify what we support
+ fixedKeySize = Integer.parseInt(algoParts[0].substring(index+1))/8;
+ }
+ keyAlgorithm = "AES";
+ } else {
+ keyAlgorithm = algoParts[0];
+ if (keyAlgorithm.equals("RC4") ||
+ keyAlgorithm.equals("ARCFOUR")) {
+ blockSize = 0;
+ } else { // DES, DESede, Blowfish
+ blockSize = 8;
+ }
+ this.blockMode =
(algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
-
+ }
String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
String paddingStr =
(algoParts.length > 2 ? algoParts[2] : defPadding);
@@ -333,6 +344,9 @@ final class P11Cipher extends CipherSpi {
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
cancelOperation();
+ if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
+ throw new InvalidKeyException("Key size is invalid");
+ }
switch (opmode) {
case Cipher.ENCRYPT_MODE:
encrypt = true;
diff --git a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
index bac38137f16..d138d675a48 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -399,12 +399,8 @@ public final class SunPKCS11 extends AuthProvider {
return System.identityHashCode(this);
}
- private static String[] s(String s1) {
- return new String[] {s1};
- }
-
- private static String[] s(String s1, String s2) {
- return new String[] {s1, s2};
+ private static String[] s(String ...aliases) {
+ return aliases;
}
private static final class Descriptor {
@@ -521,7 +517,8 @@ public final class SunPKCS11 extends AuthProvider {
m(CKM_MD2));
d(MD, "MD5", P11Digest,
m(CKM_MD5));
- d(MD, "SHA1", P11Digest, s("SHA", "SHA-1"),
+ d(MD, "SHA1", P11Digest,
+ s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"),
m(CKM_SHA_1));
d(MD, "SHA-224", P11Digest,
@@ -540,6 +537,7 @@ public final class SunPKCS11 extends AuthProvider {
d(MAC, "HmacMD5", P11MAC,
m(CKM_MD5_HMAC));
d(MAC, "HmacSHA1", P11MAC,
+ s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"),
m(CKM_SHA_1_HMAC));
d(MAC, "HmacSHA224", P11MAC,
s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"),
@@ -561,6 +559,7 @@ public final class SunPKCS11 extends AuthProvider {
d(KPG, "RSA", P11KeyPairGenerator,
m(CKM_RSA_PKCS_KEY_PAIR_GEN));
d(KPG, "DSA", P11KeyPairGenerator,
+ s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
m(CKM_DSA_KEY_PAIR_GEN));
d(KPG, "DH", P11KeyPairGenerator, s("DiffieHellman"),
m(CKM_DH_PKCS_KEY_PAIR_GEN));
@@ -583,6 +582,7 @@ public final class SunPKCS11 extends AuthProvider {
d(KF, "RSA", P11RSAKeyFactory,
m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));
d(KF, "DSA", P11DSAKeyFactory,
+ s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));
d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
@@ -609,6 +609,7 @@ public final class SunPKCS11 extends AuthProvider {
d(SKF, "DESede", P11SecretKeyFactory,
m(CKM_DES3_CBC));
d(SKF, "AES", P11SecretKeyFactory,
+ s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"),
m(CKM_AES_CBC));
d(SKF, "Blowfish", P11SecretKeyFactory,
m(CKM_BLOWFISH_CBC));
@@ -635,10 +636,28 @@ public final class SunPKCS11 extends AuthProvider {
m(CKM_DES3_ECB));
d(CIP, "AES/CBC/NoPadding", P11Cipher,
m(CKM_AES_CBC));
+ d(CIP, "AES_128/CBC/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
+ m(CKM_AES_CBC));
+ d(CIP, "AES_192/CBC/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
+ m(CKM_AES_CBC));
+ d(CIP, "AES_256/CBC/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"),
+ m(CKM_AES_CBC));
d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,
m(CKM_AES_CBC_PAD, CKM_AES_CBC));
d(CIP, "AES/ECB/NoPadding", P11Cipher,
m(CKM_AES_ECB));
+ d(CIP, "AES_128/ECB/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
+ m(CKM_AES_ECB));
+ d(CIP, "AES_192/ECB/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
+ m(CKM_AES_ECB));
+ d(CIP, "AES_256/ECB/NoPadding", P11Cipher,
+ s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"),
+ m(CKM_AES_ECB));
d(CIP, "AES/ECB/PKCS5Padding", P11Cipher, s("AES"),
m(CKM_AES_ECB));
d(CIP, "AES/CTR/NoPadding", P11Cipher,
@@ -654,13 +673,16 @@ public final class SunPKCS11 extends AuthProvider {
d(CIP, "RSA/ECB/NoPadding", P11RSACipher,
m(CKM_RSA_X_509));
- d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"),
+ d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"),
m(CKM_DSA));
- d(SIG, "DSA", P11Signature, s("SHA1withDSA"),
+ d(SIG, "DSA", P11Signature,
+ s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27",
+ "1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),
m(CKM_DSA_SHA1, CKM_DSA));
d(SIG, "NONEwithECDSA", P11Signature,
m(CKM_ECDSA));
- d(SIG, "SHA1withECDSA", P11Signature, s("ECDSA"),
+ d(SIG, "SHA1withECDSA", P11Signature,
+ s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"),
m(CKM_ECDSA_SHA1, CKM_ECDSA));
d(SIG, "SHA224withECDSA", P11Signature,
s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"),
@@ -675,10 +697,14 @@ public final class SunPKCS11 extends AuthProvider {
s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"),
m(CKM_ECDSA));
d(SIG, "MD2withRSA", P11Signature,
+ s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"),
m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
d(SIG, "MD5withRSA", P11Signature,
+ s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"),
m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
d(SIG, "SHA1withRSA", P11Signature,
+ s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
+ "1.3.14.3.2.29"),
m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
d(SIG, "SHA224withRSA", P11Signature,
s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"),
diff --git a/jdk/src/share/classes/sun/security/provider/DSA.java b/jdk/src/share/classes/sun/security/provider/DSA.java
index a59679ccc6f..411563f42e4 100644
--- a/jdk/src/share/classes/sun/security/provider/DSA.java
+++ b/jdk/src/share/classes/sun/security/provider/DSA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,14 +45,15 @@ import sun.security.jca.JCAUtil;
/**
* 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).
+ * Algorithm), as described in fips186-3 of the National Instute of
+ * Standards and Technology (NIST), using SHA digest algorithms
+ * from FIPS180-3.
*
* This file contains both the signature implementation for the
- * commonly used SHA1withDSA (DSS) as well as RawDSA, used by TLS
- * among others. RawDSA expects the 20 byte SHA-1 digest as input
- * via update rather than the original data like other signature
- * implementations.
+ * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA,
+ * as well as RawDSA, used by TLS among others. RawDSA expects
+ * the 20 byte SHA-1 digest as input via update rather than the
+ * original data like other signature implementations.
*
* @author Benjamin Renaud
*
@@ -78,129 +79,19 @@ abstract class DSA extends SignatureSpi {
/* The private key, if any */
private BigInteger presetX;
- /* 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;
+ /* The message digest object used */
+ private final MessageDigest md;
+
/**
* Construct a blank DSA object. It must be
* initialized before being usable for signing or verifying.
*/
- DSA() {
+ DSA(MessageDigest md) {
super();
- }
-
- /**
- * Return the 20 byte hash value and reset the digest.
- */
- abstract byte[] getDigest() throws SignatureException;
-
- /**
- * Reset the digest.
- */
- abstract void resetDigest();
-
- /**
- * Standard SHA1withDSA implementation.
- */
- public static final class SHA1withDSA extends DSA {
-
- /* The SHA hash for the data */
- private final MessageDigest dataSHA;
-
- public SHA1withDSA() throws NoSuchAlgorithmException {
- dataSHA = MessageDigest.getInstance("SHA-1");
- }
-
- /**
- * Update a byte to be signed or verified.
- */
- protected void engineUpdate(byte b) {
- dataSHA.update(b);
- }
-
- /**
- * Update an array of bytes to be signed or verified.
- */
- protected void engineUpdate(byte[] data, int off, int len) {
- dataSHA.update(data, off, len);
- }
-
- protected void engineUpdate(ByteBuffer b) {
- dataSHA.update(b);
- }
-
- byte[] getDigest() {
- return dataSHA.digest();
- }
-
- void resetDigest() {
- dataSHA.reset();
- }
- }
-
- /**
- * RawDSA implementation.
- *
- * RawDSA requires the data to be exactly 20 bytes long. If it is
- * not, a SignatureException is thrown when sign()/verify() is called
- * per JCA spec.
- */
- public static final class RawDSA extends DSA {
-
- // length of the SHA-1 digest (20 bytes)
- private final static int SHA1_LEN = 20;
-
- // 20 byte digest buffer
- private final byte[] digestBuffer;
-
- // offset into the buffer
- private int ofs;
-
- public RawDSA() {
- digestBuffer = new byte[SHA1_LEN];
- }
-
- protected void engineUpdate(byte b) {
- if (ofs == SHA1_LEN) {
- ofs = SHA1_LEN + 1;
- return;
- }
- digestBuffer[ofs++] = b;
- }
-
- protected void engineUpdate(byte[] data, int off, int len) {
- if (ofs + len > SHA1_LEN) {
- ofs = SHA1_LEN + 1;
- return;
- }
- System.arraycopy(data, off, digestBuffer, ofs, len);
- ofs += len;
- }
-
- byte[] getDigest() throws SignatureException {
- if (ofs != SHA1_LEN) {
- throw new SignatureException
- ("Data for RawDSA must be exactly 20 bytes long");
- }
- ofs = 0;
- return digestBuffer;
- }
-
- void resetDigest() {
- ofs = 0;
- }
+ this.md = md;
}
/**
@@ -217,13 +108,25 @@ abstract class DSA extends SignatureSpi {
throw new InvalidKeyException("not a DSA private key: " +
privateKey);
}
+
java.security.interfaces.DSAPrivateKey priv =
(java.security.interfaces.DSAPrivateKey)privateKey;
+
+ // check for algorithm specific constraints before doing initialization
+ DSAParams params = priv.getParams();
+ if (params == null) {
+ throw new InvalidKeyException("DSA private key lacks parameters");
+ }
+ checkKey(params);
+
+ this.params = params;
this.presetX = priv.getX();
this.presetY = null;
- initialize(priv.getParams());
+ this.presetP = params.getP();
+ this.presetQ = params.getQ();
+ this.presetG = params.getG();
+ this.md.reset();
}
-
/**
* Initialize the DSA object with a DSA public key.
*
@@ -240,16 +143,42 @@ abstract class DSA extends SignatureSpi {
}
java.security.interfaces.DSAPublicKey pub =
(java.security.interfaces.DSAPublicKey)publicKey;
+
+ // check for algorithm specific constraints before doing initialization
+ DSAParams params = pub.getParams();
+ if (params == null) {
+ throw new InvalidKeyException("DSA public key lacks parameters");
+ }
+ checkKey(params);
+
+ this.params = params;
this.presetY = pub.getY();
this.presetX = null;
- initialize(pub.getParams());
+ this.presetP = params.getP();
+ this.presetQ = params.getQ();
+ this.presetG = params.getG();
+ this.md.reset();
}
- private void initialize(DSAParams params) throws InvalidKeyException {
- resetDigest();
- setParams(params);
+ /**
+ * Update a byte to be signed or verified.
+ */
+ protected void engineUpdate(byte b) {
+ md.update(b);
}
+ /**
+ * Update an array of bytes to be signed or verified.
+ */
+ protected void engineUpdate(byte[] data, int off, int len) {
+ md.update(data, off, len);
+ }
+
+ protected void engineUpdate(ByteBuffer b) {
+ md.update(b);
+ }
+
+
/**
* Sign all the data thus far updated. The signature is formatted
* according to the Canonical Encoding Rules, returned as a DER
@@ -352,23 +281,51 @@ abstract class DSA extends SignatureSpi {
}
}
+ @Deprecated
+ protected void engineSetParameter(String key, Object param) {
+ throw new InvalidParameterException("No parameter accepted");
+ }
+
+ @Deprecated
+ protected Object engineGetParameter(String key) {
+ return null;
+ }
+
+ protected void checkKey(DSAParams params) throws InvalidKeyException {
+ // FIPS186-3 states in sec4.2 that a hash function which provides
+ // a lower security strength than the (L, N) pair ordinarily should
+ // not be used.
+ int valueN = params.getQ().bitLength();
+ if (valueN > md.getDigestLength()*8) {
+ throw new InvalidKeyException("Key is too strong for this signature algorithm");
+ }
+ }
+
private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
BigInteger k) {
BigInteger temp = g.modPow(k, p);
- return temp.remainder(q);
- }
+ return temp.mod(q);
+ }
private BigInteger generateS(BigInteger x, BigInteger q,
BigInteger r, BigInteger k) throws SignatureException {
- byte[] s2 = getDigest();
- BigInteger temp = new BigInteger(1, s2);
+ byte[] s2;
+ try {
+ s2 = md.digest();
+ } catch (RuntimeException re) {
+ // Only for RawDSA due to its 20-byte length restriction
+ throw new SignatureException(re.getMessage());
+ }
+ // get the leftmost min(N, outLen) bits of the digest value
+ int nBytes = q.bitLength()/8;
+ if (nBytes < s2.length) {
+ s2 = Arrays.copyOfRange(s2, 0, nBytes);
+ }
+ BigInteger z = 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);
+ return x.multiply(r).add(z).multiply(k1).mod(q);
}
private BigInteger generateW(BigInteger p, BigInteger q,
@@ -380,54 +337,41 @@ abstract class DSA extends SignatureSpi {
BigInteger q, BigInteger g, BigInteger w, BigInteger r)
throws SignatureException {
- byte[] s2 = getDigest();
- BigInteger temp = new BigInteger(1, s2);
+ byte[] s2;
+ try {
+ s2 = md.digest();
+ } catch (RuntimeException re) {
+ // Only for RawDSA due to its 20-byte length restriction
+ throw new SignatureException(re.getMessage());
+ }
+ // get the leftmost min(N, outLen) bits of the digest value
+ int nBytes = q.bitLength()/8;
+ if (nBytes < s2.length) {
+ s2 = Arrays.copyOfRange(s2, 0, nBytes);
+ }
+ BigInteger z = new BigInteger(1, s2);
- temp = temp.multiply(w);
- BigInteger u1 = temp.remainder(q);
-
- BigInteger u2 = (r.multiply(w)).remainder(q);
+ BigInteger u1 = z.multiply(w).mod(q);
+ BigInteger u2 = (r.multiply(w)).mod(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);
+ BigInteger t5 = t3.mod(p);
+ return t5.mod(q);
}
- /*
- * Please read bug report 4044247 for an alternative, faster,
- * NON-FIPS approved method to generate K
- */
- private 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 && !Arrays.equals(Kseed, previousKseed)) {
- 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.
+ // NOTE: This following impl is defined in FIPS 186-3 AppendixB.2.2.
+ // Original DSS algos such as SHA1withDSA and RawDSA uses a different
+ // algorithm defined in FIPS 186-1 Sec3.2, and thus need to override this.
+ protected BigInteger generateK(BigInteger q) {
SecureRandom random = getSigningRandom();
+ byte[] kValue = new byte[q.bitLength()/8];
while (true) {
- int[] seed = new int[5];
-
- for (int i = 0; i < 5; i++)
- seed[i] = random.nextInt();
- k = generateK(seed, q);
+ random.nextBytes(kValue);
+ BigInteger k = new BigInteger(1, kValue).mod(q);
if (k.signum() > 0 && k.compareTo(q) < 0) {
- previousKseed = new int [seed.length];
- System.arraycopy(seed, 0, previousKseed, 0, seed.length);
return k;
}
}
@@ -435,7 +379,7 @@ abstract class DSA extends SignatureSpi {
// Use the application-specified SecureRandom Object if provided.
// Otherwise, use our default SecureRandom Object.
- private SecureRandom getSigningRandom() {
+ protected SecureRandom getSigningRandom() {
if (signingRandom == null) {
if (appRandom != null) {
signingRandom = appRandom;
@@ -446,171 +390,6 @@ abstract class DSA extends SignatureSpi {
return signingRandom;
}
- /**
- * 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.
- */
- private 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:
p
, in bits.
+ * @param valueL the size of p
, in bits.
+ * @param valueN the size of q
, in bits.
+ * @param seedLen the length of seed
, 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.
+ * at index 3.
*/
- BigInteger[] generatePandQ(byte[] seed, int L) {
+ private static BigInteger[] generatePandQ(SecureRandom random, int valueL,
+ int valueN, int seedLen) {
+ String hashAlg = null;
+ if (valueN == 160) {
+ hashAlg = "SHA";
+ } else if (valueN == 224) {
+ hashAlg = "SHA-224";
+ } else if (valueN == 256) {
+ hashAlg = "SHA-256";
+ }
+ MessageDigest hashObj = null;
+ try {
+ hashObj = MessageDigest.getInstance(hashAlg);
+ } catch (NoSuchAlgorithmException nsae) {
+ // should never happen
+ nsae.printStackTrace();
+ }
- /* Useful variables */
- int g = seed.length * 8;
- int n = (L - 1) / 160;
- int b = (L - 1) % 160;
+ /* Step 3, 4: Useful variables */
+ int outLen = hashObj.getDigestLength()*8;
+ int n = (valueL - 1) / outLen;
+ int b = (valueL - 1) % outLen;
+ byte[] seedBytes = new byte[seedLen/8];
+ BigInteger twoSl = TWO.pow(seedLen);
+ int primeCertainty = 80; // for 1024-bit prime P
+ if (valueL == 2048) {
+ primeCertainty = 112;
+ //} else if (valueL == 3072) {
+ // primeCertainty = 128;
+ }
- BigInteger SEED = new BigInteger(1, seed);
- BigInteger TWOG = TWO.pow(2 * g);
+ BigInteger resultP, resultQ, seed = null;
+ int counter;
+ while (true) {
+ do {
+ /* Step 5 */
+ random.nextBytes(seedBytes);
+ seed = new BigInteger(1, seedBytes);
- /* Step 2 (Step 1 is getting seed). */
- byte[] U1 = SHA(seed);
- byte[] U2 = SHA(toByteArray((SEED.add(ONE)).mod(TWOG)));
+ /* Step 6 */
+ BigInteger U = new BigInteger(1, hashObj.digest(seedBytes)).
+ mod(TWO.pow(valueN - 1));
- xor(U1, U2);
- byte[] U = U1;
+ /* Step 7 */
+ resultQ = TWO.pow(valueN - 1).add(U).add(ONE). subtract(U.mod(TWO));
+ } while (!resultQ.isProbablePrime(primeCertainty));
- /* 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(80)) {
- 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(80)) {
- BigInteger[] result = {p, q, SEED,
- BigInteger.valueOf(counter)};
- return result;
- }
- offset = offset.add(BigInteger.valueOf(n)).add(ONE);
+ /* Step 10 */
+ BigInteger offset = ONE;
+ /* Step 11 */
+ for (counter = 0; counter < 4*valueL; counter++) {
+ BigInteger V[] = new BigInteger[n + 1];
+ /* Step 11.1 */
+ for (int j = 0; j <= n; j++) {
+ BigInteger J = BigInteger.valueOf(j);
+ BigInteger tmp = (seed.add(offset).add(J)).mod(twoSl);
+ byte[] vjBytes = hashObj.digest(toByteArray(tmp));
+ V[j] = new BigInteger(1, vjBytes);
+ }
+ /* Step 11.2 */
+ BigInteger W = V[0];
+ for (int i = 1; i < n; i++) {
+ W = W.add(V[i].multiply(TWO.pow(i * outLen)));
+ }
+ W = W.add((V[n].mod(TWO.pow(b))).multiply(TWO.pow(n * outLen)));
+ /* Step 11.3 */
+ BigInteger twoLm1 = TWO.pow(valueL - 1);
+ BigInteger X = W.add(twoLm1);
+ /* Step 11.4, 11.5 */
+ BigInteger c = X.mod(resultQ.multiply(TWO));
+ resultP = X.subtract(c.subtract(ONE));
+ /* Step 11.6, 11.7 */
+ if (resultP.compareTo(twoLm1) > -1
+ && resultP.isProbablePrime(primeCertainty)) {
+ /* Step 11.8 */
+ BigInteger[] result = {resultP, resultQ, seed,
+ BigInteger.valueOf(counter)};
+ return result;
+ }
+ /* Step 11.9 */
+ offset = offset.add(BigInteger.valueOf(n)).add(ONE);
}
- return null;
- }
+ }
+
}
/*
@@ -262,31 +279,24 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
*
* @param the g
*/
- BigInteger generateG(BigInteger p, BigInteger q) {
+ private static BigInteger generateG(BigInteger p, BigInteger q) {
BigInteger h = ONE;
+ /* Step 1 */
BigInteger pMinusOneOverQ = (p.subtract(ONE)).divide(q);
- BigInteger g = ONE;
- while (g.compareTo(TWO) < 0) {
- g = h.modPow(pMinusOneOverQ, p);
+ BigInteger resultG = ONE;
+ while (resultG.compareTo(TWO) < 0) {
+ /* Step 3 */
+ resultG = 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();
+ return resultG;
}
/*
* Converts the result of a BigInteger.toByteArray call to an exact
* signed magnitude representation for any positive number.
*/
- private byte[] toByteArray(BigInteger bigInt) {
+ private static byte[] toByteArray(BigInteger bigInt) {
byte[] result = bigInt.toByteArray();
if (result[0] == 0) {
byte[] tmp = new byte[result.length - 1];
@@ -295,13 +305,4 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
}
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/jdk/src/share/classes/sun/security/provider/ParameterCache.java b/jdk/src/share/classes/sun/security/provider/ParameterCache.java
index f263fb7ea26..419bbd68522 100644
--- a/jdk/src/share/classes/sun/security/provider/ParameterCache.java
+++ b/jdk/src/share/classes/sun/security/provider/ParameterCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package sun.security.provider;
import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import java.math.BigInteger;
import java.security.*;
@@ -55,11 +56,17 @@ public final class ParameterCache {
private final static Map