diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index 201d47ca7fb..69af5c87078 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -334,6 +334,8 @@ protected int engineGenerateSecret(byte[] sharedSecret, int offset) } else { // Array too short, pad it w/ leading 0s if (secret.length < expectedLen) { + Arrays.fill(sharedSecret, offset, + offset + (expectedLen - secret.length), (byte)0); System.arraycopy(secret, 0, sharedSecret, offset + (expectedLen - secret.length), secret.length); diff --git a/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java b/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java new file mode 100644 index 00000000000..c0bb9a02c43 --- /dev/null +++ b/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022, 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 8281628 + * @library /test/lib + * @summary ensure padding bytes are always added when generated secret + * is smaller than buffer size. + */ + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.util.Arrays; + +public class DHKeyAgreementPadding { + + public static void main(String[] args) throws Exception { + + byte[] aliceSecret = new byte[80]; + byte[] bobSecret = new byte[80]; + + KeyAgreement alice = KeyAgreement.getInstance("DiffieHellman"); + KeyAgreement bob = KeyAgreement.getInstance("DiffieHellman"); + + // The probability of an error is 0.2% or 1/500. Try more times. + for (int i = 0; i < 5000; i++) { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); + keyPairGen.initialize(512); + KeyPair aliceKeyPair = keyPairGen.generateKeyPair(); + KeyPair bobKeyPair = keyPairGen.generateKeyPair(); + + // Different stale data + Arrays.fill(aliceSecret, (byte)'a'); + Arrays.fill(bobSecret, (byte)'b'); + + alice.init(aliceKeyPair.getPrivate()); + alice.doPhase(bobKeyPair.getPublic(), true); + int aliceLen = alice.generateSecret(aliceSecret, 0); + + bob.init(bobKeyPair.getPrivate()); + bob.doPhase(aliceKeyPair.getPublic(), true); + int bobLen = bob.generateSecret(bobSecret, 0); + + if (!Arrays.equals(aliceSecret, 0, aliceLen, bobSecret, 0, bobLen)) { + System.out.println(toHexString(aliceSecret, aliceLen)); + System.out.println(toHexString(bobSecret, bobLen)); + throw new RuntimeException("Different secrets observed at runs #" + i); + } + } + } + + /* + * Converts a byte to hex digit and writes to the supplied buffer + */ + private static void byte2hex(byte b, StringBuffer buf) { + char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + int high = ((b & 0xf0) >> 4); + int low = (b & 0x0f); + buf.append(hexChars[high]); + buf.append(hexChars[low]); + } + + /* + * Converts a byte array to hex string + */ + private static String toHexString(byte[] block, int len) { + StringBuffer buf = new StringBuffer(); + + for (int i = 0; i < len; i++) { + byte2hex(block[i], buf); + if (i < len-1) { + buf.append(":"); + } + } + return buf.toString(); + } +}