changeset 8421:2e520074f7da

Merge
author andrew
date Thu, 14 Apr 2016 18:57:18 +0100
parents f9046a92fd12 34c594b52b73
children 900902aad468
files
diffstat 72 files changed, 3410 insertions(+), 1516 deletions(-) [+]
line wrap: on
line diff
--- a/make/sun/security/pkcs11/mapfile-vers	Fri Nov 27 10:59:49 2015 +0300
+++ b/make/sun/security/pkcs11/mapfile-vers	Thu Apr 14 18:57:18 2016 +0100
@@ -47,8 +47,8 @@
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession;
 #		Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo;
-#		Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState;
-#		Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState;
+		Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState;
+		Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout;
 		Java_sun_security_pkcs11_wrapper_PKCS11_C_1CreateObject;
--- a/src/share/classes/com/sun/crypto/provider/AESCipher.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/AESCipher.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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 @@
  * @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 @@
      */
     protected void engineInit(int opmode, Key key, SecureRandom random)
         throws InvalidKeyException {
+        checkKeySize(key, fixedKeySize);
         core.init(opmode, key, random);
     }
 
@@ -214,6 +319,7 @@
                               AlgorithmParameterSpec params,
                               SecureRandom random)
         throws InvalidKeyException, InvalidAlgorithmParameterException {
+        checkKeySize(key, fixedKeySize);
         core.init(opmode, key, params, random);
     }
 
@@ -221,6 +327,7 @@
                               AlgorithmParameters params,
                               SecureRandom random)
         throws InvalidKeyException, InvalidAlgorithmParameterException {
+        checkKeySize(key, fixedKeySize);
         core.init(opmode, key, params, random);
     }
 
--- a/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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 @@
  *
  * @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 @@
      */
     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 @@
             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());
     }
 
--- a/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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 @@
      * @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 @@
 
         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 @@
         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;
--- a/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -68,10 +68,10 @@
      * @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;
@@ -100,10 +100,10 @@
             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();
--- a/src/share/classes/com/sun/crypto/provider/HmacCore.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/HmacCore.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -38,16 +38,16 @@
  * This class constitutes the core of HMAC-<MD> algorithms, where
  * <MD> can be SHA1 or MD5, etc. See RFC 2104 for spec.
  *
- * It also contains the implementation classes for the SHA-256,
+ * It also contains the implementation classes for SHA-224, SHA-256,
  * SHA-384, and SHA-512 HMACs.
  *
  * @author Jan Luehe
  */
-final class HmacCore implements Cloneable {
+abstract class HmacCore extends MacSpi implements Cloneable {
 
-    private final MessageDigest md;
-    private final byte[] k_ipad; // inner padding - key XORd with ipad
-    private final byte[] k_opad; // outer padding - key XORd with opad
+    private MessageDigest md;
+    private byte[] k_ipad; // inner padding - key XORd with ipad
+    private byte[] k_opad; // outer padding - key XORd with opad
     private boolean first;       // Is this the first data to be processed?
 
     private final int blockLen;
@@ -73,22 +73,11 @@
     }
 
     /**
-     * Constructor used for cloning.
-     */
-    private HmacCore(HmacCore other) throws CloneNotSupportedException {
-        this.md = (MessageDigest)other.md.clone();
-        this.blockLen = other.blockLen;
-        this.k_ipad = (byte[])other.k_ipad.clone();
-        this.k_opad = (byte[])other.k_opad.clone();
-        this.first = other.first;
-    }
-
-    /**
      * Returns the length of the HMAC in bytes.
      *
      * @return the HMAC length in bytes.
      */
-    int getDigestLength() {
+    protected int engineGetMacLength() {
         return this.md.getDigestLength();
     }
 
@@ -103,9 +92,8 @@
      * @exception InvalidAlgorithmParameterException if the given algorithm
      * parameters are inappropriate for this MAC.
      */
-    void init(Key key, AlgorithmParameterSpec params)
+    protected void engineInit(Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
-
         if (params != null) {
             throw new InvalidAlgorithmParameterException
                 ("HMAC does not use parameters");
@@ -140,7 +128,7 @@
         Arrays.fill(secret, (byte)0);
         secret = null;
 
-        reset();
+        engineReset();
     }
 
     /**
@@ -148,7 +136,7 @@
      *
      * @param input the input byte to be processed.
      */
-    void update(byte input) {
+    protected void engineUpdate(byte input) {
         if (first == true) {
             // compute digest for 1st pass; start with inner pad
             md.update(k_ipad);
@@ -167,7 +155,7 @@
      * @param offset the offset in <code>input</code> where the input starts.
      * @param len the number of bytes to process.
      */
-    void update(byte input[], int offset, int len) {
+    protected void engineUpdate(byte input[], int offset, int len) {
         if (first == true) {
             // compute digest for 1st pass; start with inner pad
             md.update(k_ipad);
@@ -178,7 +166,13 @@
         md.update(input, offset, len);
     }
 
-    void update(ByteBuffer input) {
+    /**
+     * Processes the <code>input.remaining()</code> bytes in the ByteBuffer
+     * <code>input</code>.
+     *
+     * @param input the input byte buffer.
+     */
+    protected void engineUpdate(ByteBuffer input) {
         if (first == true) {
             // compute digest for 1st pass; start with inner pad
             md.update(k_ipad);
@@ -194,7 +188,7 @@
      *
      * @return the HMAC result.
      */
-    byte[] doFinal() {
+    protected byte[] engineDoFinal() {
         if (first == true) {
             // compute digest for 1st pass; start with inner pad
             md.update(k_ipad);
@@ -223,7 +217,7 @@
      * Resets the HMAC for further use, maintaining the secret key that the
      * HMAC was initialized with.
      */
-    void reset() {
+    protected void engineReset() {
         if (first == false) {
             md.reset();
             first = true;
@@ -234,115 +228,38 @@
      * Clones this object.
      */
     public Object clone() throws CloneNotSupportedException {
-        return new HmacCore(this);
+        HmacCore copy = (HmacCore) super.clone();
+        copy.md = (MessageDigest) md.clone();
+        copy.k_ipad = k_ipad.clone();
+        copy.k_opad = k_opad.clone();
+        return copy;
+    }
+
+    // nested static class for the HmacSHA224 implementation
+    public static final class HmacSHA224 extends HmacCore {
+        public HmacSHA224() throws NoSuchAlgorithmException {
+            super("SHA-224", 64);
+        }
     }
 
     // nested static class for the HmacSHA256 implementation
-    public static final class HmacSHA256 extends MacSpi implements Cloneable {
-        private final HmacCore core;
+    public static final class HmacSHA256 extends HmacCore {
         public HmacSHA256() throws NoSuchAlgorithmException {
-            core = new HmacCore("SHA-256", 64);
-        }
-        private HmacSHA256(HmacSHA256 base) throws CloneNotSupportedException {
-            core = (HmacCore)base.core.clone();
-        }
-        protected int engineGetMacLength() {
-            return core.getDigestLength();
-        }
-        protected void engineInit(Key key, AlgorithmParameterSpec params)
-                throws InvalidKeyException, InvalidAlgorithmParameterException {
-            core.init(key, params);
-        }
-        protected void engineUpdate(byte input) {
-            core.update(input);
-        }
-        protected void engineUpdate(byte input[], int offset, int len) {
-            core.update(input, offset, len);
-        }
-        protected void engineUpdate(ByteBuffer input) {
-            core.update(input);
-        }
-        protected byte[] engineDoFinal() {
-            return core.doFinal();
-        }
-        protected void engineReset() {
-            core.reset();
-        }
-        public Object clone() throws CloneNotSupportedException {
-            return new HmacSHA256(this);
+            super("SHA-256", 64);
         }
     }
 
     // nested static class for the HmacSHA384 implementation
-    public static final class HmacSHA384 extends MacSpi implements Cloneable {
-        private final HmacCore core;
+    public static final class HmacSHA384 extends HmacCore {
         public HmacSHA384() throws NoSuchAlgorithmException {
-            core = new HmacCore("SHA-384", 128);
-        }
-        private HmacSHA384(HmacSHA384 base) throws CloneNotSupportedException {
-            core = (HmacCore)base.core.clone();
-        }
-        protected int engineGetMacLength() {
-            return core.getDigestLength();
-        }
-        protected void engineInit(Key key, AlgorithmParameterSpec params)
-                throws InvalidKeyException, InvalidAlgorithmParameterException {
-            core.init(key, params);
-        }
-        protected void engineUpdate(byte input) {
-            core.update(input);
-        }
-        protected void engineUpdate(byte input[], int offset, int len) {
-            core.update(input, offset, len);
-        }
-        protected void engineUpdate(ByteBuffer input) {
-            core.update(input);
-        }
-        protected byte[] engineDoFinal() {
-            return core.doFinal();
-        }
-        protected void engineReset() {
-            core.reset();
-        }
-        public Object clone() throws CloneNotSupportedException {
-            return new HmacSHA384(this);
+            super("SHA-384", 128);
         }
     }
 
     // nested static class for the HmacSHA512 implementation
-    public static final class HmacSHA512 extends MacSpi implements Cloneable {
-        private final HmacCore core;
+    public static final class HmacSHA512 extends HmacCore {
         public HmacSHA512() throws NoSuchAlgorithmException {
-            core = new HmacCore("SHA-512", 128);
-        }
-        private HmacSHA512(HmacSHA512 base) throws CloneNotSupportedException {
-            core = (HmacCore)base.core.clone();
-        }
-        protected int engineGetMacLength() {
-            return core.getDigestLength();
-        }
-        protected void engineInit(Key key, AlgorithmParameterSpec params)
-                throws InvalidKeyException, InvalidAlgorithmParameterException {
-            core.init(key, params);
-        }
-        protected void engineUpdate(byte input) {
-            core.update(input);
-        }
-        protected void engineUpdate(byte input[], int offset, int len) {
-            core.update(input, offset, len);
-        }
-        protected void engineUpdate(ByteBuffer input) {
-            core.update(input);
-        }
-        protected byte[] engineDoFinal() {
-            return core.doFinal();
-        }
-        protected void engineReset() {
-            core.reset();
-        }
-        public Object clone() throws CloneNotSupportedException {
-            return new HmacSHA512(this);
+            super("SHA-512", 128);
         }
     }
-
 }
--- a/src/share/classes/com/sun/crypto/provider/HmacMD5.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/HmacMD5.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -37,97 +37,11 @@
  *
  * @author Jan Luehe
  */
-public final class HmacMD5 extends MacSpi implements Cloneable {
-
-    private HmacCore hmac;
-    private static final int MD5_BLOCK_LENGTH = 64;
-
+public final class HmacMD5 extends HmacCore {
     /**
      * Standard constructor, creates a new HmacMD5 instance.
      */
     public HmacMD5() throws NoSuchAlgorithmException {
-        hmac = new HmacCore(MessageDigest.getInstance("MD5"),
-                            MD5_BLOCK_LENGTH);
-    }
-
-    /**
-     * Returns the length of the HMAC in bytes.
-     *
-     * @return the HMAC length in bytes.
-     */
-    protected int engineGetMacLength() {
-        return hmac.getDigestLength();
-    }
-
-    /**
-     * Initializes the HMAC with the given secret key and algorithm parameters.
-     *
-     * @param key the secret key.
-     * @param params the algorithm parameters.
-     *
-     * @exception InvalidKeyException if the given key is inappropriate for
-     * initializing this MAC.
-     * @exception InvalidAlgorithmParameterException if the given algorithm
-     * parameters are inappropriate for this MAC.
-     */
-    protected void engineInit(Key key, AlgorithmParameterSpec params)
-        throws InvalidKeyException, InvalidAlgorithmParameterException {
-        hmac.init(key, params);
-    }
-
-    /**
-     * Processes the given byte.
-     *
-     * @param input the input byte to be processed.
-     */
-    protected void engineUpdate(byte input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Processes the first <code>len</code> bytes in <code>input</code>,
-     * starting at <code>offset</code>.
-     *
-     * @param input the input buffer.
-     * @param offset the offset in <code>input</code> where the input starts.
-     * @param len the number of bytes to process.
-     */
-    protected void engineUpdate(byte input[], int offset, int len) {
-        hmac.update(input, offset, len);
-    }
-
-    protected void engineUpdate(ByteBuffer input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Completes the HMAC computation and resets the HMAC for further use,
-     * maintaining the secret key that the HMAC was initialized with.
-     *
-     * @return the HMAC result.
-     */
-    protected byte[] engineDoFinal() {
-        return hmac.doFinal();
-    }
-
-    /**
-     * Resets the HMAC for further use, maintaining the secret key that the
-     * HMAC was initialized with.
-     */
-    protected void engineReset() {
-        hmac.reset();
-    }
-
-    /*
-     * Clones this object.
-     */
-    public Object clone() {
-        HmacMD5 that = null;
-        try {
-            that = (HmacMD5) super.clone();
-            that.hmac = (HmacCore) this.hmac.clone();
-        } catch (CloneNotSupportedException e) {
-        }
-        return that;
+        super("MD5", 64);
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, 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
@@ -41,26 +41,13 @@
  *
  * @author Valerie Peng
  */
-public final class HmacPKCS12PBESHA1 extends MacSpi implements Cloneable {
-
-    private HmacCore hmac = null;
-    private static final int SHA1_BLOCK_LENGTH = 64;
+public final class HmacPKCS12PBESHA1 extends HmacCore {
 
     /**
      * Standard constructor, creates a new HmacSHA1 instance.
      */
     public HmacPKCS12PBESHA1() throws NoSuchAlgorithmException {
-        this.hmac = new HmacCore(MessageDigest.getInstance("SHA1"),
-                                 SHA1_BLOCK_LENGTH);
-    }
-
-    /**
-     * Returns the length of the HMAC in bytes.
-     *
-     * @return the HMAC length in bytes.
-     */
-    protected int engineGetMacLength() {
-        return hmac.getDigestLength();
+        super("SHA1", 64);
     }
 
     /**
@@ -71,7 +58,7 @@
      *
      * @exception InvalidKeyException if the given key is inappropriate for
      * initializing this MAC.
-     u* @exception InvalidAlgorithmParameterException if the given algorithm
+     * @exception InvalidAlgorithmParameterException if the given algorithm
      * parameters are inappropriate for this MAC.
      */
     protected void engineInit(Key key, AlgorithmParameterSpec params)
@@ -140,64 +127,8 @@
                 ("IterationCount must be a positive number");
         }
         byte[] derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
-            iCount, hmac.getDigestLength(), PKCS12PBECipherCore.MAC_KEY);
+            iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY);
         SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
-        hmac.init(cipherKey, null);
-    }
-
-    /**
-     * Processes the given byte.
-     *
-     * @param input the input byte to be processed.
-     */
-    protected void engineUpdate(byte input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Processes the first <code>len</code> bytes in <code>input</code>,
-     * starting at <code>offset</code>.
-     *
-     * @param input the input buffer.
-     * @param offset the offset in <code>input</code> where the input starts.
-     * @param len the number of bytes to process.
-     */
-    protected void engineUpdate(byte input[], int offset, int len) {
-        hmac.update(input, offset, len);
-    }
-
-    protected void engineUpdate(ByteBuffer input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Completes the HMAC computation and resets the HMAC for further use,
-     * maintaining the secret key that the HMAC was initialized with.
-     *
-     * @return the HMAC result.
-     */
-    protected byte[] engineDoFinal() {
-        return hmac.doFinal();
-    }
-
-    /**
-     * Resets the HMAC for further use, maintaining the secret key that the
-     * HMAC was initialized with.
-     */
-    protected void engineReset() {
-        hmac.reset();
-    }
-
-    /*
-     * Clones this object.
-     */
-    public Object clone() {
-        HmacPKCS12PBESHA1 that = null;
-        try {
-            that = (HmacPKCS12PBESHA1)super.clone();
-            that.hmac = (HmacCore)this.hmac.clone();
-        } catch (CloneNotSupportedException e) {
-        }
-        return that;
+        super.engineInit(cipherKey, null);
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/HmacSHA1.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/HmacSHA1.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -37,97 +37,11 @@
  *
  * @author Jan Luehe
  */
-public final class HmacSHA1 extends MacSpi implements Cloneable {
-
-    private HmacCore hmac = null;
-    private static final int SHA1_BLOCK_LENGTH = 64;
-
+public final class HmacSHA1 extends HmacCore {
     /**
      * Standard constructor, creates a new HmacSHA1 instance.
      */
     public HmacSHA1() throws NoSuchAlgorithmException {
-        this.hmac = new HmacCore(MessageDigest.getInstance("SHA1"),
-                                 SHA1_BLOCK_LENGTH);
-    }
-
-    /**
-     * Returns the length of the HMAC in bytes.
-     *
-     * @return the HMAC length in bytes.
-     */
-    protected int engineGetMacLength() {
-        return hmac.getDigestLength();
-    }
-
-    /**
-     * Initializes the HMAC with the given secret key and algorithm parameters.
-     *
-     * @param key the secret key.
-     * @param params the algorithm parameters.
-     *
-     * @exception InvalidKeyException if the given key is inappropriate for
-     * initializing this MAC.
-     * @exception InvalidAlgorithmParameterException if the given algorithm
-     * parameters are inappropriate for this MAC.
-     */
-    protected void engineInit(Key key, AlgorithmParameterSpec params)
-        throws InvalidKeyException, InvalidAlgorithmParameterException {
-        hmac.init(key, params);
-    }
-
-    /**
-     * Processes the given byte.
-     *
-     * @param input the input byte to be processed.
-     */
-    protected void engineUpdate(byte input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Processes the first <code>len</code> bytes in <code>input</code>,
-     * starting at <code>offset</code>.
-     *
-     * @param input the input buffer.
-     * @param offset the offset in <code>input</code> where the input starts.
-     * @param len the number of bytes to process.
-     */
-    protected void engineUpdate(byte input[], int offset, int len) {
-        hmac.update(input, offset, len);
-    }
-
-    protected void engineUpdate(ByteBuffer input) {
-        hmac.update(input);
-    }
-
-    /**
-     * Completes the HMAC computation and resets the HMAC for further use,
-     * maintaining the secret key that the HMAC was initialized with.
-     *
-     * @return the HMAC result.
-     */
-    protected byte[] engineDoFinal() {
-        return hmac.doFinal();
-    }
-
-    /**
-     * Resets the HMAC for further use, maintaining the secret key that the
-     * HMAC was initialized with.
-     */
-    protected void engineReset() {
-        hmac.reset();
-    }
-
-    /*
-     * Clones this object.
-     */
-    public Object clone() {
-        HmacSHA1 that = null;
-        try {
-            that = (HmacSHA1)super.clone();
-            that.hmac = (HmacCore)this.hmac.clone();
-        } catch (CloneNotSupportedException e) {
-        }
-        return that;
+        super("SHA1", 64);
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, 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
@@ -105,11 +105,11 @@
         return new SecretKeySpec(b, name);
     }
 
-    // nested static class for the HmacSHA256 key generator
-    public static final class HmacSHA256KG extends KeyGeneratorSpi {
+    // nested static classes for the HmacSHA-2 family of key generator
+    abstract static class HmacSHA2KG extends KeyGeneratorSpi {
         private final KeyGeneratorCore core;
-        public HmacSHA256KG() {
-            core = new KeyGeneratorCore("HmacSHA256", 256);
+        protected HmacSHA2KG(String algoName, int len) {
+            core = new KeyGeneratorCore(algoName, len);
         }
         protected void engineInit(SecureRandom random) {
             core.implInit(random);
@@ -124,47 +124,26 @@
         protected SecretKey engineGenerateKey() {
             return core.implGenerateKey();
         }
-    }
 
-    // nested static class for the HmacSHA384 key generator
-    public static final class HmacSHA384KG extends KeyGeneratorSpi {
-        private final KeyGeneratorCore core;
-        public HmacSHA384KG() {
-            core = new KeyGeneratorCore("HmacSHA384", 384);
+        public static final class SHA224 extends HmacSHA2KG {
+            public SHA224() {
+                super("HmacSHA224", 224);
+            }
         }
-        protected void engineInit(SecureRandom random) {
-            core.implInit(random);
+        public static final class SHA256 extends HmacSHA2KG {
+            public SHA256() {
+                super("HmacSHA256", 256);
+            }
         }
-        protected void engineInit(AlgorithmParameterSpec params,
-                SecureRandom random) throws InvalidAlgorithmParameterException {
-            core.implInit(params, random);
+        public static final class SHA384 extends HmacSHA2KG {
+            public SHA384() {
+                super("HmacSHA384", 384);
+            }
         }
-        protected void engineInit(int keySize, SecureRandom random) {
-            core.implInit(keySize, random);
-        }
-        protected SecretKey engineGenerateKey() {
-            return core.implGenerateKey();
-        }
-    }
-
-    // nested static class for the HmacSHA384 key generator
-    public static final class HmacSHA512KG extends KeyGeneratorSpi {
-        private final KeyGeneratorCore core;
-        public HmacSHA512KG() {
-            core = new KeyGeneratorCore("HmacSHA512", 512);
-        }
-        protected void engineInit(SecureRandom random) {
-            core.implInit(random);
-        }
-        protected void engineInit(AlgorithmParameterSpec params,
-                SecureRandom random) throws InvalidAlgorithmParameterException {
-            core.implInit(params, random);
-        }
-        protected void engineInit(int keySize, SecureRandom random) {
-            core.implInit(keySize, random);
-        }
-        protected SecretKey engineGenerateKey() {
-            return core.implGenerateKey();
+        public static final class SHA512 extends HmacSHA2KG {
+            public SHA512() {
+                super("HmacSHA512", 512);
+            }
         }
     }
 
--- a/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/OAEPParameters.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -131,6 +131,8 @@
                         params.getName());
                 if (mgfDigestName.equals("SHA-1")) {
                     mgfSpec = MGF1ParameterSpec.SHA1;
+                } else if (mgfDigestName.equals("SHA-224")) {
+                    mgfSpec = new MGF1ParameterSpec("SHA-224");
                 } else if (mgfDigestName.equals("SHA-256")) {
                     mgfSpec = MGF1ParameterSpec.SHA256;
                 } else if (mgfDigestName.equals("SHA-384")) {
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, 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
@@ -70,7 +70,7 @@
  *
  * - Diffie-Hellman Key Agreement
  *
- * - HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512
+ * - HMAC-MD5, HMAC-SHA1, HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512
  *
  */
 
@@ -117,6 +117,7 @@
                         "NOPADDING|PKCS1PADDING|OAEPWITHMD5ANDMGF1PADDING"
                         + "|OAEPWITHSHA1ANDMGF1PADDING"
                         + "|OAEPWITHSHA-1ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-224ANDMGF1PADDING"
                         + "|OAEPWITHSHA-256ANDMGF1PADDING"
                         + "|OAEPWITHSHA-384ANDMGF1PADDING"
                         + "|OAEPWITHSHA-512ANDMGF1PADDING");
@@ -170,17 +171,67 @@
                 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);
@@ -195,7 +246,7 @@
                 put("Cipher.ARCFOUR SupportedKeyFormats", "RAW");
 
                 /*
-                 *  Key(pair) Generator engines
+                 * Key(pair) Generator engines
                  */
                 put("KeyGenerator.DES",
                     "com.sun.crypto.provider.DESKeyGenerator");
@@ -224,13 +275,28 @@
 
                 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");
+                put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.8", "HmacSHA224");
+                put("Alg.Alias.KeyGenerator.1.2.840.113549.2.8", "HmacSHA224");
 
                 put("KeyGenerator.HmacSHA256",
-                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA256KG");
+                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA256");
+                put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.9", "HmacSHA256");
+                put("Alg.Alias.KeyGenerator.1.2.840.113549.2.9", "HmacSHA256");
+
                 put("KeyGenerator.HmacSHA384",
-                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA384KG");
+                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA384");
+                put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.10", "HmacSHA384");
+                put("Alg.Alias.KeyGenerator.1.2.840.113549.2.10", "HmacSHA384");
+
                 put("KeyGenerator.HmacSHA512",
-                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA512KG");
+                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA512");
+                put("Alg.Alias.KeyGenerator.OID.1.2.840.113549.2.11", "HmacSHA512");
+                put("Alg.Alias.KeyGenerator.1.2.840.113549.2.11", "HmacSHA512");
 
                 put("KeyPairGenerator.DiffieHellman",
                     "com.sun.crypto.provider.DHKeyPairGenerator");
@@ -316,14 +382,12 @@
                     "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
                  */
@@ -393,12 +457,25 @@
                  */
                 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");
+                put("Alg.Alias.Mac.1.2.840.113549.2.8", "HmacSHA224");
                 put("Mac.HmacSHA256",
                     "com.sun.crypto.provider.HmacCore$HmacSHA256");
+                put("Alg.Alias.Mac.OID.1.2.840.113549.2.9", "HmacSHA256");
+                put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
                 put("Mac.HmacSHA384",
                     "com.sun.crypto.provider.HmacCore$HmacSHA384");
+                put("Alg.Alias.Mac.OID.1.2.840.113549.2.10", "HmacSHA384");
+                put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
                 put("Mac.HmacSHA512",
                     "com.sun.crypto.provider.HmacCore$HmacSHA512");
+                put("Alg.Alias.Mac.OID.1.2.840.113549.2.11", "HmacSHA512");
+                put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
+
                 put("Mac.HmacPBESHA1",
                     "com.sun.crypto.provider.HmacPKCS12PBESHA1");
 
@@ -409,6 +486,7 @@
 
                 put("Mac.HmacMD5 SupportedKeyFormats", "RAW");
                 put("Mac.HmacSHA1 SupportedKeyFormats", "RAW");
+                put("Mac.HmacSHA224 SupportedKeyFormats", "RAW");
                 put("Mac.HmacSHA256 SupportedKeyFormats", "RAW");
                 put("Mac.HmacSHA384 SupportedKeyFormats", "RAW");
                 put("Mac.HmacSHA512 SupportedKeyFormats", "RAW");
--- a/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -241,14 +241,29 @@
         int off = secret.length >> 1;
         int seclen = off + (secret.length & 1);
 
+        byte[] secKey = secret;
+        int keyLen = seclen;
         byte[] output = new byte[outputLength];
 
         // P_MD5(S1, label + seed)
-        expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
+        // If we have a long secret, digest it first.
+        if (seclen > 64) {              // 64: block size of HMAC-MD5
+            md5.update(secret, 0, seclen);
+            secKey = md5.digest();
+            keyLen = secKey.length;
+        }
+        expand(md5, 16, secKey, 0, keyLen, labelBytes, seed, output,
             HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         // P_SHA-1(S2, label + seed)
-        expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
+        // If we have a long secret, digest it first.
+        if (seclen > 64) {              // 64: block size of HMAC-SHA1
+            sha.update(secret, off, seclen);
+            secKey = sha.digest();
+            keyLen = secKey.length;
+            off = 0;
+        }
+        expand(sha, 20, secKey, off, keyLen, labelBytes, seed, output,
             HMAC_ipad64.clone(), HMAC_opad64.clone());
 
         return output;
--- a/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/java/security/interfaces/DSAKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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 @@
  * interface is all that is needed when you accept defaults for algorithm-specific
  * parameters.
  *
+ * <p>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 @@
      * can be null.
      *
      * @exception InvalidParameterException if the <code>params</code>
-     * value is invalid or null.
+     * value is invalid, null, or unsupported.
      */
    public void initialize(DSAParams params, SecureRandom random)
    throws InvalidParameterException;
@@ -97,7 +100,7 @@
      * 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 @@
      * @param genParams whether or not to generate new parameters for
      * the modulus length requested.
      *
-     * @exception InvalidParameterException if <code>modlen</code> is not
-     * between 512 and 1024, or if <code>genParams</code> is false and
-     * there are no precomputed parameters for the requested modulus
-     * length.
+     * @exception InvalidParameterException if <code>modlen</code> is
+     * invalid, or unsupported, or if <code>genParams</code> is false and there
+     * are no precomputed parameters for the requested modulus length.
      */
     public void initialize(int modlen, boolean genParams, SecureRandom random)
     throws InvalidParameterException;
--- a/src/share/classes/java/security/spec/MGF1ParameterSpec.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/java/security/spec/MGF1ParameterSpec.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, 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
@@ -42,6 +42,7 @@
  * <pre>
  * OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
  *   { OID id-sha1 PARAMETERS NULL   }|
+ *   { OID id-sha224 PARAMETERS NULL   }|
  *   { OID id-sha256 PARAMETERS NULL }|
  *   { OID id-sha384 PARAMETERS NULL }|
  *   { OID id-sha512 PARAMETERS NULL },
--- a/src/share/classes/java/security/spec/PSSParameterSpec.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/java/security/spec/PSSParameterSpec.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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,6 +47,7 @@
  * <pre>
  * OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
  *   { OID id-sha1 PARAMETERS NULL   }|
+ *   { OID id-sha224 PARAMETERS NULL   }|
  *   { OID id-sha256 PARAMETERS NULL }|
  *   { OID id-sha384 PARAMETERS NULL }|
  *   { OID id-sha512 PARAMETERS NULL },
--- a/src/share/classes/sun/security/ec/ECDSASignature.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/ec/ECDSASignature.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -44,6 +44,7 @@
  *
  *   . "NONEwithECDSA"
  *   . "SHA1withECDSA"
+ *   . "SHA224withECDSA"
  *   . "SHA256withECDSA"
  *   . "SHA384withECDSA"
  *   . "SHA512withECDSA"
@@ -165,6 +166,13 @@
         }
     }
 
+    // Nested class for SHA224withECDSA signatures
+    public static final class SHA224 extends ECDSASignature {
+        public SHA224() {
+           super("SHA-224");
+        }
+    }
+
     // Nested class for SHA256withECDSA signatures
     public static final class SHA256 extends ECDSASignature {
         public SHA256() {
--- a/src/share/classes/sun/security/ec/SunECEntries.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/ec/SunECEntries.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -133,17 +133,34 @@
             "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");
+        map.put("Alg.Alias.Signature.1.2.840.10045.4.3.1", "SHA224withECDSA");
+
         map.put("Signature.SHA256withECDSA",
             "sun.security.ec.ECDSASignature$SHA256");
+        map.put("Alg.Alias.Signature.OID.1.2.840.10045.4.3.2", "SHA256withECDSA");
+        map.put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
+
         map.put("Signature.SHA384withECDSA",
             "sun.security.ec.ECDSASignature$SHA384");
+        map.put("Alg.Alias.Signature.OID.1.2.840.10045.4.3.3", "SHA384withECDSA");
+        map.put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
+
         map.put("Signature.SHA512withECDSA",
             "sun.security.ec.ECDSASignature$SHA512");
+        map.put("Alg.Alias.Signature.OID.1.2.840.10045.4.3.4", "SHA512withECDSA");
+        map.put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
 
         String ecKeyClasses = "java.security.interfaces.ECPublicKey" +
                 "|java.security.interfaces.ECPrivateKey";
         map.put("Signature.NONEwithECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA1withECDSA SupportedKeyClasses", ecKeyClasses);
+        map.put("Signature.SHA224withECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA256withECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses);
@@ -152,6 +169,7 @@
 
         map.put("Signature.NONEwithECDSA ImplementedIn", "Software");
         map.put("Signature.SHA1withECDSA ImplementedIn", "Software");
+        map.put("Signature.SHA224withECDSA ImplementedIn", "Software");
         map.put("Signature.SHA256withECDSA ImplementedIn", "Software");
         map.put("Signature.SHA384withECDSA ImplementedIn", "Software");
         map.put("Signature.SHA512withECDSA ImplementedIn", "Software");
--- a/src/share/classes/sun/security/pkcs11/P11Cipher.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/P11Cipher.java	Thu Apr 14 18:57:18 2016 +0100
@@ -165,6 +165,10 @@
     // 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();
@@ -173,19 +177,26 @@
         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;
+            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);
         }
-        this.blockMode =
-                (algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
-
         String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
         String paddingStr =
                 (algoParts.length > 2 ? algoParts[2] : defPadding);
@@ -334,6 +345,9 @@
             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;
--- a/src/share/classes/sun/security/pkcs11/P11Digest.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/P11Digest.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -39,7 +39,7 @@
 
 /**
  * MessageDigest implementation class. This class currently supports
- * MD2, MD5, SHA-1, SHA-256, SHA-384, and SHA-512.
+ * MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
  *
  * Note that many digest operations are on fairly small amounts of data
  * (less than 100 bytes total). For example, the 2nd hashing in HMAC or
@@ -49,13 +49,12 @@
  * @author  Andreas Sterbenz
  * @since   1.5
  */
-final class P11Digest extends MessageDigestSpi {
+final class P11Digest extends MessageDigestSpi implements Cloneable {
 
-    /* unitialized, fields uninitialized, no session acquired */
+    /* fields initialized, no session acquired */
     private final static int S_BLANK    = 1;
 
-    // data in buffer, all fields valid, session acquired
-    // but digest not initialized
+    /* data in buffer, session acquired, but digest not initialized */
     private final static int S_BUFFERED = 2;
 
     /* session initialized for digesting */
@@ -69,8 +68,8 @@
     // algorithm name
     private final String algorithm;
 
-    // mechanism id
-    private final long mechanism;
+    // mechanism id object
+    private final CK_MECHANISM mechanism;
 
     // length of the digest in bytes
     private final int digestLength;
@@ -81,11 +80,8 @@
     // current state, one of S_* above
     private int state;
 
-    // one byte buffer for the update(byte) method, initialized on demand
-    private byte[] oneByte;
-
     // buffer to reduce number of JNI calls
-    private final byte[] buffer;
+    private byte[] buffer;
 
     // offset into the buffer
     private int bufOfs;
@@ -94,7 +90,7 @@
         super();
         this.token = token;
         this.algorithm = algorithm;
-        this.mechanism = mechanism;
+        this.mechanism = new CK_MECHANISM(mechanism);
         switch ((int)mechanism) {
         case (int)CKM_MD2:
         case (int)CKM_MD5:
@@ -103,6 +99,9 @@
         case (int)CKM_SHA_1:
             digestLength = 20;
             break;
+        case (int)CKM_SHA224:
+            digestLength = 28;
+            break;
         case (int)CKM_SHA256:
             digestLength = 32;
             break;
@@ -117,7 +116,6 @@
         }
         buffer = new byte[BUFFER_SIZE];
         state = S_BLANK;
-        engineReset();
     }
 
     // see JCA spec
@@ -125,44 +123,31 @@
         return digestLength;
     }
 
-    private void cancelOperation() {
-        token.ensureValid();
-        if (session == null) {
-            return;
-        }
-        if ((state != S_INIT) || (token.explicitCancel == false)) {
-            return;
-        }
-        // need to explicitly "cancel" active op by finishing it
-        try {
-            token.p11.C_DigestFinal(session.id(), buffer, 0, buffer.length);
-        } catch (PKCS11Exception e) {
-            throw new ProviderException("cancel() failed", e);
-        } finally {
-            state = S_BUFFERED;
-        }
-    }
-
     private void fetchSession() {
         token.ensureValid();
         if (state == S_BLANK) {
-            engineReset();
+            try {
+                session = token.getOpSession();
+                state = S_BUFFERED;
+            } catch (PKCS11Exception e) {
+                throw new ProviderException("No more session available", e);
+            }
         }
     }
 
     // see JCA spec
     protected void engineReset() {
-        try {
-            cancelOperation();
-            bufOfs = 0;
-            if (session == null) {
-                session = token.getOpSession();
+        token.ensureValid();
+
+        if (session != null) {
+            if (state == S_INIT && token.explicitCancel == true) {
+                session = token.killSession(session);
+            } else {
+                session = token.releaseSession(session);
             }
-            state = S_BUFFERED;
-        } catch (PKCS11Exception e) {
-            state = S_BLANK;
-            throw new ProviderException("reset() failed, ", e);
         }
+        state = S_BLANK;
+        bufOfs = 0;
     }
 
     // see JCA spec
@@ -180,18 +165,22 @@
     protected int engineDigest(byte[] digest, int ofs, int len)
             throws DigestException {
         if (len < digestLength) {
-            throw new DigestException("Length must be at least " + digestLength);
+            throw new DigestException("Length must be at least " +
+                    digestLength);
         }
+
         fetchSession();
         try {
             int n;
             if (state == S_BUFFERED) {
-                n = token.p11.C_DigestSingle(session.id(),
-                        new CK_MECHANISM(mechanism),
-                        buffer, 0, bufOfs, digest, ofs, len);
+                n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0,
+                        bufOfs, digest, ofs, len);
+                bufOfs = 0;
             } else {
                 if (bufOfs != 0) {
-                    doUpdate(buffer, 0, bufOfs);
+                    token.p11.C_DigestUpdate(session.id(), 0, buffer, 0,
+                            bufOfs);
+                    bufOfs = 0;
                 }
                 n = token.p11.C_DigestFinal(session.id(), digest, ofs, len);
             }
@@ -202,36 +191,44 @@
         } catch (PKCS11Exception e) {
             throw new ProviderException("digest() failed", e);
         } finally {
-            state = S_BLANK;
-            bufOfs = 0;
-            session = token.releaseSession(session);
+            engineReset();
         }
     }
 
     // see JCA spec
     protected void engineUpdate(byte in) {
-        if (oneByte == null) {
-            oneByte = new byte[1];
-        }
-        oneByte[0] = in;
-        engineUpdate(oneByte, 0, 1);
+        byte[] temp = { in };
+        engineUpdate(temp, 0, 1);
     }
 
     // see JCA spec
     protected void engineUpdate(byte[] in, int ofs, int len) {
-        fetchSession();
         if (len <= 0) {
             return;
         }
-        if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {
-            doUpdate(buffer, 0, bufOfs);
-            bufOfs = 0;
-        }
-        if (bufOfs + len > buffer.length) {
-            doUpdate(in, ofs, len);
-        } else {
-            System.arraycopy(in, ofs, buffer, bufOfs, len);
-            bufOfs += len;
+
+        fetchSession();
+        try {
+            if (state == S_BUFFERED) {
+                token.p11.C_DigestInit(session.id(), mechanism);
+                state = S_INIT;
+            }
+            if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {
+                // process the buffered data
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
+            }
+            if (bufOfs + len > buffer.length) {
+                // process the new data
+                token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);
+             } else {
+                // buffer the new data
+                System.arraycopy(in, ofs, buffer, bufOfs, len);
+                bufOfs += len;
+            }
+        } catch (PKCS11Exception e) {
+            engineReset();
+            throw new ProviderException("update() failed", e);
         }
     }
 
@@ -239,11 +236,7 @@
     // the master secret is sensitive. We may want to consider making this
     // method public in a future release.
     protected void implUpdate(SecretKey key) throws InvalidKeyException {
-        fetchSession();
-        if (bufOfs != 0) {
-            doUpdate(buffer, 0, bufOfs);
-            bufOfs = 0;
-        }
+
         // SunJSSE calls this method only if the key does not have a RAW
         // encoding, i.e. if it is sensitive. Therefore, no point in calling
         // SecretKeyFactory to try to convert it. Just verify it ourselves.
@@ -252,60 +245,77 @@
         }
         P11Key p11Key = (P11Key)key;
         if (p11Key.token != token) {
-            throw new InvalidKeyException("Not a P11Key of this provider: " + key);
+            throw new InvalidKeyException("Not a P11Key of this provider: " +
+                    key);
         }
+
+        fetchSession();
         try {
             if (state == S_BUFFERED) {
-                token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism));
+                token.p11.C_DigestInit(session.id(), mechanism);
                 state = S_INIT;
             }
+
+            if (bufOfs != 0) {
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
+            }
             token.p11.C_DigestKey(session.id(), p11Key.keyID);
         } catch (PKCS11Exception e) {
+            engineReset();
             throw new ProviderException("update(SecretKey) failed", e);
         }
     }
 
     // see JCA spec
     protected void engineUpdate(ByteBuffer byteBuffer) {
-        fetchSession();
         int len = byteBuffer.remaining();
         if (len <= 0) {
             return;
         }
+
         if (byteBuffer instanceof DirectBuffer == false) {
             super.engineUpdate(byteBuffer);
             return;
         }
+
+        fetchSession();
         long addr = ((DirectBuffer)byteBuffer).address();
         int ofs = byteBuffer.position();
         try {
             if (state == S_BUFFERED) {
-                token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism));
+                token.p11.C_DigestInit(session.id(), mechanism);
                 state = S_INIT;
-                if (bufOfs != 0) {
-                    doUpdate(buffer, 0, bufOfs);
-                    bufOfs = 0;
-                }
+            }
+            if (bufOfs != 0) {
+                token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
+                bufOfs = 0;
             }
             token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len);
             byteBuffer.position(ofs + len);
         } catch (PKCS11Exception e) {
+            engineReset();
             throw new ProviderException("update() failed", e);
         }
     }
 
-    private void doUpdate(byte[] in, int ofs, int len) {
-        if (len <= 0) {
-            return;
+    public Object clone() throws CloneNotSupportedException {
+        P11Digest copy = (P11Digest) super.clone();
+        copy.buffer = buffer.clone();
+        try {
+            if (session != null) {
+                copy.session = copy.token.getOpSession();
+            }
+            if (state == S_INIT) {
+                byte[] stateValues =
+                    token.p11.C_GetOperationState(session.id());
+                token.p11.C_SetOperationState(copy.session.id(),
+                                              stateValues, 0, 0);
+            }
+        } catch (PKCS11Exception e) {
+            throw (CloneNotSupportedException)
+                (new CloneNotSupportedException(algorithm).initCause(e));
         }
-        try {
-            if (state == S_BUFFERED) {
-                token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism));
-                state = S_INIT;
-            }
-            token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);
-        } catch (PKCS11Exception e) {
-            throw new ProviderException("update() failed", e);
-        }
+        return copy;
     }
 }
--- a/src/share/classes/sun/security/pkcs11/P11Mac.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/P11Mac.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -40,8 +40,8 @@
 
 /**
  * MAC implementation class. This class currently supports HMAC using
- * MD5, SHA-1, SHA-256, SHA-384, and SHA-512 and the SSL3 MAC using MD5
- * and SHA-1.
+ * MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 and the SSL3 MAC
+ * using MD5 and SHA-1.
  *
  * Note that unlike other classes (e.g. Signature), this does not
  * composite various operations if the token only supports part of the
@@ -107,6 +107,9 @@
         case (int)CKM_SHA_1_HMAC:
             macLength = 20;
             break;
+        case (int)CKM_SHA224_HMAC:
+            macLength = 28;
+            break;
         case (int)CKM_SHA256_HMAC:
             macLength = 32;
             break;
--- a/src/share/classes/sun/security/pkcs11/P11Signature.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/P11Signature.java	Thu Apr 14 18:57:18 2016 +0100
@@ -54,12 +54,14 @@
  *   . MD2withRSA
  *   . MD5withRSA
  *   . SHA1withRSA
+ *   . SHA224withRSA
  *   . SHA256withRSA
  *   . SHA384withRSA
  *   . SHA512withRSA
  * . ECDSA
  *   . NONEwithECDSA
  *   . SHA1withECDSA
+ *   . SHA224withECDSA
  *   . SHA256withECDSA
  *   . SHA384withECDSA
  *   . SHA512withECDSA
@@ -144,6 +146,7 @@
         case (int)CKM_MD2_RSA_PKCS:
         case (int)CKM_MD5_RSA_PKCS:
         case (int)CKM_SHA1_RSA_PKCS:
+        case (int)CKM_SHA224_RSA_PKCS:
         case (int)CKM_SHA256_RSA_PKCS:
         case (int)CKM_SHA384_RSA_PKCS:
         case (int)CKM_SHA512_RSA_PKCS:
@@ -182,6 +185,8 @@
                 String digestAlg;
                 if (algorithm.equals("SHA1withECDSA")) {
                     digestAlg = "SHA-1";
+                } else if (algorithm.equals("SHA224withECDSA")) {
+                    digestAlg = "SHA-224";
                 } else if (algorithm.equals("SHA256withECDSA")) {
                     digestAlg = "SHA-256";
                 } else if (algorithm.equals("SHA384withECDSA")) {
@@ -208,6 +213,9 @@
             } else if (algorithm.equals("MD2withRSA")) {
                 md = MessageDigest.getInstance("MD2");
                 digestOID = AlgorithmId.MD2_oid;
+            } else if (algorithm.equals("SHA224withRSA")) {
+                md = MessageDigest.getInstance("SHA-224");
+                digestOID = AlgorithmId.SHA224_oid;
             } else if (algorithm.equals("SHA256withRSA")) {
                 md = MessageDigest.getInstance("SHA-256");
                 digestOID = AlgorithmId.SHA256_oid;
@@ -333,6 +341,8 @@
             encodedLength = 34;
         } else if (algorithm.equals("SHA1withRSA")) {
             encodedLength = 35;
+        } else if (algorithm.equals("SHA224withRSA")) {
+            encodedLength = 47;
         } else if (algorithm.equals("SHA256withRSA")) {
             encodedLength = 51;
         } else if (algorithm.equals("SHA384withRSA")) {
--- a/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Thu Apr 14 18:57:18 2016 +0100
@@ -343,6 +343,7 @@
                 System.out.println("Library info:");
                 System.out.println(p11Info);
             }
+
             if ((slotID < 0) || showInfo) {
                 long[] slots = p11.C_GetSlotList(false);
                 if (showInfo) {
@@ -399,12 +400,8 @@
         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,24 +518,39 @@
                 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,
+                s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"),
+                m(CKM_SHA224));
         d(MD, "SHA-256",        P11Digest,
+                s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"),
                 m(CKM_SHA256));
         d(MD, "SHA-384",        P11Digest,
+                s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"),
                 m(CKM_SHA384));
         d(MD, "SHA-512",        P11Digest,
+                s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"),
                 m(CKM_SHA512));
 
         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"),
+                m(CKM_SHA224_HMAC));
         d(MAC, "HmacSHA256",    P11MAC,
+                s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"),
                 m(CKM_SHA256_HMAC));
         d(MAC, "HmacSHA384",    P11MAC,
+                s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"),
                 m(CKM_SHA384_HMAC));
         d(MAC, "HmacSHA512",    P11MAC,
+                s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"),
                 m(CKM_SHA512_HMAC));
         d(MAC, "SslMacMD5",     P11MAC,
                 m(CKM_SSL3_MD5_MAC));
@@ -548,6 +560,7 @@
         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));
@@ -570,6 +583,7 @@
         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));
@@ -596,6 +610,7 @@
         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));
@@ -621,10 +636,28 @@
                 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,
@@ -640,31 +673,50 @@
         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"),
+                m(CKM_ECDSA));
         d(SIG, "SHA256withECDSA",       P11Signature,
+                s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"),
                 m(CKM_ECDSA));
         d(SIG, "SHA384withECDSA",       P11Signature,
+                s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"),
                 m(CKM_ECDSA));
         d(SIG, "SHA512withECDSA",       P11Signature,
+                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"),
+                m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
         d(SIG, "SHA256withRSA", P11Signature,
+                s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"),
                 m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
         d(SIG, "SHA384withRSA", P11Signature,
+                s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"),
                 m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
         d(SIG, "SHA512withRSA", P11Signature,
+                s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"),
                 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
 
         /*
--- a/src/share/classes/sun/security/pkcs11/wrapper/Functions.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/wrapper/Functions.java	Thu Apr 14 18:57:18 2016 +0100
@@ -614,6 +614,7 @@
         addMech(CKM_X9_42_DH_DERIVE,            "CKM_X9_42_DH_DERIVE");
         addMech(CKM_X9_42_DH_HYBRID_DERIVE,     "CKM_X9_42_DH_HYBRID_DERIVE");
         addMech(CKM_X9_42_MQV_DERIVE,           "CKM_X9_42_MQV_DERIVE");
+        addMech(CKM_SHA224_RSA_PKCS,            "CKM_SHA224_RSA_PKCS");
         addMech(CKM_SHA256_RSA_PKCS,            "CKM_SHA256_RSA_PKCS");
         addMech(CKM_SHA384_RSA_PKCS,            "CKM_SHA384_RSA_PKCS");
         addMech(CKM_SHA512_RSA_PKCS,            "CKM_SHA512_RSA_PKCS");
@@ -659,6 +660,9 @@
         addMech(CKM_RIPEMD160,                  "CKM_RIPEMD160");
         addMech(CKM_RIPEMD160_HMAC,             "CKM_RIPEMD160_HMAC");
         addMech(CKM_RIPEMD160_HMAC_GENERAL,     "CKM_RIPEMD160_HMAC_GENERAL");
+        addMech(CKM_SHA224,                     "CKM_SHA224");
+        addMech(CKM_SHA224_HMAC,                "CKM_SHA224_HMAC");
+        addMech(CKM_SHA224_HMAC_GENERAL,        "CKM_SHA224_HMAC_GENERAL");
         addMech(CKM_SHA256,                     "CKM_SHA256");
         addMech(CKM_SHA256_HMAC,                "CKM_SHA256_HMAC");
         addMech(CKM_SHA256_HMAC_GENERAL,        "CKM_SHA256_HMAC_GENERAL");
@@ -718,6 +722,7 @@
         addMech(CKM_MD5_KEY_DERIVATION,         "CKM_MD5_KEY_DERIVATION");
         addMech(CKM_MD2_KEY_DERIVATION,         "CKM_MD2_KEY_DERIVATION");
         addMech(CKM_SHA1_KEY_DERIVATION,        "CKM_SHA1_KEY_DERIVATION");
+        addMech(CKM_SHA224_KEY_DERIVATION,      "CKM_SHA224_KEY_DERIVATION");
         addMech(CKM_SHA256_KEY_DERIVATION,      "CKM_SHA256_KEY_DERIVATION");
         addMech(CKM_SHA384_KEY_DERIVATION,      "CKM_SHA384_KEY_DERIVATION");
         addMech(CKM_SHA512_KEY_DERIVATION,      "CKM_SHA512_KEY_DERIVATION");
--- a/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -133,14 +133,15 @@
      * @preconditions (pkcs11ModulePath <> null)
      * @postconditions
      */
-    PKCS11(String pkcs11ModulePath, String functionListName) throws IOException {
+    PKCS11(String pkcs11ModulePath, String functionListName)
+            throws IOException {
         connect(pkcs11ModulePath, functionListName);
         this.pkcs11ModulePath = pkcs11ModulePath;
     }
 
-    public static synchronized PKCS11 getInstance(String pkcs11ModulePath, String functionList,
-            CK_C_INITIALIZE_ARGS pInitArgs, boolean omitInitialize)
-            throws IOException, PKCS11Exception {
+    public static synchronized PKCS11 getInstance(String pkcs11ModulePath,
+            String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
+            boolean omitInitialize) throws IOException, PKCS11Exception {
         // we may only call C_Initialize once per native .so/.dll
         // so keep a cache using the (non-canonicalized!) path
         PKCS11 pkcs11 = moduleMap.get(pkcs11ModulePath);
@@ -177,7 +178,8 @@
      * @preconditions (pkcs11ModulePath <> null)
      * @postconditions
      */
-    private native void connect(String pkcs11ModulePath, String functionListName) throws IOException;
+    private native void connect(String pkcs11ModulePath, String functionListName)
+            throws IOException;
 
     /**
      * Disconnects the PKCS#11 library from this object. After calling this
@@ -255,7 +257,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native long[] C_GetSlotList(boolean tokenPresent) throws PKCS11Exception;
+    public native long[] C_GetSlotList(boolean tokenPresent)
+            throws PKCS11Exception;
 
 
     /**
@@ -287,7 +290,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native CK_TOKEN_INFO C_GetTokenInfo(long slotID) throws PKCS11Exception;
+    public native CK_TOKEN_INFO C_GetTokenInfo(long slotID)
+            throws PKCS11Exception;
 
 
     /**
@@ -322,7 +326,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type) throws PKCS11Exception;
+    public native CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type)
+            throws PKCS11Exception;
 
 
     /**
@@ -339,7 +344,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native void C_InitToken(long slotID, char[] pPin, char[] pLabel) throws PKCS11Exception;
+//    public native void C_InitToken(long slotID, char[] pPin, char[] pLabel)
+//            throws PKCS11Exception;
 
 
     /**
@@ -354,7 +360,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native void C_InitPIN(long hSession, char[] pPin) throws PKCS11Exception;
+//    public native void C_InitPIN(long hSession, char[] pPin)
+//            throws PKCS11Exception;
 
 
     /**
@@ -371,7 +378,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native void C_SetPIN(long hSession, char[] pOldPin, char[] pNewPin) throws PKCS11Exception;
+//    public native void C_SetPIN(long hSession, char[] pOldPin, char[] pNewPin)
+//            throws PKCS11Exception;
 
 
 
@@ -398,7 +406,8 @@
      * @preconditions
      * @postconditions
      */
-    public native long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception;
+    public native long C_OpenSession(long slotID, long flags,
+            Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception;
 
 
     /**
@@ -440,7 +449,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception;
+    public native CK_SESSION_INFO C_GetSessionInfo(long hSession)
+            throws PKCS11Exception;
 
 
     /**
@@ -457,7 +467,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-//    public native byte[] C_GetOperationState(long hSession) throws PKCS11Exception;
+    public native byte[] C_GetOperationState(long hSession)
+            throws PKCS11Exception;
 
 
     /**
@@ -478,7 +489,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native void C_SetOperationState(long hSession, byte[] pOperationState, long hEncryptionKey, long hAuthenticationKey) throws PKCS11Exception;
+    public native void C_SetOperationState(long hSession, byte[] pOperationState,
+            long hEncryptionKey, long hAuthenticationKey) throws PKCS11Exception;
 
 
     /**
@@ -495,7 +507,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception;
+    public native void C_Login(long hSession, long userType, char[] pPin)
+            throws PKCS11Exception;
 
 
     /**
@@ -531,7 +544,8 @@
      * @preconditions
      * @postconditions
      */
-    public native long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate)
+            throws PKCS11Exception;
 
 
     /**
@@ -552,7 +566,8 @@
      * @preconditions
      * @postconditions
      */
-    public native long C_CopyObject(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native long C_CopyObject(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
 
 
     /**
@@ -567,7 +582,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_DestroyObject(long hSession, long hObject) throws PKCS11Exception;
+    public native void C_DestroyObject(long hSession, long hObject)
+            throws PKCS11Exception;
 
 
     /**
@@ -584,7 +600,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native long C_GetObjectSize(long hSession, long hObject) throws PKCS11Exception;
+//    public native long C_GetObjectSize(long hSession, long hObject)
+//            throws PKCS11Exception;
 
 
     /**
@@ -604,7 +621,8 @@
      * @preconditions (pTemplate <> null)
      * @postconditions (result <> null)
      */
-    public native void C_GetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native void C_GetAttributeValue(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
 
 
     /**
@@ -623,7 +641,8 @@
      * @preconditions (pTemplate <> null)
      * @postconditions
      */
-    public native void C_SetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native void C_SetAttributeValue(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
 
 
     /**
@@ -640,7 +659,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate)
+            throws PKCS11Exception;
 
 
     /**
@@ -659,7 +679,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native long[] C_FindObjects(long hSession, long ulMaxObjectCount) throws PKCS11Exception;
+    public native long[] C_FindObjects(long hSession, long ulMaxObjectCount)
+            throws PKCS11Exception;
 
 
     /**
@@ -695,7 +716,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_EncryptInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception;
 
 
     /**
@@ -713,7 +735,8 @@
      * @preconditions (pData <> null)
      * @postconditions (result <> null)
      */
-    public native int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen,
+            byte[] out, int outOfs, int outLen) throws PKCS11Exception;
 
 
     /**
@@ -732,7 +755,9 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-    public native int C_EncryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_EncryptUpdate(long hSession, long directIn, byte[] in,
+            int inOfs, int inLen, long directOut, byte[] out, int outOfs,
+            int outLen) throws PKCS11Exception;
 
 
     /**
@@ -749,7 +774,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_EncryptFinal(long hSession, long directOut, byte[] out,
+            int outOfs, int outLen) throws PKCS11Exception;
 
 
     /**
@@ -766,7 +792,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_DecryptInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception;
 
 
     /**
@@ -785,7 +812,8 @@
      * @preconditions (pEncryptedPart <> null)
      * @postconditions (result <> null)
      */
-    public native int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen,
+            byte[] out, int outOfs, int outLen) throws PKCS11Exception;
 
 
     /**
@@ -805,7 +833,9 @@
      * @preconditions (pEncryptedPart <> null)
      * @postconditions
      */
-    public native int C_DecryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_DecryptUpdate(long hSession, long directIn, byte[] in,
+            int inOfs, int inLen, long directOut, byte[] out, int outOfs,
+            int outLen) throws PKCS11Exception;
 
 
     /**
@@ -822,7 +852,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception;
+    public native int C_DecryptFinal(long hSession, long directOut, byte[] out,
+            int outOfs, int outLen) throws PKCS11Exception;
 
 
 
@@ -842,7 +873,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_DigestInit(long hSession, CK_MECHANISM pMechanism) throws PKCS11Exception;
+    public native void C_DigestInit(long hSession, CK_MECHANISM pMechanism)
+            throws PKCS11Exception;
 
 
     // note that C_DigestSingle does not exist in PKCS#11
@@ -863,7 +895,9 @@
      * @preconditions (data <> null)
      * @postconditions (result <> null)
      */
-    public native int C_DigestSingle(long hSession, CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception;
+    public native int C_DigestSingle(long hSession, CK_MECHANISM pMechanism,
+            byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs,
+            int digestLen) throws PKCS11Exception;
 
 
     /**
@@ -879,7 +913,8 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-    public native void C_DigestUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception;
+    public native void C_DigestUpdate(long hSession, long directIn, byte[] in,
+            int inOfs, int inLen) throws PKCS11Exception;
 
 
     /**
@@ -896,7 +931,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_DigestKey(long hSession, long hKey) throws PKCS11Exception;
+    public native void C_DigestKey(long hSession, long hKey)
+            throws PKCS11Exception;
 
 
     /**
@@ -912,7 +948,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs, int digestLen) throws PKCS11Exception;
+    public native int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs,
+            int digestLen) throws PKCS11Exception;
 
 
 
@@ -937,7 +974,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_SignInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_SignInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception;
 
 
     /**
@@ -957,7 +995,8 @@
      * @preconditions (pData <> null)
      * @postconditions (result <> null)
      */
-    public native byte[] C_Sign(long hSession, byte[] pData) throws PKCS11Exception;
+    public native byte[] C_Sign(long hSession, byte[] pData)
+            throws PKCS11Exception;
 
 
     /**
@@ -974,7 +1013,8 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-    public native void C_SignUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception;
+    public native void C_SignUpdate(long hSession, long directIn, byte[] in,
+            int inOfs, int inLen) throws PKCS11Exception;
 
 
     /**
@@ -991,7 +1031,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native byte[] C_SignFinal(long hSession, int expectedLen) throws PKCS11Exception;
+    public native byte[] C_SignFinal(long hSession, int expectedLen)
+            throws PKCS11Exception;
 
 
     /**
@@ -1009,7 +1050,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception;
 
 
     /**
@@ -1028,7 +1070,9 @@
      * @preconditions (pData <> null)
      * @postconditions (result <> null)
      */
-    public native int C_SignRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception;
+    public native int C_SignRecover(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOufs, int outLen)
+            throws PKCS11Exception;
 
 
 
@@ -1052,7 +1096,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_VerifyInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception;
 
 
     /**
@@ -1071,7 +1116,8 @@
      * @preconditions (pData <> null) and (pSignature <> null)
      * @postconditions
      */
-    public native void C_Verify(long hSession, byte[] pData, byte[] pSignature) throws PKCS11Exception;
+    public native void C_Verify(long hSession, byte[] pData, byte[] pSignature)
+            throws PKCS11Exception;
 
 
     /**
@@ -1088,7 +1134,8 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-    public native void C_VerifyUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception;
+    public native void C_VerifyUpdate(long hSession, long directIn, byte[] in,
+            int inOfs, int inLen) throws PKCS11Exception;
 
 
     /**
@@ -1104,7 +1151,8 @@
      * @preconditions (pSignature <> null)
      * @postconditions
      */
-    public native void C_VerifyFinal(long hSession, byte[] pSignature) throws PKCS11Exception;
+    public native void C_VerifyFinal(long hSession, byte[] pSignature)
+            throws PKCS11Exception;
 
 
     /**
@@ -1122,7 +1170,8 @@
      * @preconditions
      * @postconditions
      */
-    public native void C_VerifyRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
+    public native void C_VerifyRecoverInit(long hSession,
+            CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception;
 
 
     /**
@@ -1140,7 +1189,9 @@
      * @preconditions (pSignature <> null)
      * @postconditions (result <> null)
      */
-    public native int C_VerifyRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception;
+    public native int C_VerifyRecover(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOufs, int outLen)
+            throws PKCS11Exception;
 
 
 
@@ -1164,7 +1215,8 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-//    public native byte[] C_DigestEncryptUpdate(long hSession, byte[] pPart) throws PKCS11Exception;
+//    public native byte[] C_DigestEncryptUpdate(long hSession, byte[] pPart)
+//            throws PKCS11Exception;
 
 
     /**
@@ -1184,7 +1236,8 @@
      * @preconditions (pEncryptedPart <> null)
      * @postconditions
      */
-//    public native byte[] C_DecryptDigestUpdate(long hSession, byte[] pEncryptedPart) throws PKCS11Exception;
+//    public native byte[] C_DecryptDigestUpdate(long hSession,
+//            byte[] pEncryptedPart) throws PKCS11Exception;
 
 
     /**
@@ -1204,7 +1257,8 @@
      * @preconditions (pPart <> null)
      * @postconditions
      */
-//    public native byte[] C_SignEncryptUpdate(long hSession, byte[] pPart) throws PKCS11Exception;
+//    public native byte[] C_SignEncryptUpdate(long hSession, byte[] pPart)
+//            throws PKCS11Exception;
 
 
     /**
@@ -1224,7 +1278,8 @@
      * @preconditions (pEncryptedPart <> null)
      * @postconditions
      */
-//    public native byte[] C_DecryptVerifyUpdate(long hSession, byte[] pEncryptedPart) throws PKCS11Exception;
+//    public native byte[] C_DecryptVerifyUpdate(long hSession,
+//            byte[] pEncryptedPart) throws PKCS11Exception;
 
 
 
@@ -1250,7 +1305,8 @@
      * @preconditions
      * @postconditions
      */
-    public native long C_GenerateKey(long hSession, CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+    public native long C_GenerateKey(long hSession, CK_MECHANISM pMechanism,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
 
 
     /**
@@ -1280,9 +1336,8 @@
      * @postconditions (result <> null) and (result.length == 2)
      */
     public native long[] C_GenerateKeyPair(long hSession,
-                                   CK_MECHANISM pMechanism,
-                                   CK_ATTRIBUTE[] pPublicKeyTemplate,
-                                   CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception;
+            CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pPublicKeyTemplate,
+            CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception;
 
 
 
@@ -1305,7 +1360,8 @@
      * @preconditions
      * @postconditions (result <> null)
      */
-    public native byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, long hWrappingKey, long hKey) throws PKCS11Exception;
+    public native byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism,
+            long hWrappingKey, long hKey) throws PKCS11Exception;
 
 
     /**
@@ -1331,8 +1387,8 @@
      * @postconditions
      */
     public native long C_UnwrapKey(long hSession, CK_MECHANISM pMechanism,
-                          long hUnwrappingKey, byte[] pWrappedKey,
-                          CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+            long hUnwrappingKey, byte[] pWrappedKey, CK_ATTRIBUTE[] pTemplate)
+            throws PKCS11Exception;
 
 
     /**
@@ -1356,7 +1412,7 @@
      * @postconditions
      */
     public native long C_DeriveKey(long hSession, CK_MECHANISM pMechanism,
-                          long hBaseKey, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
+            long hBaseKey, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception;
 
 
 
@@ -1377,7 +1433,8 @@
      * @preconditions (pSeed <> null)
      * @postconditions
      */
-    public native void C_SeedRandom(long hSession, byte[] pSeed) throws PKCS11Exception;
+    public native void C_SeedRandom(long hSession, byte[] pSeed)
+            throws PKCS11Exception;
 
 
     /**
@@ -1393,7 +1450,8 @@
      * @preconditions (randomData <> null)
      * @postconditions
      */
-    public native void C_GenerateRandom(long hSession, byte[] randomData) throws PKCS11Exception;
+    public native void C_GenerateRandom(long hSession, byte[] randomData)
+            throws PKCS11Exception;
 
 
 
@@ -1413,7 +1471,8 @@
      * @preconditions
      * @postconditions
      */
-//    public native void C_GetFunctionStatus(long hSession) throws PKCS11Exception;
+//    public native void C_GetFunctionStatus(long hSession)
+//            throws PKCS11Exception;
 
 
     /**
@@ -1450,7 +1509,8 @@
      * @preconditions (pRserved == null)
      * @postconditions
      */
-//    public native long C_WaitForSlotEvent(long flags, Object pRserved) throws PKCS11Exception;
+//    public native long C_WaitForSlotEvent(long flags, Object pRserved)
+//            throws PKCS11Exception;
 
     /**
      * Returns the string representation of this object.
@@ -1476,7 +1536,8 @@
 // parent. Used for tokens that only support single threaded access
 static class SynchronizedPKCS11 extends PKCS11 {
 
-    SynchronizedPKCS11(String pkcs11ModulePath, String functionListName) throws IOException {
+    SynchronizedPKCS11(String pkcs11ModulePath, String functionListName)
+            throws IOException {
         super(pkcs11ModulePath, functionListName);
     }
 
@@ -1484,7 +1545,8 @@
         super.C_Initialize(pInitArgs);
     }
 
-    public synchronized void C_Finalize(Object pReserved) throws PKCS11Exception {
+    public synchronized void C_Finalize(Object pReserved)
+            throws PKCS11Exception {
         super.C_Finalize(pReserved);
     }
 
@@ -1492,39 +1554,48 @@
         return super.C_GetInfo();
     }
 
-    public synchronized long[] C_GetSlotList(boolean tokenPresent) throws PKCS11Exception {
+    public synchronized long[] C_GetSlotList(boolean tokenPresent)
+            throws PKCS11Exception {
         return super.C_GetSlotList(tokenPresent);
     }
 
-    public synchronized CK_SLOT_INFO C_GetSlotInfo(long slotID) throws PKCS11Exception {
+    public synchronized CK_SLOT_INFO C_GetSlotInfo(long slotID)
+            throws PKCS11Exception {
         return super.C_GetSlotInfo(slotID);
     }
 
-    public synchronized CK_TOKEN_INFO C_GetTokenInfo(long slotID) throws PKCS11Exception {
+    public synchronized CK_TOKEN_INFO C_GetTokenInfo(long slotID)
+            throws PKCS11Exception {
         return super.C_GetTokenInfo(slotID);
     }
 
-    public synchronized long[] C_GetMechanismList(long slotID) throws PKCS11Exception {
+    public synchronized long[] C_GetMechanismList(long slotID)
+            throws PKCS11Exception {
         return super.C_GetMechanismList(slotID);
     }
 
-    public synchronized CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type) throws PKCS11Exception {
+    public synchronized CK_MECHANISM_INFO C_GetMechanismInfo(long slotID,
+            long type) throws PKCS11Exception {
         return super.C_GetMechanismInfo(slotID, type);
     }
 
-    public synchronized long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception {
+    public synchronized long C_OpenSession(long slotID, long flags,
+            Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception {
         return super.C_OpenSession(slotID, flags, pApplication, Notify);
     }
 
-    public synchronized void C_CloseSession(long hSession) throws PKCS11Exception {
+    public synchronized void C_CloseSession(long hSession)
+            throws PKCS11Exception {
         super.C_CloseSession(hSession);
     }
 
-    public synchronized CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception {
+    public synchronized CK_SESSION_INFO C_GetSessionInfo(long hSession)
+            throws PKCS11Exception {
         return super.C_GetSessionInfo(hSession);
     }
 
-    public synchronized void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception {
+    public synchronized void C_Login(long hSession, long userType, char[] pPin)
+            throws PKCS11Exception {
         super.C_Login(hSession, userType, pPin);
     }
 
@@ -1532,157 +1603,207 @@
         super.C_Logout(hSession);
     }
 
-    public synchronized long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized long C_CreateObject(long hSession,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
         return super.C_CreateObject(hSession, pTemplate);
     }
 
-    public synchronized long C_CopyObject(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized long C_CopyObject(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
         return super.C_CopyObject(hSession, hObject, pTemplate);
     }
 
-    public synchronized void C_DestroyObject(long hSession, long hObject) throws PKCS11Exception {
+    public synchronized void C_DestroyObject(long hSession, long hObject)
+            throws PKCS11Exception {
         super.C_DestroyObject(hSession, hObject);
     }
 
-    public synchronized void C_GetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized void C_GetAttributeValue(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
         super.C_GetAttributeValue(hSession, hObject, pTemplate);
     }
 
-    public synchronized void C_SetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized void C_SetAttributeValue(long hSession, long hObject,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
         super.C_SetAttributeValue(hSession, hObject, pTemplate);
     }
 
-    public synchronized void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized void C_FindObjectsInit(long hSession,
+            CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
         super.C_FindObjectsInit(hSession, pTemplate);
     }
 
-    public synchronized long[] C_FindObjects(long hSession, long ulMaxObjectCount) throws PKCS11Exception {
+    public synchronized long[] C_FindObjects(long hSession,
+            long ulMaxObjectCount) throws PKCS11Exception {
         return super.C_FindObjects(hSession, ulMaxObjectCount);
     }
 
-    public synchronized void C_FindObjectsFinal(long hSession) throws PKCS11Exception {
+    public synchronized void C_FindObjectsFinal(long hSession)
+            throws PKCS11Exception {
         super.C_FindObjectsFinal(hSession);
     }
 
-    public synchronized void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_EncryptInit(long hSession,
+            CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
         super.C_EncryptInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
+    public synchronized int C_Encrypt(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOfs, int outLen)
+            throws PKCS11Exception {
         return super.C_Encrypt(hSession, in, inOfs, inLen, out, outOfs, outLen);
     }
 
-    public synchronized int C_EncryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
-        return super.C_EncryptUpdate(hSession, directIn, in, inOfs, inLen, directOut, out, outOfs, outLen);
+    public synchronized int C_EncryptUpdate(long hSession, long directIn,
+            byte[] in, int inOfs, int inLen, long directOut, byte[] out,
+            int outOfs, int outLen) throws PKCS11Exception {
+        return super.C_EncryptUpdate(hSession, directIn, in, inOfs, inLen,
+                directOut, out, outOfs, outLen);
     }
 
-    public synchronized int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
+    public synchronized int C_EncryptFinal(long hSession, long directOut,
+            byte[] out, int outOfs, int outLen) throws PKCS11Exception {
         return super.C_EncryptFinal(hSession, directOut, out, outOfs, outLen);
     }
 
-    public synchronized void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_DecryptInit(long hSession,
+            CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
         super.C_DecryptInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
+    public synchronized int C_Decrypt(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOfs, int outLen)
+            throws PKCS11Exception {
         return super.C_Decrypt(hSession, in, inOfs, inLen, out, outOfs, outLen);
     }
 
-    public synchronized int C_DecryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
-        return super.C_DecryptUpdate(hSession, directIn, in, inOfs, inLen, directOut, out, outOfs, outLen);
+    public synchronized int C_DecryptUpdate(long hSession, long directIn,
+            byte[] in, int inOfs, int inLen, long directOut, byte[] out,
+            int outOfs, int outLen) throws PKCS11Exception {
+        return super.C_DecryptUpdate(hSession, directIn, in, inOfs, inLen,
+                directOut, out, outOfs, outLen);
     }
 
-    public synchronized int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception {
+    public synchronized int C_DecryptFinal(long hSession, long directOut,
+            byte[] out, int outOfs, int outLen) throws PKCS11Exception {
         return super.C_DecryptFinal(hSession, directOut, out, outOfs, outLen);
     }
 
-    public synchronized void C_DigestInit(long hSession, CK_MECHANISM pMechanism) throws PKCS11Exception {
+    public synchronized void C_DigestInit(long hSession, CK_MECHANISM pMechanism)
+            throws PKCS11Exception {
         super.C_DigestInit(hSession, pMechanism);
     }
 
-    public synchronized int C_DigestSingle(long hSession, CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception {
-        return super.C_DigestSingle(hSession, pMechanism, in, inOfs, inLen, digest, digestOfs, digestLen);
+    public synchronized int C_DigestSingle(long hSession,
+            CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen,
+            byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception {
+        return super.C_DigestSingle(hSession, pMechanism, in, inOfs, inLen,
+                digest, digestOfs, digestLen);
     }
 
-    public synchronized void C_DigestUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception {
+    public synchronized void C_DigestUpdate(long hSession, long directIn,
+            byte[] in, int inOfs, int inLen) throws PKCS11Exception {
         super.C_DigestUpdate(hSession, directIn, in, inOfs, inLen);
     }
 
-    public synchronized void C_DigestKey(long hSession, long hKey) throws PKCS11Exception {
+    public synchronized void C_DigestKey(long hSession, long hKey)
+            throws PKCS11Exception {
         super.C_DigestKey(hSession, hKey);
     }
 
-    public synchronized int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs, int digestLen) throws PKCS11Exception {
+    public synchronized int C_DigestFinal(long hSession, byte[] pDigest,
+            int digestOfs, int digestLen) throws PKCS11Exception {
         return super.C_DigestFinal(hSession, pDigest, digestOfs, digestLen);
     }
 
-    public synchronized void C_SignInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_SignInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception {
         super.C_SignInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized byte[] C_Sign(long hSession, byte[] pData) throws PKCS11Exception {
+    public synchronized byte[] C_Sign(long hSession, byte[] pData)
+            throws PKCS11Exception {
         return super.C_Sign(hSession, pData);
     }
 
-    public synchronized void C_SignUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception {
+    public synchronized void C_SignUpdate(long hSession, long directIn,
+            byte[] in, int inOfs, int inLen) throws PKCS11Exception {
         super.C_SignUpdate(hSession, directIn, in, inOfs, inLen);
     }
 
-    public synchronized byte[] C_SignFinal(long hSession, int expectedLen) throws PKCS11Exception {
+    public synchronized byte[] C_SignFinal(long hSession, int expectedLen)
+            throws PKCS11Exception {
         return super.C_SignFinal(hSession, expectedLen);
     }
 
-    public synchronized void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_SignRecoverInit(long hSession,
+            CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
         super.C_SignRecoverInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized int C_SignRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception {
-        return super.C_SignRecover(hSession, in, inOfs, inLen, out, outOufs, outLen);
+    public synchronized int C_SignRecover(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOufs, int outLen)
+            throws PKCS11Exception {
+        return super.C_SignRecover(hSession, in, inOfs, inLen, out, outOufs,
+                outLen);
     }
 
-    public synchronized void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_VerifyInit(long hSession, CK_MECHANISM pMechanism,
+            long hKey) throws PKCS11Exception {
         super.C_VerifyInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized void C_Verify(long hSession, byte[] pData, byte[] pSignature) throws PKCS11Exception {
+    public synchronized void C_Verify(long hSession, byte[] pData,
+            byte[] pSignature) throws PKCS11Exception {
         super.C_Verify(hSession, pData, pSignature);
     }
 
-    public synchronized void C_VerifyUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception {
+    public synchronized void C_VerifyUpdate(long hSession, long directIn,
+            byte[] in, int inOfs, int inLen) throws PKCS11Exception {
         super.C_VerifyUpdate(hSession, directIn, in, inOfs, inLen);
     }
 
-    public synchronized void C_VerifyFinal(long hSession, byte[] pSignature) throws PKCS11Exception {
+    public synchronized void C_VerifyFinal(long hSession, byte[] pSignature)
+            throws PKCS11Exception {
         super.C_VerifyFinal(hSession, pSignature);
     }
 
-    public synchronized void C_VerifyRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
+    public synchronized void C_VerifyRecoverInit(long hSession,
+            CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception {
         super.C_VerifyRecoverInit(hSession, pMechanism, hKey);
     }
 
-    public synchronized int C_VerifyRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception {
-        return super.C_VerifyRecover(hSession, in, inOfs, inLen, out, outOufs, outLen);
+    public synchronized int C_VerifyRecover(long hSession, byte[] in, int inOfs,
+            int inLen, byte[] out, int outOufs, int outLen)
+            throws PKCS11Exception {
+        return super.C_VerifyRecover(hSession, in, inOfs, inLen, out, outOufs,
+                outLen);
     }
 
-    public synchronized long C_GenerateKey(long hSession, CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+    public synchronized long C_GenerateKey(long hSession,
+            CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate)
+            throws PKCS11Exception {
         return super.C_GenerateKey(hSession, pMechanism, pTemplate);
     }
 
     public synchronized long[] C_GenerateKeyPair(long hSession,
-                                   CK_MECHANISM pMechanism,
-                                   CK_ATTRIBUTE[] pPublicKeyTemplate,
-                                   CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception {
-        return super.C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate, pPrivateKeyTemplate);
+            CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pPublicKeyTemplate,
+            CK_ATTRIBUTE[] pPrivateKeyTemplate)
+            throws PKCS11Exception {
+        return super.C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate,
+                pPrivateKeyTemplate);
     }
 
-    public synchronized byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, long hWrappingKey, long hKey) throws PKCS11Exception {
+    public synchronized byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism,
+            long hWrappingKey, long hKey) throws PKCS11Exception {
         return super.C_WrapKey(hSession, pMechanism, hWrappingKey, hKey);
     }
 
     public synchronized long C_UnwrapKey(long hSession, CK_MECHANISM pMechanism,
-                          long hUnwrappingKey, byte[] pWrappedKey,
-                          CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
-        return super.C_UnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey, pTemplate);
+            long hUnwrappingKey, byte[] pWrappedKey, CK_ATTRIBUTE[] pTemplate)
+            throws PKCS11Exception {
+        return super.C_UnwrapKey(hSession, pMechanism, hUnwrappingKey,
+                pWrappedKey, pTemplate);
     }
 
     public synchronized long C_DeriveKey(long hSession, CK_MECHANISM pMechanism,
@@ -1690,14 +1811,14 @@
         return super.C_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate);
     }
 
-    public synchronized void C_SeedRandom(long hSession, byte[] pSeed) throws PKCS11Exception {
+    public synchronized void C_SeedRandom(long hSession, byte[] pSeed)
+            throws PKCS11Exception {
         super.C_SeedRandom(hSession, pSeed);
     }
 
-    public synchronized void C_GenerateRandom(long hSession, byte[] randomData) throws PKCS11Exception {
+    public synchronized void C_GenerateRandom(long hSession, byte[] randomData)
+            throws PKCS11Exception {
         super.C_GenerateRandom(hSession, randomData);
     }
-
 }
-
 }
--- a/src/share/classes/sun/security/provider/DSA.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/DSA.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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 @@
 
 /**
  * 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 @@
     /* 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,24 @@
             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");
+        }
+
+        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,17 +142,42 @@
         }
         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");
+        }
+
+        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
      * sequence of Integer, r and s.
@@ -352,23 +279,41 @@
         }
     }
 
+    @Deprecated
+    protected void engineSetParameter(String key, Object param) {
+        throw new InvalidParameterException("No parameter accepted");
+    }
+
+    @Deprecated
+    protected Object engineGetParameter(String key) {
+        return null;
+    }
+
     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 +325,41 @@
              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 +367,7 @@
 
     // 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;
@@ -447,171 +379,6 @@
     }
 
     /**
-     * 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:<dl>
-     *
-     * <dt><tt>Kseed</tt>
-     *
-     * <dd>a byte array.
-     *
-     * </dl>
-     *
-     * @deprecated
-     */
-    @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:
-     *
-     * <dl>
-     *
-     * <dt><tt>Kseed</tt>
-     *
-     * <dd>a byte array.
-     *
-     * </dl>
-     *
-     * @return the value of the requested parameter.
-     *
-     * @see java.security.SignatureEngine
-     *
-     * @deprecated
-     */
-    @Deprecated
-    protected Object engineGetParameter(String key) {
-        if (key.equals("KSEED")) {
-            return KseedAsByteArray;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Set the algorithm object.
-     */
-    private void setParams(DSAParams params) throws InvalidKeyException {
-        if (params == null) {
-            throw new InvalidKeyException("DSA public key lacks parameters");
-        }
-        this.params = params;
-        this.presetP = params.getP();
-        this.presetQ = params.getQ();
-        this.presetG = params.getG();
-    }
-
-    /**
      * Return a human readable rendition of the engine.
      */
     public String toString() {
@@ -632,38 +399,6 @@
         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;
-    }
-
     private static void debug(Exception e) {
         if (debug) {
             e.printStackTrace();
@@ -675,4 +410,317 @@
             System.err.println(s);
         }
     }
+
+    /**
+     * Standard SHA224withDSA implementation as defined in FIPS186-3.
+     */
+    public static final class SHA224withDSA extends DSA {
+        public SHA224withDSA() throws NoSuchAlgorithmException {
+            super(MessageDigest.getInstance("SHA-224"));
+        }
+    }
+
+    /**
+     * Standard SHA256withDSA implementation as defined in FIPS186-3.
+     */
+    public static final class SHA256withDSA extends DSA {
+        public SHA256withDSA() throws NoSuchAlgorithmException {
+            super(MessageDigest.getInstance("SHA-256"));
+        }
+    }
+
+    static class LegacyDSA extends DSA {
+        /* 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[] kSeedLast;
+
+        public LegacyDSA(MessageDigest md) throws NoSuchAlgorithmException {
+            super(md);
+        }
+
+        @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("Unsupported parameter");
+            }
+        }
+
+        @Deprecated
+        protected Object engineGetParameter(String key) {
+           if (key.equals("KSEED")) {
+               return kSeedAsByteArray;
+           } else {
+               return null;
+           }
+        }
+
+        /*
+         * Please read bug report 4044247 for an alternative, faster,
+         * NON-FIPS approved method to generate K
+         */
+        @Override
+        protected BigInteger generateK(BigInteger q) {
+            BigInteger k = null;
+
+            // The application specified a kSeed for us to use.
+            // Note: we dis-allow usage of the same Kseed twice in a row
+            if (kSeed != null && !Arrays.equals(kSeed, kSeedLast)) {
+                k = generateKUsingKSeed(kSeed, q);
+                if (k.signum() > 0 && k.compareTo(q) < 0) {
+                    kSeedLast = kSeed.clone();
+                    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 = generateKUsingKSeed(seed, q);
+                if (k.signum() > 0 && k.compareTo(q) < 0) {
+                    kSeedLast = seed;
+                    return k;
+                }
+            }
+        }
+
+        /**
+         * Compute k for the DSA signature as defined in the original DSS,
+         * i.e. FIPS186.
+         *
+         * @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 generateKUsingKSeed(int[] seed, BigInteger q) {
+
+            // check out t in the spec.
+            int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476,
+                        0xC3D2E1F0, 0x67452301 };
+            //
+            int[] tmp = 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;
+        }
+
+        /*
+         * 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;
+        }
+    }
+
+    public static final class SHA1withDSA extends LegacyDSA {
+        public SHA1withDSA() throws NoSuchAlgorithmException {
+            super(MessageDigest.getInstance("SHA-1"));
+        }
+    }
+
+    /**
+     * 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 LegacyDSA {
+        // Internal special-purpose MessageDigest impl for RawDSA
+        // Only override whatever methods used
+        // NOTE: no clone support
+        public static final class NullDigest20 extends MessageDigest {
+            // 20 byte digest buffer
+            private final byte[] digestBuffer = new byte[20];
+
+            // offset into the buffer; use Integer.MAX_VALUE to indicate
+            // out-of-bound condition
+            private int ofs = 0;
+
+            protected NullDigest20() {
+                super("NullDigest20");
+            }
+            protected void engineUpdate(byte input) {
+                if (ofs == digestBuffer.length) {
+                    ofs = Integer.MAX_VALUE;
+                } else {
+                    digestBuffer[ofs++] = input;
+                }
+            }
+            protected void engineUpdate(byte[] input, int offset, int len) {
+                if (ofs + len > digestBuffer.length) {
+                    ofs = Integer.MAX_VALUE;
+                } else {
+                    System.arraycopy(input, offset, digestBuffer, ofs, len);
+                    ofs += len;
+                }
+            }
+            protected final void engineUpdate(ByteBuffer input) {
+                int inputLen = input.remaining();
+                if (ofs + inputLen > digestBuffer.length) {
+                    ofs = Integer.MAX_VALUE;
+                } else {
+                    input.get(digestBuffer, ofs, inputLen);
+                    ofs += inputLen;
+                }
+            }
+            protected byte[] engineDigest() throws RuntimeException {
+                if (ofs != digestBuffer.length) {
+                    throw new RuntimeException
+                        ("Data for RawDSA must be exactly 20 bytes long");
+                }
+                reset();
+                return digestBuffer;
+            }
+            protected int engineDigest(byte[] buf, int offset, int len)
+                throws DigestException {
+                if (ofs != digestBuffer.length) {
+                    throw new DigestException
+                        ("Data for RawDSA must be exactly 20 bytes long");
+                }
+                if (len < digestBuffer.length) {
+                    throw new DigestException
+                        ("Output buffer too small; must be at least 20 bytes");
+                }
+                System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);
+                reset();
+                return digestBuffer.length;
+            }
+
+            protected void engineReset() {
+                ofs = 0;
+            }
+            protected final int engineGetDigestLength() {
+                return digestBuffer.length;
+            }
+        }
+
+        public RawDSA() throws NoSuchAlgorithmException {
+            super(new NullDigest20());
+        }
+    }
 }
--- a/src/share/classes/sun/security/provider/DSAKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/DSAKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -48,8 +48,9 @@
 public class DSAKeyPairGenerator extends KeyPairGenerator
 implements java.security.interfaces.DSAKeyPairGenerator {
 
-    /* The modulus length */
-    private int modlen;
+    /* Length for prime P and subPrime Q in bits */
+    private int plen;
+    private int qlen;
 
     /* whether to force new parameters to be generated for each KeyPair */
     private boolean forceNewParameters;
@@ -65,20 +66,23 @@
         initialize(1024, null);
     }
 
-    private static void checkStrength(int strength) {
-        if ((strength < 512) || (strength > 1024) || (strength % 64 != 0)) {
+    private static void checkStrength(int sizeP, int sizeQ) {
+        if ((sizeP >= 512) && (sizeP <= 1024) && (sizeP % 64 == 0)
+            && sizeQ == 160) {
+            // traditional - allow for backward compatibility
+            // L=multiples of 64 and between 512 and 1024 (inclusive)
+            // N=160
+        } else if (sizeP == 2048 && (sizeQ == 224 || sizeQ == 256)) {
+            // L=2048, N=224 or 256
+        } else {
             throw new InvalidParameterException
-                ("Modulus size must range from 512 to 1024 "
-                 + "and be a multiple of 64");
+                ("Unsupported prime and subprime size combination: " +
+                 sizeP + ", " + sizeQ);
         }
     }
 
     public void initialize(int modlen, SecureRandom random) {
-        checkStrength(modlen);
-        this.random = random;
-        this.modlen = modlen;
-        this.params = null;
-        this.forceNewParameters = false;
+        initialize(modlen, false, random);
     }
 
     /**
@@ -86,18 +90,27 @@
      * is false, a set of pre-computed parameters is used.
      */
     public void initialize(int modlen, boolean genParams, SecureRandom random) {
-        checkStrength(modlen);
+        int subPrimeLen = -1;
+        if (modlen <= 1024) {
+            subPrimeLen = 160;
+        } else if (modlen == 2048) {
+            subPrimeLen = 224;
+        }
+        checkStrength(modlen, subPrimeLen);
         if (genParams) {
             params = null;
         } else {
-            params = ParameterCache.getCachedDSAParameterSpec(modlen);
+            params = ParameterCache.getCachedDSAParameterSpec(modlen,
+                subPrimeLen);
             if (params == null) {
                 throw new InvalidParameterException
                     ("No precomputed parameters for requested modulus size "
                      + "available");
             }
+
         }
-        this.modlen = modlen;
+        this.plen = modlen;
+        this.qlen = subPrimeLen;
         this.random = random;
         this.forceNewParameters = genParams;
     }
@@ -136,9 +149,11 @@
     }
 
     private void initialize0(DSAParameterSpec params, SecureRandom random) {
-        int modlen = params.getP().bitLength();
-        checkStrength(modlen);
-        this.modlen = modlen;
+        int sizeP = params.getP().bitLength();
+        int sizeQ = params.getQ().bitLength();
+        checkStrength(sizeP, sizeQ);
+        this.plen = sizeP;
+        this.qlen = sizeQ;
         this.params = params;
         this.random = random;
         this.forceNewParameters = false;
@@ -156,11 +171,11 @@
         try {
             if (forceNewParameters) {
                 // generate new parameters each time
-                spec = ParameterCache.getNewDSAParameterSpec(modlen, random);
+                spec = ParameterCache.getNewDSAParameterSpec(plen, qlen, random);
             } else {
                 if (params == null) {
                     params =
-                        ParameterCache.getDSAParameterSpec(modlen, random);
+                        ParameterCache.getDSAParameterSpec(plen, qlen, random);
                 }
                 spec = params;
             }
@@ -203,43 +218,14 @@
      */
     private BigInteger generateX(SecureRandom random, BigInteger q) {
         BigInteger x = null;
+        byte[] temp = new byte[qlen];
         while (true) {
-            int[] seed = new int[5];
-            for (int i = 0; i < 5; i++) {
-                seed[i] = random.nextInt();
-            }
-            x = generateX(seed, q);
+            random.nextBytes(temp);
+            x = new BigInteger(1, temp).mod(q);
             if (x.signum() > 0 && (x.compareTo(q) < 0)) {
-                break;
+                return x;
             }
         }
-        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) {
-
-        // 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;
     }
 
     /**
--- a/src/share/classes/sun/security/provider/DSAParameterGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/DSAParameterGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, 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
@@ -32,11 +32,14 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.InvalidParameterException;
+import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
 import java.security.spec.DSAParameterSpec;
 
+import sun.security.spec.DSAGenParameterSpec;
+
 /**
  * This class generates parameters for the DSA algorithm. It uses a default
  * prime modulus size of 1024 bits, which can be overwritten during
@@ -54,8 +57,14 @@
 
 public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
 
-    // the modulus length
-    private int modLen = 1024; // default
+    // the default parameters
+    private static final DSAGenParameterSpec DEFAULTS =
+        new DSAGenParameterSpec(1024, 160, 160);
+
+    // the length of prime P, subPrime Q, and seed in bits
+    private int valueL = -1;
+    private int valueN = -1;
+    private int seedLen = -1;
 
     // the source of randomness
     private SecureRandom random;
@@ -65,11 +74,7 @@
     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();
     }
 
     /**
@@ -80,19 +85,18 @@
      * @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)) {
+        if ((strength >= 512) && (strength <= 1024) && (strength % 64 == 0)) {
+            this.valueN = 160;
+        } else if (strength == 2048) {
+            this.valueN = 224;
+//      } else if (strength == 3072) {
+//          this.valueN = 256;
+        } else {
             throw new InvalidParameterException
-                ("Prime size must range from 512 to 1024 "
-                 + "and be a multiple of 64");
+                ("Prime size should be 512 - 1024, or 2048");
         }
-        this.modLen = strength;
+        this.valueL = strength;
+        this.seedLen = valueN;
         this.random = random;
     }
 
@@ -100,7 +104,7 @@
      * Initializes this parameter generator with a set of
      * algorithm-specific parameter generation values.
      *
-     * @param params the set of algorithm-specific parameter generation values
+     * @param genParamSpec the set of algorithm-specific parameter generation values
      * @param random the source of randomness
      *
      * @exception InvalidAlgorithmParameterException if the given parameter
@@ -109,7 +113,19 @@
     protected void engineInit(AlgorithmParameterSpec genParamSpec,
                               SecureRandom random)
         throws InvalidAlgorithmParameterException {
+        if (!(genParamSpec instanceof DSAGenParameterSpec)) {
             throw new InvalidAlgorithmParameterException("Invalid parameter");
+        }
+        DSAGenParameterSpec dsaGenParams = (DSAGenParameterSpec) genParamSpec;
+        if (dsaGenParams.getPrimePLength() > 2048) {
+            throw new InvalidParameterException
+                ("Prime size should be 512 - 1024, or 2048");
+        }
+        // directly initialize using the already validated values
+        this.valueL = dsaGenParams.getPrimePLength();
+        this.valueN = dsaGenParams.getSubprimeQLength();
+        this.seedLen = dsaGenParams.getSeedLength();
+        this.random = random;
     }
 
     /**
@@ -123,15 +139,21 @@
             if (this.random == null) {
                 this.random = new SecureRandom();
             }
-
-            BigInteger[] pAndQ = generatePandQ(this.random, this.modLen);
+            if (valueL == -1) {
+                try {
+                    engineInit(DEFAULTS, this.random);
+                } catch (InvalidAlgorithmParameterException iape) {
+                    // should never happen
+                }
+            }
+            BigInteger[] pAndQ = generatePandQ(this.random, valueL,
+                                               valueN, seedLen);
             BigInteger paramP = pAndQ[0];
             BigInteger paramQ = pAndQ[1];
             BigInteger paramG = generateG(paramP, paramQ);
 
-            DSAParameterSpec dsaParamSpec = new DSAParameterSpec(paramP,
-                                                                 paramQ,
-                                                                 paramG);
+            DSAParameterSpec dsaParamSpec =
+                new DSAParameterSpec(paramP, paramQ, paramG);
             algParams = AlgorithmParameters.getInstance("DSA", "SUN");
             algParams.init(dsaParamSpec);
         } catch (InvalidParameterSpecException e) {
@@ -156,102 +178,98 @@
      *
      * @param random the source of randomness to generate the
      * seed
-     * @param L the size of <code>p</code>, in bits.
+     * @param valueL the size of <code>p</code>, in bits.
+     * @param valueN the size of <code>q</code>, in bits.
+     * @param seedLen the length of <code>seed</code>, in bits.
      *
      * @return an array of BigInteger, with <code>p</code> at index 0 and
-     * <code>q</code> at index 1.
+     * <code>q</code> at index 1, the seed at index 2, and the counter value
+     * at index 3.
      */
-    BigInteger[] generatePandQ(SecureRandom random, int L) {
-        BigInteger[] result = null;
-        byte[] seed = new byte[20];
+    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();
+        }
 
-        while(result == null) {
-            for (int i = 0; i < 20; i++) {
-                seed[i] = (byte)random.nextInt();
-            }
-            result = generatePandQ(seed, L);
+        /* 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;
         }
-        return result;
-    }
 
-    /*
-     * Generates the prime and subprime parameters for DSA.
-     *
-     * <p>The seed parameter corresponds to the <code>SEED</code> parameter
-     * referenced in the FIPS specification of the DSA algorithm,
-     * and L is the size of <code>p</code>, in bits.
-     *
-     * @param seed the seed to generate the parameters
-     * @param L the size of <code>p</code>, in bits.
-     *
-     * @return an array of BigInteger, with <code>p</code> at index 0,
-     * <code>q</code> 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) {
+        BigInteger resultP, resultQ, seed = null;
+        int counter;
+        while (true) {
+            do {
+                /* Step 5 */
+                random.nextBytes(seedBytes);
+                seed = new BigInteger(1, seedBytes);
 
-        /* Useful variables */
-        int g = seed.length * 8;
-        int n = (L - 1) / 160;
-        int b = (L - 1) % 160;
+                /* Step 6 */
+                BigInteger U = new BigInteger(1, hashObj.digest(seedBytes)).
+                    mod(TWO.pow(valueN - 1));
 
-        BigInteger SEED = new BigInteger(1, seed);
-        BigInteger TWOG = TWO.pow(2 * g);
+                /* Step 7 */
+                resultQ = TWO.pow(valueN - 1).add(U).add(ONE). subtract(U.mod(TWO));
+            } while (!resultQ.isProbablePrime(primeCertainty));
 
-        /* Step 2 (Step 1 is getting seed). */
-        byte[] U1 = SHA(seed);
-        byte[] U2 = SHA(toByteArray((SEED.add(ONE)).mod(TWOG)));
+            /* 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);
+             }
+        }
 
-        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(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);
-             }
-             return null;
-         }
     }
 
     /*
@@ -262,31 +280,24 @@
      *
      * @param the <code>g</code>
      */
-    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 +306,4 @@
         }
         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];
-        }
-    }
 }
--- a/src/share/classes/sun/security/provider/DigestBase.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/DigestBase.java	Thu Apr 14 18:57:18 2016 +0100
@@ -39,7 +39,6 @@
  *  . abstract void implCompress(byte[] b, int ofs);
  *  . abstract void implDigest(byte[] out, int ofs);
  *  . abstract void implReset();
- *  . public abstract Object clone();
  *
  * See the inline documentation for details.
  *
@@ -61,7 +60,7 @@
     // buffer to store partial blocks, blockSize bytes large
     // Subclasses should not access this array directly except possibly in their
     // implDigest() method. See MD5.java as an example.
-    final byte[] buffer;
+    byte[] buffer;
     // offset into buffer
     private int bufOfs;
 
@@ -83,18 +82,6 @@
         buffer = new byte[blockSize];
     }
 
-    /**
-     * Constructor for cloning. Replicates common data.
-     */
-    DigestBase(DigestBase base) {
-        this.algorithm = base.algorithm;
-        this.digestLength = base.digestLength;
-        this.blockSize = base.blockSize;
-        this.buffer = base.buffer.clone();
-        this.bufOfs = base.bufOfs;
-        this.bytesProcessed = base.bytesProcessed;
-    }
-
     // return digest length. See JCA doc.
     protected final int engineGetDigestLength() {
         return digestLength;
@@ -206,12 +193,11 @@
      */
     abstract void implReset();
 
-    /**
-     * Clone this digest. Should be implemented as "return new MyDigest(this)".
-     * That constructor should first call "super(baseDigest)" and then copy
-     * subclass specific data.
-     */
-    public abstract Object clone();
+    public Object clone() throws CloneNotSupportedException {
+        DigestBase copy = (DigestBase) super.clone();
+        copy.buffer = copy.buffer.clone();
+        return copy;
+    }
 
     // padding used for the MD5, and SHA-* message digests
     static final byte[] padding;
@@ -223,5 +209,4 @@
         padding = new byte[136];
         padding[0] = (byte)0x80;
     }
-
 }
--- a/src/share/classes/sun/security/provider/MD2.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/MD2.java	Thu Apr 14 18:57:18 2016 +0100
@@ -39,14 +39,14 @@
 public final class MD2 extends DigestBase {
 
     // state, 48 ints
-    private final int[] X;
+    private int[] X;
 
     // checksum, 16 ints. they are really bytes, but byte arithmetic in
     // the JVM is much slower that int arithmetic.
-    private final int[] C;
+    private int[] C;
 
     // temporary store for checksum C during final digest
-    private final byte[] cBytes;
+    private byte[] cBytes;
 
     /**
      * Create a new MD2 digest. Called by the JCA framework
@@ -58,15 +58,12 @@
         cBytes = new byte[16];
     }
 
-    private MD2(MD2 base) {
-        super(base);
-        this.X = base.X.clone();
-        this.C = base.C.clone();
-        cBytes = new byte[16];
-    }
-
-    public Object clone() {
-        return new MD2(this);
+    public Object clone() throws CloneNotSupportedException {
+        MD2 copy = (MD2) super.clone();
+        copy.X = copy.X.clone();
+        copy.C = copy.C.clone();
+        copy.cBytes = new byte[16];
+        return copy;
     }
 
     // reset state and checksum
--- a/src/share/classes/sun/security/provider/MD4.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/MD4.java	Thu Apr 14 18:57:18 2016 +0100
@@ -44,9 +44,9 @@
 public final class MD4 extends DigestBase {
 
     // state of this object
-    private final int[] state;
+    private int[] state;
     // temporary buffer, used by implCompress()
-    private final int[] x;
+    private int[] x;
 
     // rotation constants
     private static final int S11 = 3;
@@ -91,16 +91,12 @@
         implReset();
     }
 
-    // Cloning constructor
-    private MD4(MD4 base) {
-        super(base);
-        this.state = base.state.clone();
-        this.x = new int[16];
-    }
-
     // clone this object
-    public Object clone() {
-        return new MD4(this);
+    public Object clone() throws CloneNotSupportedException {
+        MD4 copy = (MD4) super.clone();
+        copy.state = copy.state.clone();
+        copy.x = new int[16];
+        return copy;
     }
 
     /**
--- a/src/share/classes/sun/security/provider/MD5.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/MD5.java	Thu Apr 14 18:57:18 2016 +0100
@@ -39,9 +39,9 @@
 public final class MD5 extends DigestBase {
 
     // state of this object
-    private final int[] state;
+    private int[] state;
     // temporary buffer, used by implCompress()
-    private final int[] x;
+    private int[] x;
 
     // rotation constants
     private static final int S11 = 7;
@@ -69,16 +69,12 @@
         implReset();
     }
 
-    // Cloning constructor
-    private MD5(MD5 base) {
-        super(base);
-        this.state = base.state.clone();
-        this.x = new int[16];
-    }
-
     // clone this object
-    public Object clone() {
-        return new MD5(this);
+    public Object clone() throws CloneNotSupportedException {
+        MD5 copy = (MD5) super.clone();
+        copy.state = copy.state.clone();
+        copy.x = new int[16];
+        return copy;
     }
 
     /**
--- a/src/share/classes/sun/security/provider/ParameterCache.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/ParameterCache.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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.*;
@@ -34,6 +35,8 @@
 
 import javax.crypto.spec.DHParameterSpec;
 
+import sun.security.spec.DSAGenParameterSpec;
+
 /**
  * Cache for DSA and DH parameter specs. Used by the KeyPairGenerators
  * in the Sun, SunJCE, and SunPKCS11 provider if no parameters have been
@@ -55,11 +58,17 @@
     private final static Map<Integer,DHParameterSpec> dhCache;
 
     /**
-     * Return cached DSA parameters for the given keylength, or null if none
-     * are available in the cache.
+     * Return cached DSA parameters for the given length combination of
+     * prime and subprime, or null if none are available in the cache.
      */
-    public static DSAParameterSpec getCachedDSAParameterSpec(int keyLength) {
-        return dsaCache.get(Integer.valueOf(keyLength));
+    public static DSAParameterSpec getCachedDSAParameterSpec(int primeLen,
+            int subprimeLen) {
+        // ensure the sum is unique in all cases, i.e.
+        // case#1: (512 <= p <= 1024) AND q=160
+        // case#2: p=2048 AND q=224
+        // case#3: p=2048 AND q=256
+        // (NOT-YET-SUPPORTED)case#4: p=3072 AND q=256
+        return dsaCache.get(Integer.valueOf(primeLen+subprimeLen));
     }
 
     /**
@@ -71,18 +80,39 @@
     }
 
     /**
-     * Return DSA parameters for the given keylength. Uses cache if possible,
-     * generates new parameters and adds them to the cache otherwise.
+     * Return DSA parameters for the given primeLen. Uses cache if
+     * possible, generates new parameters and adds them to the cache
+     * otherwise.
      */
-    public static DSAParameterSpec getDSAParameterSpec(int keyLength,
+    public static DSAParameterSpec getDSAParameterSpec(int primeLen,
             SecureRandom random)
-            throws NoSuchAlgorithmException, InvalidParameterSpecException {
-        DSAParameterSpec spec = getCachedDSAParameterSpec(keyLength);
+            throws NoSuchAlgorithmException, InvalidParameterSpecException,
+                   InvalidAlgorithmParameterException {
+        if (primeLen <= 1024) {
+            return getDSAParameterSpec(primeLen, 160, random);
+        } else if (primeLen == 2048) {
+            return getDSAParameterSpec(primeLen, 224, random);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Return DSA parameters for the given primeLen and subprimeLen.
+     * Uses cache if possible, generates new parameters and adds them to the
+     * cache otherwise.
+     */
+    public static DSAParameterSpec getDSAParameterSpec(int primeLen,
+            int subprimeLen, SecureRandom random)
+            throws NoSuchAlgorithmException, InvalidParameterSpecException,
+                   InvalidAlgorithmParameterException {
+        DSAParameterSpec spec =
+            getCachedDSAParameterSpec(primeLen, subprimeLen);
         if (spec != null) {
             return spec;
         }
-        spec = getNewDSAParameterSpec(keyLength, random);
-        dsaCache.put(Integer.valueOf(keyLength), spec);
+        spec = getNewDSAParameterSpec(primeLen, subprimeLen, random);
+        dsaCache.put(Integer.valueOf(primeLen + subprimeLen), spec);
         return spec;
     }
 
@@ -107,28 +137,28 @@
     }
 
     /**
-     * Return new DSA parameters for the given keylength. Do not lookup in
-     * cache and do not cache the newly generated parameters. This method
-     * really only exists for the legacy method
+     * Return new DSA parameters for the given length combination of prime and
+     * sub prime. Do not lookup in cache and do not cache the newly generated
+     * parameters. This method really only exists for the legacy method
      * DSAKeyPairGenerator.initialize(int, boolean, SecureRandom).
      */
-    public static DSAParameterSpec getNewDSAParameterSpec(int keyLength,
-            SecureRandom random)
-            throws NoSuchAlgorithmException, InvalidParameterSpecException {
+    public static DSAParameterSpec getNewDSAParameterSpec(int primeLen,
+            int subprimeLen, SecureRandom random)
+            throws NoSuchAlgorithmException, InvalidParameterSpecException,
+                   InvalidAlgorithmParameterException {
         AlgorithmParameterGenerator gen =
                 AlgorithmParameterGenerator.getInstance("DSA");
-        gen.init(keyLength, random);
+        DSAGenParameterSpec genParams =
+            new DSAGenParameterSpec(primeLen, subprimeLen);
+        gen.init(genParams, random);
         AlgorithmParameters params = gen.generateParameters();
         DSAParameterSpec spec = params.getParameterSpec(DSAParameterSpec.class);
         return spec;
     }
 
     static {
-        // XXX change to ConcurrentHashMap once available
-        dhCache = Collections.synchronizedMap
-                        (new HashMap<Integer,DHParameterSpec>());
-        dsaCache = Collections.synchronizedMap
-                        (new HashMap<Integer,DSAParameterSpec>());
+        dhCache = new ConcurrentHashMap<Integer,DHParameterSpec>();
+        dsaCache = new ConcurrentHashMap<Integer,DSAParameterSpec>();
 
         /*
          * We support precomputed parameter for 512, 768 and 1024 bit
@@ -210,17 +240,99 @@
                            "83dfe15ae59f06928b665e807b552564014c3bfecf" +
                            "492a", 16);
 
-        dsaCache.put(Integer.valueOf(512),
+        dsaCache.put(Integer.valueOf(512+160),
                                 new DSAParameterSpec(p512, q512, g512));
-        dsaCache.put(Integer.valueOf(768),
+        dsaCache.put(Integer.valueOf(768+160),
                                 new DSAParameterSpec(p768, q768, g768));
-        dsaCache.put(Integer.valueOf(1024),
+        dsaCache.put(Integer.valueOf(1024+160),
                                 new DSAParameterSpec(p1024, q1024, g1024));
+        /*
+         * L = 2048, N = 224
+         * SEED = 584236080cfa43c09b02354135f4cc5198a19efada08bd866d601ba4
+         * counter = 2666
+         */
+        BigInteger p2048_224 =
+            new BigInteger("8f7935d9b9aae9bfabed887acf4951b6f32ec59e3b" +
+                           "af3718e8eac4961f3efd3606e74351a9c4183339b8" +
+                           "09e7c2ae1c539ba7475b85d011adb8b47987754984" +
+                           "695cac0e8f14b3360828a22ffa27110a3d62a99345" +
+                           "3409a0fe696c4658f84bdd20819c3709a01057b195" +
+                           "adcd00233dba5484b6291f9d648ef883448677979c" +
+                           "ec04b434a6ac2e75e9985de23db0292fc1118c9ffa" +
+                           "9d8181e7338db792b730d7b9e349592f6809987215" +
+                           "3915ea3d6b8b4653c633458f803b32a4c2e0f27290" +
+                           "256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea1" +
+                           "43de4b66ff04903ed5cf1623e158d487c608e97f21" +
+                           "1cd81dca23cb6e380765f822e342be484c05763939" +
+                           "601cd667", 16);
+
+        BigInteger q2048_224 =
+            new BigInteger("baf696a68578f7dfdee7fa67c977c785ef32b233ba" +
+                           "e580c0bcd5695d", 16);
+
+        BigInteger g2048_224 =
+            new BigInteger("16a65c58204850704e7502a39757040d34da3a3478" +
+                           "c154d4e4a5c02d242ee04f96e61e4bd0904abdac8f" +
+                           "37eeb1e09f3182d23c9043cb642f88004160edf9ca" +
+                           "09b32076a79c32a627f2473e91879ba2c4e744bd20" +
+                           "81544cb55b802c368d1fa83ed489e94e0fa0688e32" +
+                           "428a5c78c478c68d0527b71c9a3abb0b0be12c4468" +
+                           "9639e7d3ce74db101a65aa2b87f64c6826db3ec72f" +
+                           "4b5599834bb4edb02f7c90e9a496d3a55d535bebfc" +
+                           "45d4f619f63f3dedbb873925c2f224e07731296da8" +
+                           "87ec1e4748f87efb5fdeb75484316b2232dee553dd" +
+                           "af02112b0d1f02da30973224fe27aeda8b9d4b2922" +
+                           "d9ba8be39ed9e103a63c52810bc688b7e2ed4316e1" +
+                           "ef17dbde", 16);
+        dsaCache.put(Integer.valueOf(2048+224),
+                     new DSAParameterSpec(p2048_224, q2048_224, g2048_224));
+
+        /*
+         * L = 2048, N = 256
+         * SEED = b0b4417601b59cbc9d8ac8f935cadaec4f5fbb2f23785609ae466748d9b5a536
+         * counter = 497
+         */
+        BigInteger p2048_256 =
+            new BigInteger("95475cf5d93e596c3fcd1d902add02f427f5f3c721" +
+                           "0313bb45fb4d5bb2e5fe1cbd678cd4bbdd84c9836b" +
+                           "e1f31c0777725aeb6c2fc38b85f48076fa76bcd814" +
+                           "6cc89a6fb2f706dd719898c2083dc8d896f84062e2" +
+                           "c9c94d137b054a8d8096adb8d51952398eeca852a0" +
+                           "af12df83e475aa65d4ec0c38a9560d5661186ff98b" +
+                           "9fc9eb60eee8b030376b236bc73be3acdbd74fd61c" +
+                           "1d2475fa3077b8f080467881ff7e1ca56fee066d79" +
+                           "506ade51edbb5443a563927dbc4ba520086746175c" +
+                           "8885925ebc64c6147906773496990cb714ec667304" +
+                           "e261faee33b3cbdf008e0c3fa90650d97d3909c927" +
+                           "5bf4ac86ffcb3d03e6dfc8ada5934242dd6d3bcca2" +
+                           "a406cb0b", 16);
+
+        BigInteger q2048_256 =
+            new BigInteger("f8183668ba5fc5bb06b5981e6d8b795d30b8978d43" +
+                           "ca0ec572e37e09939a9773", 16);
+
+        BigInteger g2048_256 =
+            new BigInteger("42debb9da5b3d88cc956e08787ec3f3a09bba5f48b" +
+                           "889a74aaf53174aa0fbe7e3c5b8fcd7a53bef563b0" +
+                           "e98560328960a9517f4014d3325fc7962bf1e04937" +
+                           "0d76d1314a76137e792f3f0db859d095e4a5b93202" +
+                           "4f079ecf2ef09c797452b0770e1350782ed57ddf79" +
+                           "4979dcef23cb96f183061965c4ebc93c9c71c56b92" +
+                           "5955a75f94cccf1449ac43d586d0beee43251b0b22" +
+                           "87349d68de0d144403f13e802f4146d882e057af19" +
+                           "b6f6275c6676c8fa0e3ca2713a3257fd1b27d0639f" +
+                           "695e347d8d1cf9ac819a26ca9b04cb0eb9b7b03598" +
+                           "8d15bbac65212a55239cfc7e58fae38d7250ab9991" +
+                           "ffbc97134025fe8ce04c4399ad96569be91a546f49" +
+                           "78693c7a", 16);
+        dsaCache.put(Integer.valueOf(2048+256),
+                                new DSAParameterSpec(p2048_256, q2048_256, g2048_256));
 
         // use DSA parameters for DH as well
         dhCache.put(Integer.valueOf(512), new DHParameterSpec(p512, g512));
         dhCache.put(Integer.valueOf(768), new DHParameterSpec(p768, g768));
         dhCache.put(Integer.valueOf(1024), new DHParameterSpec(p1024, g1024));
+        dhCache.put(Integer.valueOf(2048), new DHParameterSpec(p2048_224, g2048_224));
     }
 
 }
--- a/src/share/classes/sun/security/provider/SHA.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/SHA.java	Thu Apr 14 18:57:18 2016 +0100
@@ -47,10 +47,10 @@
     // 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 final int[] W;
+    private int[] W;
 
     // state of this
-    private final int[] state;
+    private int[] state;
 
     /**
      * Creates a new SHA object.
@@ -62,19 +62,14 @@
         implReset();
     }
 
-    /**
-     * Creates a SHA object.with state (for cloning) */
-    private SHA(SHA base) {
-        super(base);
-        this.state = base.state.clone();
-        this.W = new int[80];
-    }
-
     /*
      * Clones this object.
      */
-    public Object clone() {
-        return new SHA(this);
+    public Object clone() throws CloneNotSupportedException {
+        SHA copy = (SHA) super.clone();
+        copy.state = copy.state.clone();
+        copy.W = new int[80];
+        return copy;
     }
 
     /**
--- a/src/share/classes/sun/security/provider/SHA2.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/SHA2.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, 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
@@ -40,7 +40,7 @@
  * @author      Valerie Peng
  * @author      Andreas Sterbenz
  */
-public final class SHA2 extends DigestBase {
+abstract class SHA2 extends DigestBase {
 
     private static final int ITERATION = 64;
     // Constants for each round
@@ -64,46 +64,30 @@
     };
 
     // buffer used by implCompress()
-    private final int[] W;
+    private int[] W;
 
     // state of this object
-    private final int[] state;
+    private int[] state;
+
+    // initial state value. different between SHA-224 and SHA-256
+    private final int[] initialHashes;
 
     /**
      * Creates a new SHA object.
      */
-    public SHA2() {
-        super("SHA-256", 32, 64);
+    SHA2(String name, int digestLength, int[] initialHashes) {
+        super(name, digestLength, 64);
+        this.initialHashes = initialHashes;
         state = new int[8];
         W = new int[64];
         implReset();
     }
 
     /**
-     * Creates a SHA2 object.with state (for cloning)
-     */
-    private SHA2(SHA2 base) {
-        super(base);
-        this.state = base.state.clone();
-        this.W = new int[64];
-    }
-
-    public Object clone() {
-        return new SHA2(this);
-    }
-
-    /**
      * Resets the buffers and hash value to start a new hash.
      */
     void implReset() {
-        state[0] = 0x6a09e667;
-        state[1] = 0xbb67ae85;
-        state[2] = 0x3c6ef372;
-        state[3] = 0xa54ff53a;
-        state[4] = 0x510e527f;
-        state[5] = 0x9b05688c;
-        state[6] = 0x1f83d9ab;
-        state[7] = 0x5be0cd19;
+        System.arraycopy(initialHashes, 0, state, 0, state.length);
     }
 
     void implDigest(byte[] out, int ofs) {
@@ -242,4 +226,38 @@
         state[7] += h;
     }
 
+    public Object clone() throws CloneNotSupportedException {
+        SHA2 copy = (SHA2) super.clone();
+        copy.state = copy.state.clone();
+        copy.W = new int[64];
+        return copy;
+    }
+
+    /**
+     * SHA-224 implementation class.
+     */
+    public static final class SHA224 extends SHA2 {
+        private static final int[] INITIAL_HASHES = {
+            0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+            0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+        };
+
+        public SHA224() {
+            super("SHA-224", 28, INITIAL_HASHES);
+        }
+    }
+
+    /**
+     * SHA-256 implementation class.
+     */
+    public static final class SHA256 extends SHA2 {
+        private static final int[] INITIAL_HASHES = {
+            0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+            0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+        };
+
+        public SHA256() {
+            super("SHA-256", 32, INITIAL_HASHES);
+        }
+    }
 }
--- a/src/share/classes/sun/security/provider/SHA5.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/SHA5.java	Thu Apr 14 18:57:18 2016 +0100
@@ -82,10 +82,10 @@
     };
 
     // buffer used by implCompress()
-    private final long[] W;
+    private long[] W;
 
     // state of this object
-    private final long[] state;
+    private long[] state;
 
     // initial state value. different between SHA-384 and SHA-512
     private final long[] initialHashes;
@@ -101,16 +101,6 @@
         implReset();
     }
 
-    /**
-     * Creates a SHA object with state (for cloning)
-     */
-    SHA5(SHA5 base) {
-        super(base);
-        this.initialHashes = base.initialHashes;
-        this.state = base.state.clone();
-        this.W = new long[80];
-    }
-
     final void implReset() {
         System.arraycopy(initialHashes, 0, state, 0, state.length);
     }
@@ -255,6 +245,13 @@
         state[7] += h;
     }
 
+    public Object clone() throws CloneNotSupportedException {
+        SHA5 copy = (SHA5) super.clone();
+        copy.state = copy.state.clone();
+        copy.W = new long[80];
+        return copy;
+    }
+
     /**
      * SHA-512 implementation class.
      */
@@ -270,14 +267,6 @@
         public SHA512() {
             super("SHA-512", 64, INITIAL_HASHES);
         }
-
-        private SHA512(SHA512 base) {
-            super(base);
-        }
-
-        public Object clone() {
-            return new SHA512(this);
-        }
     }
 
     /**
@@ -295,14 +284,5 @@
         public SHA384() {
             super("SHA-384", 48, INITIAL_HASHES);
         }
-
-        private SHA384(SHA384 base) {
-            super(base);
-        }
-
-        public Object clone() {
-            return new SHA384(this);
-        }
     }
-
 }
--- a/src/share/classes/sun/security/provider/SunEntries.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/provider/SunEntries.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, 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
@@ -43,6 +43,14 @@
  *   identifier strings "OID.1.3.14.3.2.13", "OID.1.3.14.3.2.27" and
  *   "OID.1.2.840.10040.4.3".
  *
+ * - SHA-2 is a set of message digest schemes described in FIPS 180-2.
+ *   SHA-2 family of hash functions includes SHA-224, SHA-256, SHA-384,
+ *   and SHA-512.
+ *
+ * - SHA-224withDSA/SHA-256withDSA are the signature schemes
+ *   described in FIPS 186-3. The associated object identifiers are
+ *   "OID.2.16.840.1.101.3.4.3.1", and "OID.2.16.840.1.101.3.4.3.2".
+
  * - DSA is the key generation scheme as described in FIPS 186.
  *   Aliases for DSA include the OID strings "OID.1.3.14.3.2.12"
  *   and "OID.1.2.840.10040.4.1".
@@ -102,11 +110,15 @@
         map.put("Signature.SHA1withDSA", "sun.security.provider.DSA$SHA1withDSA");
         map.put("Signature.NONEwithDSA", "sun.security.provider.DSA$RawDSA");
         map.put("Alg.Alias.Signature.RawDSA", "NONEwithDSA");
+        map.put("Signature.SHA224withDSA", "sun.security.provider.DSA$SHA224withDSA");
+        map.put("Signature.SHA256withDSA", "sun.security.provider.DSA$SHA256withDSA");
 
         String dsaKeyClasses = "java.security.interfaces.DSAPublicKey" +
                 "|java.security.interfaces.DSAPrivateKey";
         map.put("Signature.SHA1withDSA SupportedKeyClasses", dsaKeyClasses);
         map.put("Signature.NONEwithDSA SupportedKeyClasses", dsaKeyClasses);
+        map.put("Signature.SHA224withDSA SupportedKeyClasses", dsaKeyClasses);
+        map.put("Signature.SHA256withDSA SupportedKeyClasses", dsaKeyClasses);
 
         map.put("Alg.Alias.Signature.DSA", "SHA1withDSA");
         map.put("Alg.Alias.Signature.DSS", "SHA1withDSA");
@@ -120,6 +132,10 @@
         map.put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
         map.put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
         map.put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
+        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.1", "SHA224withDSA");
+        map.put("Alg.Alias.Signature.2.16.840.1.101.3.4.3.1", "SHA224withDSA");
+        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.2", "SHA256withDSA");
+        map.put("Alg.Alias.Signature.2.16.840.1.101.3.4.3.2", "SHA256withDSA");
 
         /*
          *  Key Pair Generator engines
@@ -139,10 +155,22 @@
 
         map.put("Alg.Alias.MessageDigest.SHA-1", "SHA");
         map.put("Alg.Alias.MessageDigest.SHA1", "SHA");
+        map.put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA");
+        map.put("Alg.Alias.MessageDigest.OID.1.3.14.3.2.26", "SHA");
 
-        map.put("MessageDigest.SHA-256", "sun.security.provider.SHA2");
+        map.put("MessageDigest.SHA-224", "sun.security.provider.SHA2$SHA224");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.4", "SHA-224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.4", "SHA-224");
+
+        map.put("MessageDigest.SHA-256", "sun.security.provider.SHA2$SHA256");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1", "SHA-256");
         map.put("MessageDigest.SHA-384", "sun.security.provider.SHA5$SHA384");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2", "SHA-384");
         map.put("MessageDigest.SHA-512", "sun.security.provider.SHA5$SHA512");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3", "SHA-512");
 
         /*
          * Algorithm Parameter Generator engines
@@ -155,15 +183,17 @@
          */
         map.put("AlgorithmParameters.DSA",
             "sun.security.provider.DSAParameters");
+        map.put("Alg.Alias.AlgorithmParameters.OID.1.2.840.10040.4.1", "DSA");
+        map.put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");
         map.put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA");
-        map.put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");
 
         /*
          * Key factories
          */
         map.put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
+        map.put("Alg.Alias.KeyFactory.OID.1.2.840.10040.4.1", "DSA");
+        map.put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
         map.put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
-        map.put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
 
         /*
          * Certificates
@@ -220,9 +250,13 @@
         /*
          * KeySize
          */
+        map.put("Signature.NONEwithDSA KeySize", "1024");
         map.put("Signature.SHA1withDSA KeySize", "1024");
-        map.put("KeyPairGenerator.DSA KeySize", "1024");
-        map.put("AlgorithmParameterGenerator.DSA KeySize", "1024");
+        map.put("Signature.SHA224withDSA KeySize", "2048");
+        map.put("Signature.SHA256withDSA KeySize", "2048");
+
+        map.put("KeyPairGenerator.DSA KeySize", "2048");
+        map.put("AlgorithmParameterGenerator.DSA KeySize", "2048");
 
         /*
          * Implementation type: software or hardware
--- a/src/share/classes/sun/security/rsa/RSASignature.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/rsa/RSASignature.java	Thu Apr 14 18:57:18 2016 +0100
@@ -39,8 +39,8 @@
  * PKCS#1 RSA signatures with the various message digest algorithms.
  * This file contains an abstract base class with all the logic plus
  * a nested static class for each of the message digest algorithms
- * (see end of the file). We support MD2, MD5, SHA-1, SHA-256, SHA-384,
- * and SHA-512.
+ * (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256,
+ * SHA-384, and SHA-512.
  *
  * @since   1.5
  * @author  Andreas Sterbenz
@@ -278,6 +278,13 @@
         }
     }
 
+    // Nested class for SHA224withRSA signatures
+    public static final class SHA224withRSA extends RSASignature {
+        public SHA224withRSA() {
+            super("SHA-224", AlgorithmId.SHA224_oid, 11);
+        }
+    }
+
     // Nested class for SHA256withRSA signatures
     public static final class SHA256withRSA extends RSASignature {
         public SHA256withRSA() {
--- a/src/share/classes/sun/security/rsa/SunRsaSignEntries.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/rsa/SunRsaSignEntries.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, 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
@@ -52,6 +52,8 @@
                 "sun.security.rsa.RSASignature$MD5withRSA");
         map.put("Signature.SHA1withRSA",
                 "sun.security.rsa.RSASignature$SHA1withRSA");
+        map.put("Signature.SHA224withRSA",
+                "sun.security.rsa.RSASignature$SHA224withRSA");
         map.put("Signature.SHA256withRSA",
                 "sun.security.rsa.RSASignature$SHA256withRSA");
         map.put("Signature.SHA384withRSA",
@@ -66,6 +68,7 @@
         map.put("Signature.MD2withRSA SupportedKeyClasses", rsaKeyClasses);
         map.put("Signature.MD5withRSA SupportedKeyClasses", rsaKeyClasses);
         map.put("Signature.SHA1withRSA SupportedKeyClasses", rsaKeyClasses);
+        map.put("Signature.SHA224withRSA SupportedKeyClasses", rsaKeyClasses);
         map.put("Signature.SHA256withRSA SupportedKeyClasses", rsaKeyClasses);
         map.put("Signature.SHA384withRSA SupportedKeyClasses", rsaKeyClasses);
         map.put("Signature.SHA512withRSA SupportedKeyClasses", rsaKeyClasses);
@@ -88,6 +91,9 @@
         map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
         map.put("Alg.Alias.Signature.1.3.14.3.2.29",            "SHA1withRSA");
 
+        map.put("Alg.Alias.Signature.1.2.840.113549.1.1.14",     "SHA224withRSA");
+        map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.14", "SHA224withRSA");
+
         map.put("Alg.Alias.Signature.1.2.840.113549.1.1.11",     "SHA256withRSA");
         map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/spec/DSAGenParameterSpec.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,129 @@
+/*
+ * 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 sun.security.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This immutable class specifies the set of parameters used for
+ * generating DSA parameters as specified in
+ * <a href="http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf">FIPS 186-3 Digital Signature Standard (DSS)</a>.
+ *
+ * @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 <code>primePLen</code> and <code>subprimeQLen</code>.
+     * The value of <code>subprimeQLen</code> 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 <code>primePLen</code>
+     * or <code>subprimeQLen</code> 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 <code>primePLen</code>, <code>subprimeQLen</code>,
+     * and <code>seedLen</code>.
+     * @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 <code>subprimeQLen</code>.
+     * @exception IllegalArgumentException if <code>primePLenLen</code>,
+     * <code>subprimeQLen</code>, or <code>seedLen</code> 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;
+    }
+}
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java	Thu Apr 14 18:57:18 2016 +0100
@@ -41,6 +41,8 @@
 
 import javax.security.auth.Subject;
 
+import sun.security.action.GetPropertyAction;
+import sun.security.util.KeyUtil;
 import sun.security.util.LegacyAlgorithmConstraints;
 import sun.security.ssl.HandshakeMessage.*;
 import sun.security.ssl.CipherSuite.*;
@@ -102,6 +104,50 @@
                     LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS,
                     new SSLAlgorithmDecomposer());
 
+    // Flag to use smart ephemeral DH key which size matches the corresponding
+    // authentication key
+    private static final boolean useSmartEphemeralDHKeys;
+
+    // Flag to use legacy ephemeral DH key which size is 512 bits for
+    // exportable cipher suites, and 768 bits for others
+    private static final boolean useLegacyEphemeralDHKeys;
+
+    // The customized ephemeral DH key size for non-exportable cipher suites.
+    private static final int customizedDHKeySize;
+
+    static {
+        String property = AccessController.doPrivileged(
+                    new GetPropertyAction("jdk.tls.ephemeralDHKeySize"));
+        if (property == null || property.length() == 0) {
+            useLegacyEphemeralDHKeys = false;
+            useSmartEphemeralDHKeys = false;
+            customizedDHKeySize = -1;
+        } else if ("matched".equals(property)) {
+            useLegacyEphemeralDHKeys = false;
+            useSmartEphemeralDHKeys = true;
+            customizedDHKeySize = -1;
+        } else if ("legacy".equals(property)) {
+            useLegacyEphemeralDHKeys = true;
+            useSmartEphemeralDHKeys = false;
+            customizedDHKeySize = -1;
+        } else {
+            useLegacyEphemeralDHKeys = false;
+            useSmartEphemeralDHKeys = false;
+
+            try {
+                customizedDHKeySize = parseUnsignedInt(property);
+                if (customizedDHKeySize < 1024 || customizedDHKeySize > 2048) {
+                    throw new IllegalArgumentException(
+                        "Customized DH key size should be positive integer " +
+                        "between 1024 and 2048 bits, inclusive");
+                }
+            } catch (NumberFormatException nfe) {
+                throw new IllegalArgumentException(
+                        "Invalid system property jdk.tls.ephemeralDHKeySize");
+            }
+        }
+    }
+
     /*
      * Constructor ... use the keys found in the auth context.
      */
@@ -1081,7 +1127,7 @@
                 }
             }
 
-            setupEphemeralDHKeys(suite.exportable);
+            setupEphemeralDHKeys(suite.exportable, privateKey);
             break;
         case K_ECDHE_RSA:
             // need RSA certs for authentication
@@ -1128,7 +1174,8 @@
             if (setupPrivateKeyAndChain("DSA") == false) {
                 return false;
             }
-            setupEphemeralDHKeys(suite.exportable);
+
+            setupEphemeralDHKeys(suite.exportable, privateKey);
             break;
         case K_ECDHE_ECDSA:
             // get preferable peer signature algorithm for server key exchange
@@ -1177,7 +1224,7 @@
             break;
         case K_DH_ANON:
             // no certs needed for anonymous
-            setupEphemeralDHKeys(suite.exportable);
+            setupEphemeralDHKeys(suite.exportable, null);
             break;
         case K_ECDH_ANON:
             // no certs needed for anonymous
@@ -1227,15 +1274,70 @@
      * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
      * We don't reuse these, for improved forward secrecy.
      */
-    private void setupEphemeralDHKeys(boolean export) {
+    private void setupEphemeralDHKeys(boolean export, Key key) {
         /*
-         * Diffie-Hellman keys ... we use 768 bit private keys due
-         * to the "use twice as many key bits as bits you want secret"
-         * rule of thumb, assuming we want the same size premaster
-         * secret with Diffie-Hellman and RSA key exchanges.  Except
-         * that exportable ciphers max out at 512 bits modulus values.
+         * 768 bits ephemeral DH private keys were used to be used in
+         * ServerKeyExchange except that exportable ciphers max out at 512
+         * bits modulus values. We still adhere to this behavior in legacy
+         * mode (system property "jdk.tls.ephemeralDHKeySize" is defined
+         * as "legacy").
+         *
+         * Older versions of OpenJDK don't support DH keys bigger
+         * than 1024 bits. We have to consider the compatibility requirement.
+         * 1024 bits DH key is always used for non-exportable cipher suites
+         * in default mode (system property "jdk.tls.ephemeralDHKeySize"
+         * is not defined).
+         *
+         * However, if applications want more stronger strength, setting
+         * system property "jdk.tls.ephemeralDHKeySize" to "matched"
+         * is a workaround to use ephemeral DH key which size matches the
+         * corresponding authentication key. For example, if the public key
+         * size of an authentication certificate is 2048 bits, then the
+         * ephemeral DH key size should be 2048 bits accordingly unless
+         * the cipher suite is exportable.  This key sizing scheme keeps
+         * the cryptographic strength consistent between authentication
+         * keys and key-exchange keys.
+         *
+         * Applications may also want to customize the ephemeral DH key size
+         * to a fixed length for non-exportable cipher suites. This can be
+         * approached by setting system property "jdk.tls.ephemeralDHKeySize"
+         * to a valid positive integer between 1024 and 2048 bits, inclusive.
+         *
+         * Note that the minimum acceptable key size is 1024 bits except
+         * exportable cipher suites or legacy mode.
+         *
+         * Note that the maximum acceptable key size is 2048 bits because
+         * DH keys bigger than 2048 are not always supported by underlying
+         * JCE providers.
+         *
+         * Note that per RFC 2246, the key size limit of DH is 512 bits for
+         * exportable cipher suites.  Because of the weakness, exportable
+         * cipher suites are deprecated since TLS v1.1 and they are not
+         * enabled by default in Oracle provider. The legacy behavior is
+         * reserved and 512 bits DH key is always used for exportable
+         * cipher suites.
          */
-        dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
+        int keySize = export ? 512 : 1024;           // default mode
+        if (!export) {
+            if (useLegacyEphemeralDHKeys) {          // legacy mode
+                keySize = 768;
+            } else if (useSmartEphemeralDHKeys) {    // matched mode
+                if (key != null) {
+                    int ks = KeyUtil.getKeySize(key);
+                    // Note that SunJCE provider only supports 2048 bits DH
+                    // keys bigger than 1024.  Please DON'T use value other
+                    // than 1024 and 2048 at present.  We may improve the
+                    // underlying providers and key size here in the future.
+                    //
+                    // keySize = ks <= 1024 ? 1024 : (ks >= 2048 ? 2048 : ks);
+                    keySize = ks <= 1024 ? 1024 : 2048;
+                } // Otherwise, anonymous cipher suites, 1024-bit is used.
+            } else if (customizedDHKeySize > 0) {    // customized mode
+                keySize = customizedDHKeySize;
+            }
+        }
+
+        dh = new DHCrypt(keySize, sslContext.getSecureRandom());
     }
 
     // Setup the ephemeral ECDH parameters.
@@ -1747,4 +1849,98 @@
 
         session.setPeerCertificates(peerCerts);
     }
+
+    /**
+     * Parses the string argument as an unsigned integer in the radix
+     * specified by the second argument.  An unsigned integer maps the
+     * values usually associated with negative numbers to positive
+     * numbers larger than {@code MAX_VALUE}.
+     *
+     * The characters in the string must all be digits of the
+     * specified radix (as determined by whether {@link
+     * java.lang.Character#digit(char, int)} returns a nonnegative
+     * value), except that the first character may be an ASCII plus
+     * sign {@code '+'} ({@code '\u005Cu002B'}). The resulting
+     * integer value is returned.
+     *
+     * <p>An exception of type {@code NumberFormatException} is
+     * thrown if any of the following situations occurs:
+     * <ul>
+     * <li>The first argument is {@code null} or is a string of
+     * length zero.
+     *
+     * <li>The radix is either smaller than
+     * {@link java.lang.Character#MIN_RADIX} or
+     * larger than {@link java.lang.Character#MAX_RADIX}.
+     *
+     * <li>Any character of the string is not a digit of the specified
+     * radix, except that the first character may be a plus sign
+     * {@code '+'} ({@code '\u005Cu002B'}) provided that the
+     * string is longer than length 1.
+     *
+     * <li>The value represented by the string is larger than the
+     * largest unsigned {@code int}, 2<sup>32</sup>-1.
+     *
+     * </ul>
+     *
+     *
+     * @param      s   the {@code String} containing the unsigned integer
+     *                  representation to be parsed
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the integer represented by the string argument in the
+     *             specified radix.
+     * @throws     NumberFormatException if the {@code String}
+     *             does not contain a parsable {@code int}.
+     */
+    private static int parseUnsignedInt(String s, int radix)
+                throws NumberFormatException {
+        if (s == null)  {
+            throw new NumberFormatException("null");
+        }
+
+        int len = s.length();
+        if (len > 0) {
+            char firstChar = s.charAt(0);
+            if (firstChar == '-') {
+                throw new
+                    NumberFormatException(String.format("Illegal leading minus sign " +
+                                                       "on unsigned string %s.", s));
+            } else {
+                if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
+                    (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
+                    return Integer.parseInt(s, radix);
+                } else {
+                    long ell = Long.parseLong(s, radix);
+                    if ((ell & 0xffff_ffff_0000_0000L) == 0) {
+                        return (int) ell;
+                    } else {
+                        throw new
+                            NumberFormatException(String.format("String value %s exceeds " +
+                                                                "range of unsigned int.", s));
+                    }
+                }
+            }
+        } else {
+            throw new NumberFormatException("For input string: \"" + s + "\"");
+        }
+    }
+
+    /**
+     * Parses the string argument as an unsigned decimal integer. The
+     * characters in the string must all be decimal digits, except
+     * that the first character may be an an ASCII plus sign {@code
+     * '+'} ({@code '\u005Cu002B'}). The resulting integer value
+     * is returned, exactly as if the argument and the radix 10 were
+     * given as arguments to the {@link
+     * #parseUnsignedInt(java.lang.String, int)} method.
+     *
+     * @param s   a {@code String} containing the unsigned {@code int}
+     *            representation to be parsed
+     * @return    the unsigned integer value represented by the argument in decimal.
+     * @throws    NumberFormatException  if the string does not contain a
+     *            parsable unsigned integer.
+     */
+    private static int parseUnsignedInt(String s) throws NumberFormatException {
+        return parseUnsignedInt(s, 10);
+    }
 }
--- a/src/share/classes/sun/security/x509/AlgorithmId.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/classes/sun/security/x509/AlgorithmId.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2010, 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
@@ -175,9 +175,9 @@
             // it's NULL. They are ---
             // rfc3370 2.1: Implementations SHOULD generate SHA-1
             // AlgorithmIdentifiers with absent parameters.
-            // rfc3447 C1: When id-sha1, id-sha256, id-sha384 and id-sha512
-            // are used in an AlgorithmIdentifier the parameters (which are
-            // optional) SHOULD be omitted.
+            // rfc3447 C1: When id-sha1, id-sha224, id-sha256, id-sha384 and
+            // id-sha512 are used in an AlgorithmIdentifier the parameters
+            // (which are optional) SHOULD be omitted.
             // rfc3279 2.3.2: The id-dsa algorithm syntax includes optional
             // domain parameters... When omitted, the parameters component
             // MUST be omitted entirely
@@ -185,6 +185,7 @@
             // is used, the AlgorithmIdentifier parameters field MUST be absent.
             /*if (
                 algid.equals((Object)SHA_oid) ||
+                algid.equals((Object)SHA224_oid) ||
                 algid.equals((Object)SHA256_oid) ||
                 algid.equals((Object)SHA384_oid) ||
                 algid.equals((Object)SHA512_oid) ||
@@ -488,7 +489,10 @@
             name.equalsIgnoreCase("SHA512")) {
             return AlgorithmId.SHA512_oid;
         }
-
+        if (name.equalsIgnoreCase("SHA-224") ||
+            name.equalsIgnoreCase("SHA224")) {
+            return AlgorithmId.SHA224_oid;
+        }
 
         // Various public key algorithms
         if (name.equalsIgnoreCase("RSA")) {
@@ -504,6 +508,9 @@
         if (name.equalsIgnoreCase("EC")) {
             return EC_oid;
         }
+        if (name.equalsIgnoreCase("ECDH")) {
+            return AlgorithmId.ECDH_oid;
+        }
 
         // Common signature types
         if (name.equalsIgnoreCase("MD5withRSA")
@@ -523,6 +530,12 @@
             || name.equalsIgnoreCase("SHA-1/DSA")) {
             return AlgorithmId.sha1WithDSA_oid;
         }
+        if (name.equalsIgnoreCase("SHA224WithDSA")) {
+            return AlgorithmId.sha224WithDSA_oid;
+        }
+        if (name.equalsIgnoreCase("SHA256WithDSA")) {
+            return AlgorithmId.sha256WithDSA_oid;
+        }
         if (name.equalsIgnoreCase("SHA1WithRSA")
             || name.equalsIgnoreCase("SHA1/RSA")) {
             return AlgorithmId.sha1WithRSAEncryption_oid;
@@ -625,6 +638,9 @@
     public static final ObjectIdentifier SHA_oid =
     ObjectIdentifier.newInternal(new int[] {1, 3, 14, 3, 2, 26});
 
+    public static final ObjectIdentifier SHA224_oid =
+    ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 4});
+
     public static final ObjectIdentifier SHA256_oid =
     ObjectIdentifier.newInternal(new int[] {2, 16, 840, 1, 101, 3, 4, 2, 1});
 
@@ -650,6 +666,7 @@
     public static final ObjectIdentifier DSA_oid;
     public static final ObjectIdentifier DSA_OIW_oid;
     public static final ObjectIdentifier EC_oid = oid(1, 2, 840, 10045, 2, 1);
+    public static final ObjectIdentifier ECDH_oid = oid(1, 3, 132, 1, 12);
     public static final ObjectIdentifier RSA_oid;
     public static final ObjectIdentifier RSAEncryption_oid;
 
@@ -664,6 +681,8 @@
                                        { 1, 2, 840, 113549, 1, 1, 5 };
     private static final int sha1WithRSAEncryption_OIW_data[] =
                                        { 1, 3, 14, 3, 2, 29 };
+    private static final int sha224WithRSAEncryption_data[] =
+                                       { 1, 2, 840, 113549, 1, 1, 14 };
     private static final int sha256WithRSAEncryption_data[] =
                                        { 1, 2, 840, 113549, 1, 1, 11 };
     private static final int sha384WithRSAEncryption_data[] =
@@ -681,12 +700,17 @@
     public static final ObjectIdentifier md5WithRSAEncryption_oid;
     public static final ObjectIdentifier sha1WithRSAEncryption_oid;
     public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid;
+    public static final ObjectIdentifier sha224WithRSAEncryption_oid;
     public static final ObjectIdentifier sha256WithRSAEncryption_oid;
     public static final ObjectIdentifier sha384WithRSAEncryption_oid;
     public static final ObjectIdentifier sha512WithRSAEncryption_oid;
     public static final ObjectIdentifier shaWithDSA_OIW_oid;
     public static final ObjectIdentifier sha1WithDSA_OIW_oid;
     public static final ObjectIdentifier sha1WithDSA_oid;
+    public static final ObjectIdentifier sha224WithDSA_oid =
+                                            oid(2, 16, 840, 1, 101, 3, 4, 3, 1);
+    public static final ObjectIdentifier sha256WithDSA_oid =
+                                            oid(2, 16, 840, 1, 101, 3, 4, 3, 2);
 
     public static final ObjectIdentifier sha1WithECDSA_oid =
                                             oid(1, 2, 840, 10045, 4, 1);
@@ -718,7 +742,6 @@
     public static ObjectIdentifier pbeWithSHA1AndRC2_40_oid =
         ObjectIdentifier.newInternal(new int[] {1, 2, 840, 113549, 1, 12, 1, 6});
 
-
     static {
     /*
      * Note the preferred OIDs are named simply with no "OIW" or
@@ -810,6 +833,14 @@
             ObjectIdentifier.newInternal(sha1WithRSAEncryption_OIW_data);
 
     /**
+     * Identifies a signing algorithm where a SHA224 digest is
+     * encrypted using an RSA private key; defined by PKCS #1.
+     * OID = 1.2.840.113549.1.1.14
+     */
+        sha224WithRSAEncryption_oid =
+            ObjectIdentifier.newInternal(sha224WithRSAEncryption_data);
+
+    /**
      * Identifies a signing algorithm where a SHA256 digest is
      * encrypted using an RSA private key; defined by PKCS #1.
      * OID = 1.2.840.113549.1.1.11
@@ -859,6 +890,7 @@
         nameTable.put(MD5_oid, "MD5");
         nameTable.put(MD2_oid, "MD2");
         nameTable.put(SHA_oid, "SHA");
+        nameTable.put(SHA224_oid, "SHA224");
         nameTable.put(SHA256_oid, "SHA256");
         nameTable.put(SHA384_oid, "SHA384");
         nameTable.put(SHA512_oid, "SHA512");
@@ -869,6 +901,8 @@
         nameTable.put(DSA_oid, "DSA");
         nameTable.put(DSA_OIW_oid, "DSA");
         nameTable.put(EC_oid, "EC");
+        nameTable.put(ECDH_oid, "ECDH");
+
         nameTable.put(sha1WithECDSA_oid, "SHA1withECDSA");
         nameTable.put(sha224WithECDSA_oid, "SHA224withECDSA");
         nameTable.put(sha256WithECDSA_oid, "SHA256withECDSA");
@@ -879,8 +913,11 @@
         nameTable.put(sha1WithDSA_oid, "SHA1withDSA");
         nameTable.put(sha1WithDSA_OIW_oid, "SHA1withDSA");
         nameTable.put(shaWithDSA_OIW_oid, "SHA1withDSA");
+        nameTable.put(sha224WithDSA_oid, "SHA224withDSA");
+        nameTable.put(sha256WithDSA_oid, "SHA256withDSA");
         nameTable.put(sha1WithRSAEncryption_oid, "SHA1withRSA");
         nameTable.put(sha1WithRSAEncryption_OIW_oid, "SHA1withRSA");
+        nameTable.put(sha224WithRSAEncryption_oid, "SHA224withRSA");
         nameTable.put(sha256WithRSAEncryption_oid, "SHA256withRSA");
         nameTable.put(sha384WithRSAEncryption_oid, "SHA384withRSA");
         nameTable.put(sha512WithRSAEncryption_oid, "SHA512withRSA");
--- a/src/share/lib/security/sunpkcs11-solaris.cfg	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/lib/security/sunpkcs11-solaris.cfg	Thu Apr 14 18:57:18 2016 +0100
@@ -17,23 +17,27 @@
 attributes = compatibility
 
 disabledMechanisms = {
-# the following mechanisms are disabled due to lack of digest cloning support
-# need to fix 6414899 first
+  CKM_DSA_KEY_PAIR_GEN
+# the following mechanisms are disabled due to CKR_SAVED_STATE_INVALID bug
+# (Solaris bug 7058108)
   CKM_MD2
   CKM_MD5
   CKM_SHA_1
+# the following mechanisms are disabled due to no cloning support
+# (Solaris bug 7050617)
   CKM_SHA256
   CKM_SHA384
   CKM_SHA512
-  CKM_DSA_KEY_PAIR_GEN
-# the following mechanisms are disabled due to performance issues (Solaris bug 6337157)
+# the following mechanisms are disabled due to performance issues
+# (Solaris bug 6337157)
   CKM_DSA_SHA1
   CKM_MD5_RSA_PKCS
   CKM_SHA1_RSA_PKCS
   CKM_SHA256_RSA_PKCS
   CKM_SHA384_RSA_PKCS
   CKM_SHA512_RSA_PKCS
-# the following mechanisms are disabled to ensure backward compatibility (Solaris bug 6545046)
+# the following mechanisms are disabled to ensure backward compatibility
+# (Solaris bug 6545046)
   CKM_DES_CBC_PAD
   CKM_DES3_CBC_PAD
   CKM_AES_CBC_PAD
--- a/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -96,8 +96,8 @@
 #define P11_ENABLE_C_CLOSESESSION
 #undef  P11_ENABLE_C_CLOSEALLSESSIONS
 #define P11_ENABLE_C_GETSESSIONINFO
-#undef  P11_ENABLE_C_GETOPERATIONSTATE
-#undef  P11_ENABLE_C_SETOPERATIONSTATE
+#define P11_ENABLE_C_GETOPERATIONSTATE
+#define P11_ENABLE_C_SETOPERATIONSTATE
 #define P11_ENABLE_C_LOGIN
 #define P11_ENABLE_C_LOGOUT
 #define P11_ENABLE_C_CREATEOBJECT
--- a/src/windows/classes/sun/security/mscapi/RSASignature.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/windows/classes/sun/security/mscapi/RSASignature.java	Thu Apr 14 18:57:18 2016 +0100
@@ -51,6 +51,7 @@
  *
  *  . "NONEwithRSA"
  *  . "SHA1withRSA"
+ *  . "SHA224withRSA"
  *  . "SHA256withRSA"
  *  . "SHA384withRSA"
  *  . "SHA512withRSA"
@@ -61,8 +62,8 @@
  *
  * NOTE: NONEwithRSA must be supplied with a pre-computed message digest.
  *       Only the following digest algorithms are supported: MD5, SHA-1,
- *       SHA-256, SHA-384, SHA-512 and a special-purpose digest algorithm
- *       which is a concatenation of SHA-1 and MD5 digests.
+ *       SHA-224, SHA-256, SHA-384, SHA-512 and a special-purpose digest
+ *       algorithm which is a concatenation of SHA-1 and MD5 digests.
  *
  * @since   1.6
  * @author  Stanley Man-Kit Ho
@@ -184,6 +185,8 @@
                 setDigestName("SHA-512");
             } else if (offset == 16) {
                 setDigestName("MD5");
+            } else if (offset == 28) {
+                setDigestName("SHA-224");
             } else {
                 throw new SignatureException(
                     "Message digest length is not supported");
@@ -203,6 +206,12 @@
         }
     }
 
+    public static final class SHA224 extends RSASignature {
+        public SHA224() {
+            super("SHA-224");
+        }
+    }
+
     public static final class SHA256 extends RSASignature {
         public SHA256() {
             super("SHA-256");
--- a/src/windows/classes/sun/security/mscapi/SunMSCAPI.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/src/windows/classes/sun/security/mscapi/SunMSCAPI.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -81,18 +81,30 @@
          */
         // NONEwithRSA must be supplied with a pre-computed message digest.
         // Only the following digest algorithms are supported: MD5, SHA-1,
-        // SHA-256, SHA-384, SHA-512 and a special-purpose digest algorithm
-        // which is a concatenation of SHA-1 and MD5 digests.
+        // SHA-224, SHA-256, SHA-384, SHA-512 and a special-purpose digest
+        // algorithm which is a concatenation of SHA-1 and MD5 digests.
         map.put("Signature.NONEwithRSA",
             "sun.security.mscapi.RSASignature$Raw");
         map.put("Signature.SHA1withRSA",
             "sun.security.mscapi.RSASignature$SHA1");
+        map.put("Signature.SHA224withRSA",
+            "sun.security.mscapi.RSASignature$SHA224");
+        map.put("Alg.Alias.Signature.1.2.840.113549.1.1.14",     "SHA224withRSA");
+        map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.14", "SHA224withRSA");
         map.put("Signature.SHA256withRSA",
             "sun.security.mscapi.RSASignature$SHA256");
+        map.put("Alg.Alias.Signature.1.2.840.113549.1.1.11",     "SHA256withRSA");
+        map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
         map.put("Signature.SHA384withRSA",
             "sun.security.mscapi.RSASignature$SHA384");
+        map.put("Alg.Alias.Signature.1.2.840.113549.1.1.12",     "SHA384withRSA");
+        map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.12", "SHA384withRSA");
+
         map.put("Signature.SHA512withRSA",
             "sun.security.mscapi.RSASignature$SHA512");
+        map.put("Alg.Alias.Signature.1.2.840.113549.1.1.13",     "SHA512withRSA");
+        map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.13", "SHA512withRSA");
+
         map.put("Signature.MD5withRSA",
             "sun.security.mscapi.RSASignature$MD5");
         map.put("Signature.MD2withRSA",
@@ -103,6 +115,8 @@
             "sun.security.mscapi.Key");
         map.put("Signature.SHA1withRSA SupportedKeyClasses",
             "sun.security.mscapi.Key");
+        map.put("Signature.SHA224withRSA SupportedKeyClasses",
+            "sun.security.mscapi.Key");
         map.put("Signature.SHA256withRSA SupportedKeyClasses",
             "sun.security.mscapi.Key");
         map.put("Signature.SHA384withRSA SupportedKeyClasses",
--- a/test/com/sun/crypto/provider/Cipher/RSA/TestOAEP.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/Cipher/RSA/TestOAEP.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, 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
@@ -58,6 +58,7 @@
         Cipher.getInstance("RSA/ECB/OAEPwithMD5andMGF1Padding");
         Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding");
         Cipher.getInstance("RSA/ECB/OAEPwithSHA-1andMGF1Padding");
+        Cipher.getInstance("RSA/ECB/OAEPwithSHA-224andMGF1Padding");
         Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding");
         Cipher.getInstance("RSA/ECB/OAEPwithSHA-384andMGF1Padding");
         Cipher.getInstance("RSA/ECB/OAEPwithSHA-512andMGF1Padding");
@@ -88,6 +89,18 @@
         // tests alias works
         testEncryptDecrypt("SHA-1", 16);
 
+        // basic test using SHA-224
+        testEncryptDecrypt("SHA-224", 0);
+        testEncryptDecrypt("SHA-224", 16);
+        testEncryptDecrypt("SHA-224", 38);
+        try {
+            testEncryptDecrypt("SHA-224", 39);
+            throw new Exception("Unexpectedly completed call");
+        } catch (IllegalBlockSizeException e) {
+            // ok
+            System.out.println(e);
+        }
+
         // basic test using SHA-256
         testEncryptDecrypt("SHA-256", 0);
         testEncryptDecrypt("SHA-256", 16);
@@ -195,6 +208,7 @@
         System.out.println("Done (" + (stop - start) + " ms).");
     }
 
+    // NOTE: OAEP can process up to (modLen - 2*digestLen - 2) bytes of data
     private static void testEncryptDecrypt(String hashAlg, int dataLength) throws Exception {
         System.out.println("Testing OAEP with hash " + hashAlg + ", " + dataLength + " bytes");
         Cipher c = Cipher.getInstance("RSA/ECB/OAEPwith" + hashAlg + "andMGF1Padding", cp);
--- a/test/com/sun/crypto/provider/Cipher/RSA/TestOAEPParameterSpec.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/Cipher/RSA/TestOAEPParameterSpec.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, 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
@@ -121,6 +121,7 @@
     public static void main(String[] argv) throws Exception {
         boolean status = true;
         byte[] p = { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04 };
+        status &= runTest("SHA-224", MGF1ParameterSpec.SHA224, p);
         status &= runTest("SHA-256", MGF1ParameterSpec.SHA256, p);
         status &= runTest("SHA-384", MGF1ParameterSpec.SHA384, p);
         status &= runTest("SHA-512", MGF1ParameterSpec.SHA512, p);
--- a/test/com/sun/crypto/provider/Cipher/RSA/TestOAEPWithParams.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/Cipher/RSA/TestOAEPWithParams.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, 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
@@ -47,10 +47,10 @@
     private static Random random = new Random();
 
     private static String MD[] = {
-        "MD5", "SHA1", "SHA-256"
+        "MD5", "SHA1", "SHA-224", "SHA-256"
     };
     private static int DATA_LENGTH[] = {
-        62, 54, 30
+        62, 54, 34, 30
     };
     public static void main(String[] args) throws Exception {
         long start = System.currentTimeMillis();
--- a/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6330287 6331386
+ * @bug 6330287 6331386 7044060
  * @summary verify that DHKeyPairGenerator returns keys of the expected size
  * (modulus and exponent)
  * -and-
@@ -57,7 +57,8 @@
      * Sizes and values for various lengths.
      */
     private enum Sizes {
-        two56(256), three84(384), five12(512), seven68(768), ten24(1024);
+        two56(256), three84(384), five12(512), seven68(768), ten24(1024),
+        twenty48(2048);
 
         private final int intSize;
         private final BigInteger bigIntValue;
@@ -82,7 +83,8 @@
         KeyPair kp;
         KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "SunJCE");
 
-        // Sun's default uses a default psize of 1024/lsize of 512
+        // Sun's default uses a default psize of 1024 and
+        // lsize of (pSize / 2) but at least 384 bits
         kp = kpg.generateKeyPair();
         checkKeyPair(kp, Sizes.ten24, Sizes.five12);
 
@@ -114,6 +116,20 @@
         kp = kpg.generateKeyPair();
         checkKeyPair(kp, Sizes.seven68, Sizes.three84);
 
+        // test w/ only pSize
+        kpg.initialize(Sizes.twenty48.getIntSize());
+        kp = kpg.generateKeyPair();
+        checkKeyPair(kp, Sizes.twenty48, Sizes.ten24);
+
+        publicKey = (DHPublicKey)kp.getPublic();
+        p = publicKey.getParams().getP();
+        g = publicKey.getParams().getG();
+
+        // test w/ all values specified
+        kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize()));
+        kp = kpg.generateKeyPair();
+        checkKeyPair(kp, Sizes.twenty48, Sizes.five12);
+
         System.out.println("OK");
     }
 
--- a/test/com/sun/crypto/provider/KeyGenerator/Test4628062.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/KeyGenerator/Test4628062.java	Thu Apr 14 18:57:18 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4628062
+ * @bug 4628062 4963723
  * @summary Verify that AES KeyGenerator supports default initialization
  *      when init is not called
  * @author Valerie Peng
@@ -34,39 +34,45 @@
 
 public class Test4628062 {
 
-    private static final String ALGO = "AES";
-    private static final int[] KEYSIZES =
-        { 16, 24, 32 }; // in bytes
+    private static final int[] AES_SIZES = { 16, 24, 32 }; // in bytes
+    private static final int[] HMACSHA224_SIZES = { 28 };
+    private static final int[] HMACSHA256_SIZES = { 32 };
+    private static final int[] HMACSHA384_SIZES = { 48 };
+    private static final int[] HMACSHA512_SIZES = { 64 };
 
-    public boolean execute() throws Exception {
-        KeyGenerator kg = KeyGenerator.getInstance(ALGO, "SunJCE");
+    public boolean execute(String algo, int[] keySizes) throws Exception {
+        KeyGenerator kg = KeyGenerator.getInstance(algo, "SunJCE");
 
         // TEST FIX 4628062
         Key keyWithDefaultSize = kg.generateKey();
         byte[] encoding = keyWithDefaultSize.getEncoded();
-        if (encoding.length == 0) {
+        int defKeyLen = encoding.length ;
+        if (defKeyLen == 0) {
             throw new Exception("default key length is 0!");
+        } else if (defKeyLen != keySizes[0]) {
+            throw new Exception("default key length mismatch!");
         }
 
         // BONUS TESTS
-        // 1. call init(int keysize) with various valid key sizes
-        // and see if the generated key is the right size.
-        for (int i=0; i<KEYSIZES.length; i++) {
-            kg.init(KEYSIZES[i]*8); // in bits
-            Key key = kg.generateKey();
-            if (key.getEncoded().length != KEYSIZES[i]) {
-                throw new Exception("key is generated with the wrong length!");
+        if (keySizes.length > 1) {
+            // 1. call init(int keysize) with various valid key sizes
+            // and see if the generated key is the right size.
+            for (int i=0; i<keySizes.length; i++) {
+                kg.init(keySizes[i]*8); // in bits
+                Key key = kg.generateKey();
+                if (key.getEncoded().length != keySizes[i]) {
+                    throw new Exception("key is generated with the wrong length!");
+                }
+            }
+            // 2. call init(int keysize) with invalid key size and see
+            // if the expected InvalidParameterException is thrown.
+            try {
+                kg.init(keySizes[0]*8+1);
+            } catch (InvalidParameterException ex) {
+            } catch (Exception ex) {
+                throw new Exception("wrong exception is thrown for invalid key size!");
             }
         }
-        // 2. call init(int keysize) with invalid key size and see
-        // if the expected InvalidParameterException is thrown.
-        try {
-            kg.init(KEYSIZES[0]*8+1);
-        } catch (InvalidParameterException ex) {
-        } catch (Exception ex) {
-            throw new Exception("wrong exception is thrown for invalid key size!");
-        }
-
         // passed all tests...hooray!
         return true;
     }
@@ -76,8 +82,20 @@
 
         Test4628062 test = new Test4628062();
         String testName = test.getClass().getName();
-        if (test.execute()) {
-            System.out.println(testName + ": Passed!");
+        if (test.execute("AES", AES_SIZES)) {
+            System.out.println(testName + ": AES Passed!");
+        }
+        if (test.execute("HmacSHA224", HMACSHA224_SIZES)) {
+            System.out.println(testName + ": HmacSHA224 Passed!");
+        }
+        if (test.execute("HmacSHA256", HMACSHA256_SIZES)) {
+            System.out.println(testName + ": HmacSHA256 Passed!");
+        }
+        if (test.execute("HmacSHA384", HMACSHA384_SIZES)) {
+            System.out.println(testName + ": HmacSHA384 Passed!");
+        }
+        if (test.execute("HmacSHA512", HMACSHA512_SIZES)) {
+            System.out.println(testName + ": HmacSHA512 Passed!");
         }
     }
 }
--- a/test/com/sun/crypto/provider/Mac/MacClone.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/Mac/MacClone.java	Thu Apr 14 18:57:18 2016 +0100
@@ -28,15 +28,33 @@
  * @author Jan Luehe
  */
 import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
 
 public class MacClone {
 
     public static void main(String[] args) throws Exception {
 
+        String[] algos = { "HmacMD5", "HmacSHA1", "HmacSHA224", "HmacSHA256",
+                           "HmacSHA384", "HmacSHA512" };
+        KeyGenerator kgen = KeyGenerator.getInstance("DES");
+        SecretKey skey = kgen.generateKey();
+        for (String algo : algos) {
+            doTest(algo, skey);
+        }
+
+        String[] algos2 = { "HmacPBESHA1" };
+        skey = new SecretKeySpec("whatever".getBytes(), "PBE");
+        for (String algo : algos2) {
+            doTest(algo, skey);
+        }
+        System.out.println("Test Passed");
+    }
+
+    private static void doTest(String algo, SecretKey skey) throws Exception {
         //
-        // Clone uninitialized Mac object
+        // Clone an uninitialized Mac object
         //
-        Mac mac = Mac.getInstance("HmacSHA1", "SunJCE");
+        Mac mac = Mac.getInstance(algo, "SunJCE");
         Mac macClone = (Mac)mac.clone();
         System.out.println(macClone.getProvider().toString());
         System.out.println(macClone.getAlgorithm());
@@ -51,12 +69,9 @@
         }
 
         //
-        // Clone initialized Mac object
+        // Clone an initialized Mac object
         //
-        KeyGenerator kgen = KeyGenerator.getInstance("DES");
-        SecretKey skey = kgen.generateKey();
-
-        mac = Mac.getInstance("HmacSHA1", "SunJCE");
+        mac = Mac.getInstance(algo, "SunJCE");
         mac.init(skey);
         macClone = (Mac)mac.clone();
         System.out.println(macClone.getProvider().toString());
@@ -66,7 +81,20 @@
         byte[] macFinal = mac.doFinal();
         byte[] macCloneFinal = macClone.doFinal();
         if (!java.util.Arrays.equals(macFinal, macCloneFinal)) {
-            throw new Exception("MAC results are different");
-        }
+            throw new Exception("ERROR: MAC result of init clone is different");
+        } else System.out.println("MAC check#1 passed");
+
+        //
+        // Clone an updated Mac object
+        //
+        mac.update((byte)0x12);
+        macClone = (Mac)mac.clone();
+        mac.update((byte)0x34);
+        macClone.update((byte)0x34);
+        macFinal = mac.doFinal();
+        macCloneFinal = macClone.doFinal();
+        if (!java.util.Arrays.equals(macFinal, macCloneFinal)) {
+            throw new Exception("ERROR: MAC result of updated clone is different");
+        } else System.out.println("MAC check#2 passed");
     }
 }
--- a/test/com/sun/crypto/provider/Mac/MacKAT.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/com/sun/crypto/provider/Mac/MacKAT.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4846410 6313661
+ * @bug 4846410 6313661 4963723
  * @summary Basic known-answer-test for Hmac and SslMac algorithms
  * @author Andreas Sterbenz
  */
@@ -147,7 +147,9 @@
     private static Test t(String alg, String input, String macvalue, String key) {
         return new MacTest(alg, b(input), b(macvalue), b(key));
     }
-
+    private static Test t(String alg, String input, String macvalue, byte[] key) {
+        return new MacTest(alg, b(input), b(macvalue), key);
+    }
     private static Test t(String alg, byte[] input, String macvalue, String key) {
         return new MacTest(alg, input, b(macvalue), b(key));
     }
@@ -155,8 +157,8 @@
     private static Test t(String alg, byte[] input, String macvalue, byte[] key) {
         return new MacTest(alg, input, b(macvalue), key);
     }
-
     private final static byte[] ALONG, BLONG, BKEY;
+    private final static byte[] BKEY_20, DDDATA_50, AAKEY_20, CDDATA_50, AAKEY_131;
 
     static {
         ALONG = new byte[1024 * 128];
@@ -166,6 +168,16 @@
         random.nextBytes(BLONG);
         BKEY = new byte[128];
         random.nextBytes(BKEY);
+        BKEY_20 = new byte[20];
+        Arrays.fill(BKEY_20, (byte) 0x0b);
+        DDDATA_50 = new byte[50];
+        Arrays.fill(DDDATA_50, (byte) 0xdd);
+        AAKEY_20 = new byte[20];
+        Arrays.fill(AAKEY_20, (byte) 0xaa);
+        CDDATA_50 = new byte[50];
+        Arrays.fill(CDDATA_50, (byte) 0xcd);
+        AAKEY_131 = new byte[131];
+        Arrays.fill(AAKEY_131, (byte) 0xaa);
     }
 
     private final static Test[] tests = {
@@ -203,15 +215,24 @@
                 "1b:34:61:29:05:0d:73:db:25:d0:dd:64:06:29:f6:8a"),
         t("HmacSHA512", BLONG, "fb:cf:4b:c6:d5:49:5a:5b:0b:d9:2a:32:f5:fa:68:d2:68:a4:0f:ae:53:fc:49:12:e6:1d:53:cf:b2:cb:c5:c5:f2:2d:86:bd:14:61:30:c3:a6:6f:44:1f:77:9b:aa:a1:22:48:a9:dd:d0:45:86:d1:a1:82:53:13:c4:03:06:a3",
                 BKEY),
+        // Test vectors From RFC4231
+        t("HmacSHA224", s("Hi There"), "89:6f:b1:12:8a:bb:df:19:68:32:10:7c:d4:9d:f3:3f:47:b4:b1:16:99:12:ba:4f:53:68:4b:22", BKEY_20),
+        t("HmacSHA224", s("what do ya want for nothing?"), "a3:0e:01:09:8b:c6:db:bf:45:69:0f:3a:7e:9e:6d:0f:8b:be:a2:a3:9e:61:48:00:8f:d0:5e:44", s("Jefe")),
+        t("HmacSHA224", DDDATA_50, "7f:b3:cb:35:88:c6:c1:f6:ff:a9:69:4d:7d:6a:d2:64:93:65:b0:c1:f6:5d:69:d1:ec:83:33:ea", AAKEY_20),
+        t("HmacSHA224", CDDATA_50, "6c:11:50:68:74:01:3c:ac:6a:2a:bc:1b:b3:82:62:7c:ec:6a:90:d8:6e:fc:01:2d:e7:af:ec:5a", "01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19"),
+        t("HmacSHA224", s("Test Using Larger Than Block-Size Key - Hash Key First"), "95:e9:a0:db:96:20:95:ad:ae:be:9b:2d:6f:0d:bc:e2:d4:99:f1:12:f2:d2:b7:27:3f:a6:87:0e", AAKEY_131),
+        t("HmacSHA224", s("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."), "3a:85:41:66:ac:5d:9f:02:3f:54:d5:17:d0:b3:9d:bd:94:67:70:db:9c:2b:95:c9:f6:f5:65:d1", AAKEY_131),
     };
 
     static void runTests(Test[] tests) throws Exception {
         long start = System.currentTimeMillis();
         Provider p = Security.getProvider("SunJCE");
         System.out.println("Testing provider " + p.getName() + "...");
+        Mac.getInstance("HmacSHA224", p);
         Mac.getInstance("HmacSHA256", p);
         Mac.getInstance("HmacSHA384", p);
         Mac.getInstance("HmacSHA512", p);
+        KeyGenerator.getInstance("HmacSHA224", p);
         KeyGenerator.getInstance("HmacSHA256", p);
         KeyGenerator.getInstance("HmacSHA384", p);
         KeyGenerator.getInstance("HmacSHA512", p);
--- a/test/sun/security/mscapi/SignUsingNONEwithRSA.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/mscapi/SignUsingNONEwithRSA.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -48,6 +48,12 @@
             0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30,
             0x31, 0x32, 0x33, 0x34, 0x35, 0x36
         },
+        // A SHA-224 hash
+        new byte[] {
+            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
+            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28
+        },
         // A SHA-256 hash
         new byte[] {
             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
--- a/test/sun/security/mscapi/SignUsingSHA2withRSA.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/mscapi/SignUsingSHA2withRSA.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -78,12 +78,16 @@
         generatedSignatures.add(signUsing("SHA256withRSA", privateKey));
         generatedSignatures.add(signUsing("SHA384withRSA", privateKey));
         generatedSignatures.add(signUsing("SHA512withRSA", privateKey));
+        generatedSignatures.add(signUsing("SHA224withRSA", privateKey));
+
 
         System.out.println("-------------------------------------------------");
 
         verifyUsing("SHA256withRSA", publicKey, generatedSignatures.get(0));
         verifyUsing("SHA384withRSA", publicKey, generatedSignatures.get(1));
         verifyUsing("SHA512withRSA", publicKey, generatedSignatures.get(2));
+        verifyUsing("SHA224withRSA", publicKey, generatedSignatures.get(3));
+
 
         System.out.println("-------------------------------------------------");
     }
--- a/test/sun/security/pkcs11/MessageDigest/DigestKAT.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/pkcs11/MessageDigest/DigestKAT.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -174,6 +174,12 @@
         t("SHA1", s("12345678901234567890123456789012345678901234567890123456789012345678901234567890"), "50:ab:f5:70:6a:15:09:90:a0:8b:2c:5e:a4:0f:a0:e5:85:55:47:32"),
         t("SHA1", ALONG, "ce:56:53:59:08:04:ba:a9:36:9f:72:d4:83:ed:9e:ba:72:f0:4d:29"),
 
+        t("SHA-224", s(""), "d1:4a:02:8c:2a:3a:2b:c9:47:61:02:bb:28:82:34:c4:15:a2:b0:1f:82:8e:a6:2a:c5:b3:e4:2f"),
+        t("SHA-224", s("abc"), "23:09:7d:22:34:05:d8:22:86:42:a4:77:bd:a2:55:b3:2a:ad:bc:e4:bd:a0:b3:f7:e3:6c:9d:a7"),
+        t("SHA-224", s("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), "75:38:8b:16:51:27:76:cc:5d:ba:5d:a1:fd:89:01:50:b0:c6:45:5c:b4:f5:8b:19:52:52:25:25"),
+        t("SHA-224", s("The quick brown fox jumps over the lazy dog"), "73:0e:10:9b:d7:a8:a3:2b:1c:b9:d9:a0:9a:a2:32:5d:24:30:58:7d:db:c0:c3:8b:ad:91:15:25"),
+        t("SHA-224", s("The quick brown fox jumps over the lazy dog."), "61:9c:ba:8e:8e:05:82:6e:9b:8c:51:9c:0a:5c:68:f4:fb:65:3e:8a:3d:8a:a0:4b:b2:c8:cd:4c"),
+
         t("SHA-256", s(""), "e3:b0:c4:42:98:fc:1c:14:9a:fb:f4:c8:99:6f:b9:24:27:ae:41:e4:64:9b:93:4c:a4:95:99:1b:78:52:b8:55"),
         t("SHA-256", s("a"), "ca:97:81:12:ca:1b:bd:ca:fa:c2:31:b3:9a:23:dc:4d:a7:86:ef:f8:14:7c:4e:72:b9:80:77:85:af:ee:48:bb"),
         t("SHA-256", s("abc"), "ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs11/MessageDigest/TestCloning.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6414899
+ * @summary Ensure the cloning functionality works.
+ * @author Valerie Peng
+ * @library ..
+ */
+
+import java.util.*;
+
+import java.security.*;
+
+public class TestCloning extends PKCS11Test {
+
+    private static final String[] ALGOS = {
+        "MD2", "MD5", "SHA1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"
+    };
+
+    public static void main(String[] args) throws Exception {
+        main(new TestCloning());
+    }
+
+    private static final byte[] data1 = new byte[10];
+    private static final byte[] data2 = new byte[10*1024];
+
+
+    public void main(Provider p) throws Exception {
+        Random r = new Random();
+        byte[] data1 = new byte[10];
+        byte[] data2 = new byte[2*1024];
+        r.nextBytes(data1);
+        r.nextBytes(data2);
+        System.out.println("Testing against provider " + p.getName());
+        for (int i = 0; i < ALGOS.length; i++) {
+            if (p.getService("MessageDigest", ALGOS[i]) == null) {
+                System.out.println(ALGOS[i] + " is not supported, skipping");
+                continue;
+            } else {
+                System.out.println("Testing " + ALGOS[i] + " of " + p.getName());
+                MessageDigest md = MessageDigest.getInstance(ALGOS[i], p);
+                try {
+                    md = testCloning(md, p);
+                    // repeat the test again after generating digest once
+                    for (int j = 0; j < 10; j++) {
+                        md = testCloning(md, p);
+                    }
+                } catch (Exception ex) {
+                    if (ALGOS[i] == "MD2" &&
+                        p.getName().equalsIgnoreCase("SunPKCS11-NSS")) {
+                        // known bug in NSS; ignore for now
+                        System.out.println("Ignore Known bug in MD2 of NSS");
+                        continue;
+                    }
+                    throw ex;
+                }
+            }
+        }
+    }
+
+    private static MessageDigest testCloning(MessageDigest mdObj, Provider p)
+        throws Exception {
+
+        // copy#0: clone at state BLANK w/o any data
+        MessageDigest mdCopy0 = (MessageDigest) mdObj.clone();
+
+        // copy#1: clone again at state BUFFERED w/ very short data
+        mdObj.update(data1);
+        mdCopy0.update(data1);
+        MessageDigest mdCopy1 = (MessageDigest) mdObj.clone();
+
+        // copy#2: clone again after updating it w/ long data to trigger
+        // the state into INIT
+        mdObj.update(data2);
+        mdCopy0.update(data2);
+        mdCopy1.update(data2);
+        MessageDigest mdCopy2 = (MessageDigest) mdObj.clone();
+
+        // copy#3: clone again after updating it w/ very short data
+        mdObj.update(data1);
+        mdCopy0.update(data1);
+        mdCopy1.update(data1);
+        mdCopy2.update(data1);
+        MessageDigest mdCopy3 = (MessageDigest) mdObj.clone();
+
+        // copy#4: clone again after updating it w/ long data
+        mdObj.update(data2);
+        mdCopy0.update(data2);
+        mdCopy1.update(data2);
+        mdCopy2.update(data2);
+        mdCopy3.update(data2);
+        MessageDigest mdCopy4 = (MessageDigest) mdObj.clone();
+
+        // check digest equalities
+        byte[] answer = mdObj.digest();
+        byte[] result0 = mdCopy0.digest();
+        byte[] result1 = mdCopy1.digest();
+        byte[] result2 = mdCopy2.digest();
+        byte[] result3 = mdCopy3.digest();
+        byte[] result4 = mdCopy4.digest();
+
+
+        check(answer, result0, "copy0");
+        check(answer, result1, "copy1");
+        check(answer, result2, "copy2");
+        check(answer, result3, "copy3");
+        check(answer, result4, "copy4");
+
+        return mdCopy3;
+    }
+
+    private static void check(byte[] d1, byte[] d2, String copyName)
+            throws Exception {
+        if (Arrays.equals(d1, d2) == false) {
+            throw new RuntimeException(copyName + " digest mismatch!");
+        }
+    }
+}
+
--- a/test/sun/security/pkcs11/Signature/TestRSAKeyLength.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/pkcs11/Signature/TestRSAKeyLength.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -37,7 +37,7 @@
     }
     public void main(Provider p) throws Exception {
         boolean isValidKeyLength[] = { true, true, false, false };
-        String algos[] = { "SHA1withRSA", "SHA256withRSA",
+        String algos[] = { "SHA1withRSA", "SHA224withRSA", "SHA256withRSA",
                            "SHA384withRSA", "SHA512withRSA" };
         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p);
         kpg.initialize(512);
--- a/test/sun/security/pkcs11/ec/TestCurves.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/pkcs11/ec/TestCurves.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -68,6 +68,7 @@
             kp2 = kpg.generateKeyPair();
 
             testSigning(p, "SHA1withECDSA", data, kp1, kp2);
+            testSigning(p, "SHA224withECDSA", data, kp1, kp2);
             testSigning(p, "SHA256withECDSA", data, kp1, kp2);
             testSigning(p, "SHA384withECDSA", data, kp1, kp2);
             testSigning(p, "SHA512withECDSA", data, kp1, kp2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs11/ec/TestECDH2.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6405536
+ * @summary basic test of ECDSA signatures for P-256 and P-384 from the
+ * example data in "Suite B Implementer's Guide to FIPS 186-3".
+ * @library ..
+ * @library ../../../../java/security/testlibrary
+ * @compile -XDignore.symbol.file TestECDH2.java
+ * @run main TestECDH2
+ */
+
+import java.io.*;
+import java.util.*;
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import javax.crypto.*;
+
+import sun.security.ec.NamedCurve;
+
+public class TestECDH2 extends PKCS11Test {
+
+    // values of the keys we use for the tests
+
+    // keypair using NIST P-256
+    private final static String privD256 = "70a12c2db16845ed56ff68cfc21a472b3f04d7d6851bf6349f2d7d5b3452b38a";
+    private final static String pubX256 = "8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8";
+    private final static String pubY256 = "d8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9";
+
+    // keypair using NIST P-384
+    private final static String privD384 = "c838b85253ef8dc7394fa5808a5183981c7deef5a69ba8f4f2117ffea39cfcd90e95f6cbc854abacab701d50c1f3cf24";
+    private final static String pubX384 = "1fbac8eebd0cbf35640b39efe0808dd774debff20a2a329e91713baf7d7f3c3e81546d883730bee7e48678f857b02ca0";
+    private final static String pubY384 = "eb213103bd68ce343365a8a4c3d4555fa385f5330203bdd76ffad1f3affb95751c132007e1b240353cb0a4cf1693bdf9";
+
+    private KeyFactory kf = null;
+    private KeyPairGenerator kpg = null;
+
+    private static void testKeyAgreement(KeyPair kpA, KeyPair kpB, Provider p)
+        throws Exception {
+        KeyAgreement ka1 = KeyAgreement.getInstance("ECDH", p);
+        ka1.init(kpA.getPrivate());
+        ka1.doPhase(kpB.getPublic(), true);
+        byte[] s1 = ka1.generateSecret();
+
+        KeyAgreement ka2 = KeyAgreement.getInstance("ECDH", p);
+        ka2.init(kpB.getPrivate());
+        ka2.doPhase(kpA.getPublic(), true);
+        byte[] s2 = ka2.generateSecret();
+        if (Arrays.equals(s1, s2) == false) {
+            System.out.println("expected: " + toString(s1));
+            System.out.println("actual:   " + toString(s2));
+            throw new Exception("Generated secrets do not match");
+        }
+    }
+
+    private KeyPair genECKeyPair(String curvName, String privD, String pubX,
+                                 String pubY) throws Exception {
+        ECParameterSpec ecParams = NamedCurve.getECParameterSpec(curvName);
+        ECPrivateKeySpec privKeySpec =
+            new ECPrivateKeySpec(new BigInteger(privD, 16), ecParams);
+        ECPublicKeySpec pubKeySpec =
+            new ECPublicKeySpec(new ECPoint(new BigInteger(pubX, 16),
+                                            new BigInteger(pubY, 16)),
+                                ecParams);
+        PrivateKey privKey = kf.generatePrivate(privKeySpec);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        return new KeyPair(pubKey, privKey);
+    }
+    private KeyPair genECKeyPair(String curvName) throws Exception {
+        ECGenParameterSpec genParams = new ECGenParameterSpec(curvName);
+        kpg.initialize(genParams, null);
+        return kpg.generateKeyPair();
+    }
+    public static void main(String[] args) throws Exception {
+        main(new TestECDH2());
+    }
+
+    public void main(Provider provider) throws Exception {
+        if (provider.getService("KeyAgreement", "ECDH") == null) {
+            System.out.println("ECDH not supported, skipping");
+            return;
+        }
+
+        kf = KeyFactory.getInstance("EC", provider);
+        kpg = KeyPairGenerator.getInstance("EC", provider);
+
+        System.out.println("Testing against NIST P-256");
+
+        long start = System.currentTimeMillis();
+        KeyPair kp256A = genECKeyPair("secp256r1", privD256, pubX256, pubY256);
+        KeyPair kp256B = genECKeyPair("secp256r1");
+        testKeyAgreement(kp256A, kp256B, provider);
+
+        System.out.println("Testing against NIST P-384");
+        KeyPair kp384A = genECKeyPair("secp384r1", privD384, pubX384, pubY384);
+        KeyPair kp384B = genECKeyPair("secp384r1");
+        testKeyAgreement(kp384A, kp384B, provider);
+
+        long stop = System.currentTimeMillis();
+        System.out.println("All tests passed (" + (stop - start) + " ms).");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/pkcs11/ec/TestECDSA2.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6405536
+ * @summary basic test of ECDSA signatures for P-256 and P-384 from the
+ * example data in "Suite B Implementer's Guide to FIPS 186-3".
+ * @library ..
+ * @library ../../../../java/security/testlibrary
+ * @compile -XDignore.symbol.file TestECDSA2.java
+ * @run main TestECDSA2
+ */
+
+import java.io.*;
+import java.util.*;
+import java.math.BigInteger;
+
+import java.security.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+
+import sun.security.ec.NamedCurve;
+
+public class TestECDSA2 extends PKCS11Test {
+
+    // values of the keys we use for the tests
+
+    // keypair using NIST P-256
+    private final static String privD256 = "70a12c2db16845ed56ff68cfc21a472b3f04d7d6851bf6349f2d7d5b3452b38a";
+    private final static String pubX256 = "8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8";
+    private final static String pubY256 = "d8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9";
+
+    // keypair using NIST P-384
+    private final static String privD384 = "c838b85253ef8dc7394fa5808a5183981c7deef5a69ba8f4f2117ffea39cfcd90e95f6cbc854abacab701d50c1f3cf24";
+    private final static String pubX384 = "1fbac8eebd0cbf35640b39efe0808dd774debff20a2a329e91713baf7d7f3c3e81546d883730bee7e48678f857b02ca0";
+    private final static String pubY384 = "eb213103bd68ce343365a8a4c3d4555fa385f5330203bdd76ffad1f3affb95751c132007e1b240353cb0a4cf1693bdf9";
+
+    // data to be signed
+    private final static byte[] data = "This is only a test message. It is 48 bytes long".getBytes();
+
+    private KeyFactory kf = null;
+
+    private static void testSignAndVerify(String alg, KeyPair kp, Provider p) throws Exception {
+        Signature s = Signature.getInstance(alg, p);
+        s.initSign(kp.getPrivate());
+        s.update(data);
+        byte[] result = s.sign();
+
+        s.initVerify(kp.getPublic());
+        s.update(data);
+        if (!s.verify(result)) {
+            throw new Exception("Error: Signature verification failed");
+        }
+        System.out.println(p.getName() + ": " + alg + " Passed");
+    }
+
+    private KeyPair genECKeyPair(String curvName, String privD, String pubX, String pubY) throws Exception {
+        ECParameterSpec ecParams = NamedCurve.getECParameterSpec(curvName);
+        ECPrivateKeySpec privKeySpec =
+            new ECPrivateKeySpec(new BigInteger(privD, 16), ecParams);
+        ECPublicKeySpec pubKeySpec =
+            new ECPublicKeySpec(new ECPoint(new BigInteger(pubX, 16), new BigInteger(pubY, 16)),
+                                ecParams);
+        PrivateKey privKey = kf.generatePrivate(privKeySpec);
+        PublicKey pubKey = kf.generatePublic(pubKeySpec);
+        return new KeyPair(pubKey, privKey);
+    }
+
+    public static void main(String[] args) throws Exception {
+        main(new TestECDSA2());
+    }
+
+    public void main(Provider provider) throws Exception {
+        boolean testP256 =
+            (provider.getService("Signature", "SHA256withECDSA") != null);
+
+        boolean testP384 =
+            (provider.getService("Signature", "SHA384withECDSA") != null);
+
+        if (!testP256 && !testP384) {
+            System.out.println("ECDSA not supported, skipping");
+            return;
+        }
+
+        kf = KeyFactory.getInstance("EC", provider);
+
+        long start = System.currentTimeMillis();
+        if (testP256) {
+            // can use secp256r1, NIST P-256, X9.62 prime256v1, or 1.2.840.10045.3.1.7
+            KeyPair kp = genECKeyPair("secp256r1", privD256, pubX256, pubY256);
+            testSignAndVerify("SHA256withECDSA", kp, provider);
+        }
+        if (testP384) {
+            // can use secp384r1, NIST P-384, 1.3.132.0.34
+            KeyPair kp = genECKeyPair("secp384r1", privD384, pubX384, pubY384);
+            testSignAndVerify("SHA384withECDSA", kp, provider);
+        }
+        long stop = System.currentTimeMillis();
+        System.out.println("All tests passed (" + (stop - start) + " ms).");
+    }
+}
--- a/test/sun/security/pkcs11/rsa/TestKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/pkcs11/rsa/TestKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -61,6 +61,7 @@
         testSignature("MD2withRSA", privateKey, publicKey);
         testSignature("MD5withRSA", privateKey, publicKey);
         testSignature("SHA1withRSA", privateKey, publicKey);
+        testSignature("SHA224withRSA", privateKey, publicKey);
         testSignature("SHA256withRSA", privateKey, publicKey);
         RSAPublicKey rsaKey = (RSAPublicKey)publicKey;
         if (rsaKey.getModulus().bitLength() > 512) {
--- a/test/sun/security/pkcs11/rsa/TestSignatures.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/pkcs11/rsa/TestSignatures.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -81,6 +81,7 @@
         testSignature("MD2withRSA", privateKey, publicKey);
         testSignature("MD5withRSA", privateKey, publicKey);
         testSignature("SHA1withRSA", privateKey, publicKey);
+        testSignature("SHA224withRSA", privateKey, publicKey);
         testSignature("SHA256withRSA", privateKey, publicKey);
         RSAPublicKey rsaKey = (RSAPublicKey)publicKey;
         if (rsaKey.getModulus().bitLength() > 512) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/DSA/TestAlgParameterGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7044060
+ * @summary verify that DSA parameter generation works
+ * @run main/othervm/timeout=300 TestAlgParameterGenerator
+ */
+import java.security.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+
+import sun.security.spec.DSAGenParameterSpec;
+
+public class TestAlgParameterGenerator {
+
+    private static void checkParamStrength(AlgorithmParameters param,
+                                           int strength) throws Exception {
+        String algo = param.getAlgorithm();
+        if (!algo.equalsIgnoreCase("DSA")) {
+            throw new Exception("Unexpected type of parameters: " + algo);
+        }
+        DSAParameterSpec spec = param.getParameterSpec(DSAParameterSpec.class);
+        int valueL = spec.getP().bitLength();
+        if (strength != valueL) {
+            System.out.println("Expected " + strength + " but actual " + valueL);
+            throw new Exception("Wrong P strength");
+        }
+    }
+    private static void checkParamStrength(AlgorithmParameters param,
+                                           DSAGenParameterSpec genParam)
+        throws Exception {
+        String algo = param.getAlgorithm();
+        if (!algo.equalsIgnoreCase("DSA")) {
+            throw new Exception("Unexpected type of parameters: " + algo);
+        }
+        DSAParameterSpec spec = param.getParameterSpec(DSAParameterSpec.class);
+        int valueL = spec.getP().bitLength();
+        int strength = genParam.getPrimePLength();
+        if (strength != valueL) {
+            System.out.println("P: Expected " + strength + " but actual " + valueL);
+            throw new Exception("Wrong P strength");
+        }
+        int valueN = spec.getQ().bitLength();
+        strength = genParam.getSubprimeQLength();
+        if (strength != valueN) {
+            System.out.println("Q: Expected " + strength + " but actual " + valueN);
+            throw new Exception("Wrong Q strength");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        AlgorithmParameterGenerator apg =
+            AlgorithmParameterGenerator.getInstance("DSA", "SUN");
+
+        long start, stop;
+        // make sure no-init still works
+        start = System.currentTimeMillis();
+        AlgorithmParameters param = apg.generateParameters();
+        stop = System.currentTimeMillis();
+        System.out.println("Time: " + (stop - start) + " ms.");
+        checkParamStrength(param, 1024);
+
+        // make sure the old model works
+        int[] strengths = { 512, 768, 1024 };
+        for (int i = 0; i < strengths.length; i++) {
+            int sizeP = strengths[i];
+            System.out.println("Generating " + sizeP + "-bit DSA Parameters");
+            start = System.currentTimeMillis();
+            apg.init(sizeP);
+            param = apg.generateParameters();
+            stop = System.currentTimeMillis();
+            System.out.println("Time: " + (stop - start) + " ms.");
+            checkParamStrength(param, sizeP);
+        }
+
+        // now the newer model
+        DSAGenParameterSpec spec1 = new DSAGenParameterSpec(1024, 160);
+        DSAGenParameterSpec spec2 = new DSAGenParameterSpec(2048, 224);
+        DSAGenParameterSpec spec3 = new DSAGenParameterSpec(2048, 256);
+        //DSAGenParameterSpec spec4 = new DSAGenParameterSpec(3072, 256);
+        DSAGenParameterSpec[] specSet = {
+            spec1, spec2, spec3//, spec4
+        };
+        for (int i = 0; i < specSet.length; i++) {
+            DSAGenParameterSpec genParam = specSet[i];
+            System.out.println("Generating (" + genParam.getPrimePLength() +
+                               ", " + genParam.getSubprimeQLength() +
+                               ") DSA Parameters");
+            start = System.currentTimeMillis();
+            apg.init(genParam, null);
+            param = apg.generateParameters();
+            stop = System.currentTimeMillis();
+            System.out.println("Time: " + (stop - start) + " ms.");
+            checkParamStrength(param, genParam);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/DSA/TestDSA2.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ *
+ * 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.
+ */
+/*
+ * @test
+ * @bug 7044060
+ * @run main/othervm/timeout=250 TestDSA2
+ * @summary verify that DSA signature works using SHA and SHA-224 and SHA-256 digests.
+ */
+
+
+import java.security.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+
+public class TestDSA2 {
+
+    // NOTE: need to explictly specify provider since the more
+    // preferred provider SunPKCS11 provider only supports up
+    // 1024 bits.
+    private static final String PROV = "SUN";
+
+    private static final String[] SIG_ALGOS = {
+        "SHA1withDSA", "SHA224withDSA", "SHA256withDSA"
+    };
+
+    private static final int[] KEYSIZES = {
+        1024, 2048
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean[] expectedToPass = { true, true, true };
+        test(1024, expectedToPass);
+        boolean[] expectedToPass2 = { true, true, true };
+        test(2048, expectedToPass2);
+    }
+
+    private static void test(int keySize, boolean[] testStatus)
+        throws Exception {
+        byte[] data = "1234567890".getBytes();
+        System.out.println("Test against key size: " + keySize);
+
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", PROV);
+        keyGen.initialize(keySize, new SecureRandom());
+        KeyPair pair = keyGen.generateKeyPair();
+
+        if (testStatus.length != SIG_ALGOS.length) {
+            throw new RuntimeException("TestError: incorrect status array!");
+        }
+        for (int i = 0; i < SIG_ALGOS.length; i++) {
+            Signature dsa = Signature.getInstance(SIG_ALGOS[i], PROV);
+            try {
+                dsa.initSign(pair.getPrivate());
+                dsa.update(data);
+                byte[] sig = dsa.sign();
+                dsa.initVerify(pair.getPublic());
+                dsa.update(data);
+                boolean verifies = dsa.verify(sig);
+                if (verifies == testStatus[i]) {
+                    System.out.println(SIG_ALGOS[i] + ": Passed");
+                } else {
+                    System.out.println(SIG_ALGOS[i] + ": should " +
+                                       (testStatus[i]? "pass":"fail"));
+                    throw new RuntimeException(SIG_ALGOS[i] + ": Unexpected Test result!");
+
+                }
+            } catch (Exception ex) {
+                if (testStatus[i]) {
+                    ex.printStackTrace();
+                    throw new RuntimeException(SIG_ALGOS[i] + ": Unexpected exception " + ex);
+                } else {
+                    System.out.println(SIG_ALGOS[i] + ": Passed, expected " + ex);
+                }
+            }
+        }
+    }
+}
--- a/test/sun/security/provider/DSA/TestKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/provider/DSA/TestKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4800108
- * @summary verify that precomputed DSA parameters are always used (512, 768, 1024 bit)
+ * @summary verify that precomputed DSA parameters are always used (512, 768, 1024, 2048 bit)
  * @run main/othervm/timeout=15 TestKeyPairGenerator
  */
 
@@ -78,6 +78,10 @@
         kp = kpg.generateKeyPair();
         checkKeyLength(kp, 512);
 
+        kpg.initialize(2048);
+        kp = kpg.generateKeyPair();
+        checkKeyLength(kp, 2048);
+
         long stop = System.currentTimeMillis();
         System.out.println("Time: " + (stop - start) + " ms.");
     }
--- a/test/sun/security/provider/MessageDigest/DigestKAT.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/provider/MessageDigest/DigestKAT.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4819771 4834179 5008306
+ * @bug 4819771 4834179 5008306 4963723
  * @summary Basic known-answer-test for all our MessageDigest algorithms
  * @author Andreas Sterbenz
  */
@@ -190,6 +190,12 @@
         t("SHA1", ALONG, "ce:56:53:59:08:04:ba:a9:36:9f:72:d4:83:ed:9e:ba:72:f0:4d:29"),
         t("SHA1", BLONG, "1d:a8:1a:de:8d:1e:d0:82:ba:12:13:e2:56:26:30:fc:05:b8:8d:a6"),
 
+        t("SHA-224", s(""), "d1:4a:02:8c:2a:3a:2b:c9:47:61:02:bb:28:82:34:c4:15:a2:b0:1f:82:8e:a6:2a:c5:b3:e4:2f"),
+        t("SHA-224", s("abc"), "23:09:7d:22:34:05:d8:22:86:42:a4:77:bd:a2:55:b3:2a:ad:bc:e4:bd:a0:b3:f7:e3:6c:9d:a7"),
+        t("SHA-224", s("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), "75:38:8b:16:51:27:76:cc:5d:ba:5d:a1:fd:89:01:50:b0:c6:45:5c:b4:f5:8b:19:52:52:25:25"),
+        t("SHA-224", s("The quick brown fox jumps over the lazy dog"), "73:0e:10:9b:d7:a8:a3:2b:1c:b9:d9:a0:9a:a2:32:5d:24:30:58:7d:db:c0:c3:8b:ad:91:15:25"),
+        t("SHA-224", s("The quick brown fox jumps over the lazy dog."), "61:9c:ba:8e:8e:05:82:6e:9b:8c:51:9c:0a:5c:68:f4:fb:65:3e:8a:3d:8a:a0:4b:b2:c8:cd:4c"),
+
         t("SHA-256", s(""), "e3:b0:c4:42:98:fc:1c:14:9a:fb:f4:c8:99:6f:b9:24:27:ae:41:e4:64:9b:93:4c:a4:95:99:1b:78:52:b8:55"),
         t("SHA-256", s("a"), "ca:97:81:12:ca:1b:bd:ca:fa:c2:31:b3:9a:23:dc:4d:a7:86:ef:f8:14:7c:4e:72:b9:80:77:85:af:ee:48:bb"),
         t("SHA-256", s("abc"), "ba:78:16:bf:8f:01:cf:ea:41:41:40:de:5d:ae:22:23:b0:03:61:a3:96:17:7a:9c:b4:10:ff:61:f2:00:15:ad"),
--- a/test/sun/security/provider/MessageDigest/Offsets.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/provider/MessageDigest/Offsets.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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,6 +80,7 @@
         test("MD2", 0, 64, 0, 128);
         test("MD5", 0, 64, 0, 128);
         test("SHA1", 0, 64, 0, 128);
+        test("SHA-224", 0, 64, 0, 128);
         test("SHA-256", 0, 64, 0, 128);
         test("SHA-384", 0, 128, 0, 256);
         test("SHA-512", 0, 128, 0, 256);
--- a/test/sun/security/provider/MessageDigest/TestSHAClone.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/provider/MessageDigest/TestSHAClone.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, 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
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4775971
- * @summary test the clone implementation of SHA, SHA-256,
+ * @summary test the clone implementation of SHA, SHA-224, SHA-256,
  *          SHA-384, SHA-512 MessageDigest implementation.
  */
 import java.security.*;
@@ -33,7 +33,7 @@
 public class TestSHAClone {
 
     private static final String[] ALGOS = {
-        "SHA", "SHA-256", "SHA-512", "SHA-384"
+        "SHA", "SHA-224", "SHA-256", "SHA-512", "SHA-384"
     };
 
     private static byte[] input1 = {
--- a/test/sun/security/rsa/TestKeyPairGenerator.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/rsa/TestKeyPairGenerator.java	Thu Apr 14 18:57:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4853305 4865198 4888410
+ * @bug 4853305 4865198 4888410 4963723
  * @summary Verify that the RSA KeyPairGenerator works
  * @author Andreas Sterbenz
  */
@@ -60,6 +60,7 @@
         testSignature("MD2withRSA", privateKey, publicKey);
         testSignature("MD5withRSA", privateKey, publicKey);
         testSignature("SHA1withRSA", privateKey, publicKey);
+        testSignature("SHA224withRSA", privateKey, publicKey);
         testSignature("SHA256withRSA", privateKey, publicKey);
         RSAPublicKey rsaKey = (RSAPublicKey)publicKey;
         if (rsaKey.getModulus().bitLength() > 512) {
--- a/test/sun/security/rsa/TestSignatures.java	Fri Nov 27 10:59:49 2015 +0300
+++ b/test/sun/security/rsa/TestSignatures.java	Thu Apr 14 18:57:18 2016 +0100
@@ -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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4853305
+ * @bug 4853305 4963723
  * @summary Test signing/verifying using all the signature algorithms
  * @author Andreas Sterbenz
  */
@@ -80,6 +80,7 @@
         testSignature("MD2withRSA", privateKey, publicKey);
         testSignature("MD5withRSA", privateKey, publicKey);
         testSignature("SHA1withRSA", privateKey, publicKey);
+        testSignature("SHA224withRSA", privateKey, publicKey);
         testSignature("SHA256withRSA", privateKey, publicKey);
         RSAPublicKey rsaKey = (RSAPublicKey)publicKey;
         if (rsaKey.getModulus().bitLength() > 512) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java	Thu Apr 14 18:57:18 2016 +0100
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 6956398
+ * @summary make ephemeral DH key match the length of the certificate key
+ * @run main/othervm
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1318 75
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1318 75
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1318 75
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1318 75
+ *
+ * @run main/othervm
+ *      DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 292 75
+ *
+ * @run main/othervm
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1510 139
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1414 107
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1894 267
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1510 139
+ *
+ * @run main/othervm
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 484 139
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 388 107
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 484 139
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 484 139
+ */
+
+/*
+ * This is a simple hack to test key sizes of Diffie-Hellman key exchanging
+ * during SSL/TLS handshaking.
+ *
+ * The record length of DH ServerKeyExchange and ClientKeyExchange.
+ * ServerKeyExchange message are wrapped in ServerHello series messages, which
+ * contains ServerHello, Certificate and ServerKeyExchange message.
+ *
+ *    struct {
+ *        opaque dh_p<1..2^16-1>;
+ *        opaque dh_g<1..2^16-1>;
+ *        opaque dh_Ys<1..2^16-1>;
+ *    } ServerDHParams;     // Ephemeral DH parameters
+ *
+ *    struct {
+ *        select (PublicValueEncoding) {
+ *            case implicit: struct { };
+ *            case explicit: opaque dh_Yc<1..2^16-1>;
+ *        } dh_public;
+ *    } ClientDiffieHellmanPublic;
+ *
+ * Fomr above structures, it is clear that if the DH key size increasing 128
+ * bits (16 bytes), the ServerHello series messages increases 48 bytes
+ * (becuase dh_p, dh_g and dh_Ys each increase 16 bytes) and ClientKeyExchange
+ * increases 16 bytes (because of the size increasing of dh_Yc).
+ *
+ * Here is a summary of the record length in the test case.
+ *
+ *            |  ServerHello Series  |  ClientKeyExchange | ServerHello Anon
+ *   512-bit  |          1318 bytes  |           75 bytes |        292 bytes
+ *   768-bit  |          1414 bytes  |          107 bytes |        388 bytes
+ *  1024-bit  |          1510 bytes  |          139 bytes |        484 bytes
+ *  2048-bit  |          1894 bytes  |          267 bytes |        484 bytes
+ */
+
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.nio.*;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.util.Base64;
+
+public class DHEKeySizing {
+
+    private static boolean debug = true;
+
+    private SSLContext sslc;
+    private SSLEngine ssle1;    // client
+    private SSLEngine ssle2;    // server
+
+    private ByteBuffer appOut1;         // write side of ssle1
+    private ByteBuffer appIn1;          // read side of ssle1
+    private ByteBuffer appOut2;         // write side of ssle2
+    private ByteBuffer appIn2;          // read side of ssle2
+
+    private ByteBuffer oneToTwo;        // "reliable" transport ssle1->ssle2
+    private ByteBuffer twoToOne;        // "reliable" transport ssle2->ssle1
+
+    /*
+     * Where do we find the keystores?
+     */
+    // Certificates and key used in the test.
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIC8jCCAdqgAwIBAgIEUjkuRzANBgkqhkiG9w0BAQUFADA7MR0wGwYDVQQLExRT\n" +
+        "dW5KU1NFIFRlc3QgU2VyaXZjZTENMAsGA1UEChMESmF2YTELMAkGA1UEBhMCVVMw\n" +
+        "HhcNMTMwOTE4MDQzODMxWhcNMTMxMjE3MDQzODMxWjA7MR0wGwYDVQQLExRTdW5K\n" +
+        "U1NFIFRlc3QgU2VyaXZjZTENMAsGA1UEChMESmF2YTELMAkGA1UEBhMCVVMwggEi\n" +
+        "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCO+IGeaskJAvEcYc7pCl9neK3E\n" +
+        "a28fwWLtChufYNaC9hQfZlUdETWYjV7fZJVJKT/oLzdDNMWuVA0LKXArpI3thLNK\n" +
+        "QLXisdF9hKPlZRDazACL9kWUUtJ0FzpEySK4e8wW/z9FuU6e6iO19FbjxAfInJqk\n" +
+        "3EDiEhB5g73S2vtvPCxgq2DvWw9TDl/LIqdKG2JCS93koXCCaHmQ7MrIOqHPd+8r\n" +
+        "RbGpatXT9qyHKppUv9ATxVygO4rA794mgCFxpT+fkhz+NEB0twTkM65T1hnnOv5n\n" +
+        "ZIxkcjBggt85UlZtnP3b9P7SYxsWIa46Oc38Od2f3YejfVg6B+PqPgWNl3+/AgMB\n" +
+        "AAEwDQYJKoZIhvcNAQEFBQADggEBAAlrP6DFLRPSy0IgQhcI2i56tR/na8pezSte\n" +
+        "ZHcCdaCZPDy4UP8mpLJ9QCjEB5VJv8hPm4xdK7ULnKGOGHgYqDpV2ZHvQlhV1woQ\n" +
+        "TZGb/LM3c6kAs0j4j9KM2fq3iYUYexjIkS1KzsziflxMM6igS9BRMBR2LQyU+cYq\n" +
+        "YEsFzkF7Aj2ET4v/+tgot9mRr2NioJcaJkdsPDpMU3IKB1cczfu+OuLQ/GCG0Fqu\n" +
+        "6ijCeCqfnaAbemHbJeVZZ6Qgka3uC2YMntLBmLkhqEo1d9zGYLoh7oWL77y5ibQZ\n" +
+        "LK5/H/zikcu579TWjlDHcqL3arCwBcrtsjSaPrRSWMrWV/6c0qw=\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8
+    static String targetPrivateKey =
+        "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCO+IGeaskJAvEc\n" +
+        "Yc7pCl9neK3Ea28fwWLtChufYNaC9hQfZlUdETWYjV7fZJVJKT/oLzdDNMWuVA0L\n" +
+        "KXArpI3thLNKQLXisdF9hKPlZRDazACL9kWUUtJ0FzpEySK4e8wW/z9FuU6e6iO1\n" +
+        "9FbjxAfInJqk3EDiEhB5g73S2vtvPCxgq2DvWw9TDl/LIqdKG2JCS93koXCCaHmQ\n" +
+        "7MrIOqHPd+8rRbGpatXT9qyHKppUv9ATxVygO4rA794mgCFxpT+fkhz+NEB0twTk\n" +
+        "M65T1hnnOv5nZIxkcjBggt85UlZtnP3b9P7SYxsWIa46Oc38Od2f3YejfVg6B+Pq\n" +
+        "PgWNl3+/AgMBAAECggEAPdb5Ycc4m4A9QBSCRcRpzbyiFLKPh0HDg1n65q4hOtYr\n" +
+        "kAVYTVFTSF/lqGS+Ob3w2YIKujQKSUQrvCc5UHdFuHXMgxKIWbymK0+DAMb9SlYw\n" +
+        "6lkkcWp9gx9E4dnJ/df2SAAxovvrKMuHlL1SFASHhVtPfH2URvSfUaANLDXxyYOs\n" +
+        "8BX0Nr6wazhWjLjXo9yIGnKSvFfB8XisYcA78kEgas43zhmIGCDPqaYyyffOfRbx\n" +
+        "pM1KNwGmlN86iWR1CbwA/wwhcMySWQueS+s7cHbpRqZIYJF9jEeELiwi0vxjealS\n" +
+        "EMuHYedIRFMWaDIq9XyjrvXamHb0Z25jlXBNZHaM0QKBgQDE9adl+zAezR/n79vw\n" +
+        "0XiX2Fx1UEo3ApZHuoA2Q/PcBk+rlKqqQ3IwTcy6Wo648wK7v6Nq7w5nEWcsf0dU\n" +
+        "QA2Ng/AJEev/IfF34x7sKGYxtk1gcE0EuSBA3R+ocEZxnNw1Ryd5nUU24s8d4jCP\n" +
+        "Mkothnyaim+zE2raDlEtVc0CaQKBgQC509av+02Uq5oMjzbQp5PBJfQFjATOQT15\n" +
+        "eefYnVYurkQ1kcVfixkrO2ORhg4SjmI2Z5hJDgGtXdwgidpzkad+R2epS5qLMyno\n" +
+        "lQVpY6bMpEZ7Mos0yQygxnm8uNohEcTExOe+nP5fNJVpzBsGmfeyYOhnPQlf6oqf\n" +
+        "0cHizedb5wKBgQC/l5LyMil6HOGHlhzmIm3jj7VI7QR0hJC5T6N+phVml8ESUDjA\n" +
+        "DYHbmSKouISTRtkG14FY+RiSjCxH7bvuKazFV2289PETquogTA/9e8MFYqfcQwG4\n" +
+        "sXi9gBxWlnj/9a2EKiYtOB5nKLR/BlNkSHA93tAA6N+FXEMZwMmYhxk42QKBgAuY\n" +
+        "HQgD3PZOsqDf+qKQIhbmAFCsSMx5o5VFtuJ8BpmJA/Z3ruHkMuDQpsi4nX4o5hXQ\n" +
+        "5t6AAjjH52kcUMXvK40kdWJJtk3DFnVNfvXxYsHX6hHbuHXFqYUKfSP6QJnZmvZP\n" +
+        "9smcz/4usLfWJUWHK740b6upUkFqx9Vq5/b3s9y3AoGAdM5TW7LkkOFsdMGVAUzR\n" +
+        "9iXmCWElHTK2Pcp/3yqDBHSfiQx6Yp5ANyPnE9NBM0yauCfOyBB2oxLO4Rdv3Rqk\n" +
+        "9V9kyR/YAGr7dJaPcQ7pZX0OpkzgueAOJYPrx5VUzPYUtklYV1ycFZTfKlpFCxT+\n" +
+        "Ei6KUo0NXSdUIcB4yib1J10=";
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Majority of the test case is here, setup is done below.
+     */
+
+    private void createSSLEngines() throws Exception {
+        ssle1 = sslc.createSSLEngine("client", 1);
+        ssle1.setUseClientMode(true);
+
+        ssle2 = sslc.createSSLEngine("server", 2);
+        ssle2.setUseClientMode(false);
+    }
+
+    private boolean isHandshaking(SSLEngine e) {
+        return (e.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING);
+    }
+
+    private void checkResult(ByteBuffer bbIn, ByteBuffer bbOut,
+            SSLEngineResult result,
+            Status status, HandshakeStatus hsStatus,
+            int consumed, int produced)
+            throws Exception {
+
+        if ((status != null) && (result.getStatus() != status)) {
+            throw new Exception("Unexpected Status: need = " + status +
+                " got = " + result.getStatus());
+        }
+
+        if ((hsStatus != null) && (result.getHandshakeStatus() != hsStatus)) {
+            throw new Exception("Unexpected hsStatus: need = " + hsStatus +
+                " got = " + result.getHandshakeStatus());
+        }
+
+        if ((consumed != -1) && (consumed != result.bytesConsumed())) {
+            throw new Exception("Unexpected consumed: need = " + consumed +
+                " got = " + result.bytesConsumed());
+        }
+
+        if ((produced != -1) && (produced != result.bytesProduced())) {
+            throw new Exception("Unexpected produced: need = " + produced +
+                " got = " + result.bytesProduced());
+        }
+
+        if ((consumed != -1) && (bbIn.position() != result.bytesConsumed())) {
+            throw new Exception("Consumed " + bbIn.position() +
+                " != " + consumed);
+        }
+
+        if ((produced != -1) && (bbOut.position() != result.bytesProduced())) {
+            throw new Exception("produced " + bbOut.position() +
+                " != " + produced);
+        }
+    }
+
+    private void test(String cipherSuite, boolean exportable,
+            int lenServerKeyEx, int lenClientKeyEx) throws Exception {
+
+        createSSLEngines();
+        createBuffers();
+
+        SSLEngineResult result1;        // ssle1's results from last operation
+        SSLEngineResult result2;        // ssle2's results from last operation
+
+        String[] suites = new String [] {cipherSuite};
+
+        ssle1.setEnabledCipherSuites(suites);
+        ssle2.setEnabledCipherSuites(suites);
+
+        log("======================================");
+        log("===================");
+        log("client hello");
+        result1 = ssle1.wrap(appOut1, oneToTwo);
+        checkResult(appOut1, oneToTwo, result1,
+            Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);
+        oneToTwo.flip();
+
+        result2 = ssle2.unwrap(oneToTwo, appIn2);
+        checkResult(oneToTwo, appIn2, result2,
+            Status.OK, HandshakeStatus.NEED_TASK, result1.bytesProduced(), 0);
+        runDelegatedTasks(ssle2);
+        oneToTwo.compact();
+
+        log("===================");
+        log("ServerHello");
+        result2 = ssle2.wrap(appOut2, twoToOne);
+        checkResult(appOut2, twoToOne, result2,
+            Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);
+        twoToOne.flip();
+
+        log("Message length of ServerHello series: " + twoToOne.remaining());
+        if (lenServerKeyEx != twoToOne.remaining()) {
+            throw new Exception(
+                "Expected to generate ServerHello series messages of " +
+                lenServerKeyEx + " bytes, but not " + twoToOne.remaining());
+        }
+
+        result1 = ssle1.unwrap(twoToOne, appIn1);
+        checkResult(twoToOne, appIn1, result1,
+            Status.OK, HandshakeStatus.NEED_TASK, result2.bytesProduced(), 0);
+        runDelegatedTasks(ssle1);
+        twoToOne.compact();
+
+        log("===================");
+        log("Key Exchange");
+        result1 = ssle1.wrap(appOut1, oneToTwo);
+        checkResult(appOut1, oneToTwo, result1,
+            Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);
+        oneToTwo.flip();
+
+        log("Message length of ClientKeyExchange: " + oneToTwo.remaining());
+        if (lenClientKeyEx != oneToTwo.remaining()) {
+            throw new Exception(
+                "Expected to generate ClientKeyExchange message of " +
+                lenClientKeyEx + " bytes, but not " + oneToTwo.remaining());
+        }
+        result2 = ssle2.unwrap(oneToTwo, appIn2);
+        checkResult(oneToTwo, appIn2, result2,
+            Status.OK, HandshakeStatus.NEED_TASK, result1.bytesProduced(), 0);
+        runDelegatedTasks(ssle2);
+        oneToTwo.compact();
+
+        log("===================");
+        log("Client CCS");
+        result1 = ssle1.wrap(appOut1, oneToTwo);
+        checkResult(appOut1, oneToTwo, result1,
+            Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);
+        oneToTwo.flip();
+
+        result2 = ssle2.unwrap(oneToTwo, appIn2);
+        checkResult(oneToTwo, appIn2, result2,
+            Status.OK, HandshakeStatus.NEED_UNWRAP,
+            result1.bytesProduced(), 0);
+        oneToTwo.compact();
+
+        log("===================");
+        log("Client Finished");
+        result1 = ssle1.wrap(appOut1, oneToTwo);
+        checkResult(appOut1, oneToTwo, result1,
+            Status.OK, HandshakeStatus.NEED_UNWRAP, 0, -1);
+        oneToTwo.flip();
+
+        result2 = ssle2.unwrap(oneToTwo, appIn2);
+        checkResult(oneToTwo, appIn2, result2,
+            Status.OK, HandshakeStatus.NEED_WRAP,
+            result1.bytesProduced(), 0);
+        oneToTwo.compact();
+
+        log("===================");
+        log("Server CCS");
+        result2 = ssle2.wrap(appOut2, twoToOne);
+        checkResult(appOut2, twoToOne, result2,
+            Status.OK, HandshakeStatus.NEED_WRAP, 0, -1);
+        twoToOne.flip();
+
+        result1 = ssle1.unwrap(twoToOne, appIn1);
+        checkResult(twoToOne, appIn1, result1,
+            Status.OK, HandshakeStatus.NEED_UNWRAP, result2.bytesProduced(), 0);
+        twoToOne.compact();
+
+        log("===================");
+        log("Server Finished");
+        result2 = ssle2.wrap(appOut2, twoToOne);
+        checkResult(appOut2, twoToOne, result2,
+            Status.OK, HandshakeStatus.FINISHED, 0, -1);
+        twoToOne.flip();
+
+        result1 = ssle1.unwrap(twoToOne, appIn1);
+        checkResult(twoToOne, appIn1, result1,
+            Status.OK, HandshakeStatus.FINISHED, result2.bytesProduced(), 0);
+        twoToOne.compact();
+
+        log("===================");
+        log("Check Session/Ciphers");
+        String cs = ssle1.getSession().getCipherSuite();
+        if (!cs.equals(suites[0])) {
+            throw new Exception("suites not equal: " + cs + "/" + suites[0]);
+        }
+
+        cs = ssle2.getSession().getCipherSuite();
+        if (!cs.equals(suites[0])) {
+            throw new Exception("suites not equal: " + cs + "/" + suites[0]);
+        }
+
+        log("===================");
+        log("Done with SSL/TLS handshaking");
+    }
+
+    public static void main(String args[]) throws Exception {
+        if (args.length != 4) {
+            System.out.println(
+                "Usage: java DHEKeySizing cipher-suite " +
+                "exportable(true|false)\n" +
+                "    size-of-server-hello-record size-of-client-key-exchange");
+            throw new Exception("Incorrect usage!");
+        }
+
+        (new DHEKeySizing()).test(args[0],
+                Boolean.parseBoolean(args[1]),
+                Integer.parseInt(args[2]),
+                Integer.parseInt(args[3]));
+        System.out.println("Test Passed.");
+    }
+
+    /*
+     * **********************************************************
+     * Majority of the test case is above, below is just setup stuff
+     * **********************************************************
+     */
+
+    public DHEKeySizing() throws Exception {
+        sslc = getSSLContext();
+    }
+
+    /*
+     * Create an initialized SSLContext to use for this test.
+     */
+    private SSLContext getSSLContext() throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ts = KeyStore.getInstance("JKS");
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ts.load(null, null);
+        ks.load(null, null);
+
+        // import the trused cert
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trustedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+        ts.setCertificateEntry("rsa-trusted-2048", trusedCert);
+
+        // generate the private key.
+        String keySpecStr = targetPrivateKey;
+        PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                            Base64.getMimeDecoder().decode(keySpecStr));
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+        Certificate[] chain = new Certificate[1];
+        chain[0] = trusedCert;
+
+        // import the key entry.
+        ks.setKeyEntry("rsa-key-2048", priKey, passphrase, chain);
+
+        // create SSL context
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(ks, passphrase);
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+        tmf.init(ts);
+
+        SSLContext sslCtx = SSLContext.getInstance("TLS");
+        sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+        return sslCtx;
+    }
+
+    private void createBuffers() {
+        // Size the buffers as appropriate.
+
+        SSLSession session = ssle1.getSession();
+        int appBufferMax = session.getApplicationBufferSize();
+        int netBufferMax = session.getPacketBufferSize();
+
+        appIn1 = ByteBuffer.allocateDirect(appBufferMax + 50);
+        appIn2 = ByteBuffer.allocateDirect(appBufferMax + 50);
+
+        oneToTwo = ByteBuffer.allocateDirect(netBufferMax);
+        twoToOne = ByteBuffer.allocateDirect(netBufferMax);
+
+        appOut1 = ByteBuffer.wrap("Hi Engine2, I'm SSLEngine1".getBytes());
+        appOut2 = ByteBuffer.wrap("Hello Engine1, I'm SSLEngine2".getBytes());
+
+        log("AppOut1 = " + appOut1);
+        log("AppOut2 = " + appOut2);
+        log("");
+    }
+
+    private static void runDelegatedTasks(SSLEngine engine) throws Exception {
+
+        Runnable runnable;
+        while ((runnable = engine.getDelegatedTask()) != null) {
+            log("running delegated task...");
+            runnable.run();
+        }
+    }
+
+    private static void log(String str) {
+        if (debug) {
+            System.out.println(str);
+        }
+    }
+}