8180392: SunJCE provider should throw exceptions for unsupported mode and padding combinations
Change JCA Cipher class to create obj to ensure the mode and padding combination is supported Reviewed-by: xuelei
This commit is contained in:
parent
74c3432b28
commit
6b662abe74
src/java.base/share/classes
test/jdk
com/sun/crypto/provider/Cipher
AES
Blowfish
DES
javax/crypto/Cipher
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2019, 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
|
||||
@ -271,7 +271,9 @@ final class CipherCore {
|
||||
padding = null;
|
||||
} else if (paddingScheme.equalsIgnoreCase("ISO10126Padding")) {
|
||||
padding = new ISO10126Padding(blockSize);
|
||||
} else if (!paddingScheme.equalsIgnoreCase("PKCS5Padding")) {
|
||||
} else if (paddingScheme.equalsIgnoreCase("PKCS5Padding")) {
|
||||
padding = new PKCS5Padding(blockSize);
|
||||
} else {
|
||||
throw new NoSuchPaddingException("Padding: " + paddingScheme
|
||||
+ " not implemented");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2019, 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
|
||||
@ -559,16 +559,16 @@ public class Cipher {
|
||||
// does not support mode or padding we need, ignore
|
||||
continue;
|
||||
}
|
||||
if (canuse == S_YES) {
|
||||
// S_YES, S_MAYBE
|
||||
// even when mode and padding are both supported, they
|
||||
// may not be used together, try out and see if it works
|
||||
try {
|
||||
CipherSpi spi = (CipherSpi)s.newInstance(null);
|
||||
tr.setModePadding(spi);
|
||||
// specify null instead of spi for delayed provider selection
|
||||
return new Cipher(null, s, t, transformation, transforms);
|
||||
} else { // S_MAYBE, try out if it works
|
||||
try {
|
||||
CipherSpi spi = (CipherSpi)s.newInstance(null);
|
||||
tr.setModePadding(spi);
|
||||
return new Cipher(spi, s, t, transformation, transforms);
|
||||
} catch (Exception e) {
|
||||
failure = e;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failure = e;
|
||||
}
|
||||
}
|
||||
throw new NoSuchAlgorithmException
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, 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,19 +48,24 @@ public class Padding {
|
||||
|
||||
private static final String ALGORITHM = "AES";
|
||||
private static final String PROVIDER = "SunJCE";
|
||||
private static final String[] MODES = { "ECb", "CbC", "PCBC", "OFB",
|
||||
private static final String[] MODES_PKCS5PAD = {
|
||||
"ECb", "CbC", "PCBC", "OFB",
|
||||
"OFB150", "cFB", "CFB7", "cFB8", "cFB16", "cFB24", "cFB32",
|
||||
"Cfb40", "cfB48", "cfB56", "cfB64", "cfB72", "cfB80", "cfB88",
|
||||
"cfB96", "cfb104", "cfB112", "cfB120", "OFB8", "OFB16", "OFB24",
|
||||
"OFB32", "OFB40", "OFB48", "OFB56", "OFB64", "OFB72", "OFB80",
|
||||
"OFB88", "OFB96", "OFB104", "OFB112", "OFB120", "GCM" };
|
||||
private static final String PADDING = "PKCS5Padding";
|
||||
"OFB88", "OFB96", "OFB104", "OFB112", "OFB120" };
|
||||
private static final String[] MODES_NOPAD = { "CTR", "CTS", "GCM" };
|
||||
|
||||
private static final int KEY_LENGTH = 128;
|
||||
|
||||
public static void main(String argv[]) throws Exception {
|
||||
Padding test = new Padding();
|
||||
for (String mode : MODES) {
|
||||
test.runTest(ALGORITHM, mode, PADDING);
|
||||
for (String mode : MODES_PKCS5PAD) {
|
||||
test.runTest(ALGORITHM, mode, "PKCS5Padding");
|
||||
}
|
||||
for (String mode : MODES_NOPAD) {
|
||||
test.runTest(ALGORITHM, mode, "NoPadding");
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +97,6 @@ public class Padding {
|
||||
int offset = ci.update(plainText, 0, plainText.length,
|
||||
cipherText, 0);
|
||||
ci.doFinal(cipherText, offset);
|
||||
|
||||
if (!mo.equalsIgnoreCase("ECB")) {
|
||||
iv = ci.getIV();
|
||||
aps = new IvParameterSpec(iv);
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 8180392
|
||||
* @summary Ensure SunJCE provider throws exception for unsupported modes
|
||||
* and padding combinations
|
||||
*/
|
||||
import java.security.*;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import javax.crypto.*;
|
||||
|
||||
public class TestNoPaddingModes {
|
||||
|
||||
// SunJCE only supports NoPadding with following modes
|
||||
private static final String[] MODES = {
|
||||
"CTR", "CTS", "GCM"
|
||||
};
|
||||
private static final String[] PADDINGS = {
|
||||
"PKCS5Padding", "ISO10126Padding"
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Provider p = Security.getProvider("SunJCE");
|
||||
String transformation;
|
||||
for (String mode : MODES) {
|
||||
for (String padding : PADDINGS) {
|
||||
transformation = "AES/" + mode + "/" + padding;
|
||||
|
||||
System.out.println("Test using " + transformation);
|
||||
try {
|
||||
Cipher c = Cipher.getInstance(transformation, "SunJCE");
|
||||
throw new RuntimeException("=> Fail, no exception thrown");
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
|
||||
System.out.println("=> Expected ex: " + ex);
|
||||
}
|
||||
try {
|
||||
Cipher c = Cipher.getInstance(transformation, p);
|
||||
throw new RuntimeException("=> Fail, no exception thrown");
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
|
||||
System.out.println("=> Expected ex: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Test Passed");
|
||||
}
|
||||
|
||||
public static class MyCipImpl extends CipherSpi {
|
||||
public MyCipImpl() {
|
||||
super();
|
||||
System.out.println("MyCipImpl is created");
|
||||
}
|
||||
protected void engineSetMode(String mode)
|
||||
throws NoSuchAlgorithmException {};
|
||||
protected void engineSetPadding(String padding)
|
||||
throws NoSuchPaddingException {};
|
||||
protected int engineGetBlockSize() { return 16; }
|
||||
protected int engineGetOutputSize(int inputLen) { return 0; }
|
||||
protected byte[] engineGetIV() { return null; }
|
||||
protected AlgorithmParameters engineGetParameters() { return null; }
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {};
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {};
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameters params,
|
||||
SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {};
|
||||
protected byte[] engineUpdate(byte[] input, int inputOffset,
|
||||
int inputLen) { return null; }
|
||||
protected int engineUpdate(byte[] input, int inputOffset,
|
||||
int inputLen, byte[] output,
|
||||
int outputOffset)
|
||||
throws ShortBufferException { return 0; };
|
||||
protected byte[] engineDoFinal(byte[] input, int inputOffset,
|
||||
int inputLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
return null;
|
||||
}
|
||||
protected int engineDoFinal(byte[] input, int inputOffset,
|
||||
int inputLen, byte[] output,
|
||||
int outputOffset)
|
||||
throws ShortBufferException, IllegalBlockSizeException,
|
||||
BadPaddingException { return 0; }
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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,20 +32,20 @@ import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class TestCipherBlowfish extends TestCipher {
|
||||
|
||||
TestCipherBlowfish() throws NoSuchAlgorithmException {
|
||||
super("Blowfish",
|
||||
new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
|
||||
"CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
|
||||
"OFB64"},
|
||||
new String[]{"NoPaDDing", "PKCS5Padding"},
|
||||
32, 448);
|
||||
TestCipherBlowfish(String[] modes, String[] paddings) throws NoSuchAlgorithmException {
|
||||
super("Blowfish", modes, paddings, 32, 448);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestCipherBlowfish().runAll();
|
||||
new TestCipherBlowfish(new String[]{ "CBC", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
|
||||
"CFB48", "CFB56", "CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
|
||||
"OFB48", "OFB56", "OFB64"},
|
||||
new String[]{ "NoPaDDing", "PKCS5Padding"}).runAll();
|
||||
new TestCipherBlowfish(new String[]{ "CTR", "CTS" },
|
||||
new String[]{ "NoPaDDing" }).runAll();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -30,19 +30,20 @@
|
||||
|
||||
public class TestCipherDES extends TestCipher {
|
||||
|
||||
TestCipherDES() {
|
||||
super("DES",
|
||||
new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
|
||||
"CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
|
||||
"OFB64"},
|
||||
new String[]{"NoPaDDing", "PKCS5Padding"});
|
||||
TestCipherDES(String[] modes, String[] paddings) {
|
||||
super("DES", modes, paddings);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestCipherDES().runAll();
|
||||
new TestCipherDES(new String[]{ "CBC", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
|
||||
"CFB48", "CFB56", "CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
|
||||
"OFB48", "OFB56", "OFB64" },
|
||||
new String[]{ "NoPaDDing", "PKCS5Padding" }).runAll();
|
||||
new TestCipherDES(new String[]{ "CTR", "CTS" },
|
||||
new String[]{ "NoPaDDing" }).runAll();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -30,19 +30,22 @@
|
||||
|
||||
public class TestCipherDESede extends TestCipher {
|
||||
|
||||
TestCipherDESede() {
|
||||
super("DESede",
|
||||
new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
|
||||
"CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
|
||||
"OFB64"},
|
||||
new String[]{"NoPaDDing", "PKCS5Padding"});
|
||||
TestCipherDESede(String[] modes, String[] paddings) {
|
||||
super("DESede", modes, paddings);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestCipherDESede().runAll();
|
||||
new TestCipherDESede(
|
||||
new String[]{ "CBC", "ECB", "PCBC",
|
||||
//CFBx
|
||||
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
|
||||
"CFB48", "CFB56", "CFB64",
|
||||
//OFBx
|
||||
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
|
||||
"OFB48", "OFB56", "OFB64"},
|
||||
new String[]{ "NoPaDDing", "PKCS5Padding" }).runAll();
|
||||
new TestCipherDESede(
|
||||
new String[]{ "CTR", "CTS" },
|
||||
new String[]{ "NoPaDDing" }).runAll();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -55,7 +55,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
/* Full read stream, check that getMoreData() is throwing an exception
|
||||
* This test
|
||||
* 1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
* 1) Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
* 2) Changes the last byte to invalidate the authetication tag.
|
||||
* 3) Fully reads CipherInputStream to decrypt the message and closes
|
||||
*/
|
||||
@ -66,7 +66,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
System.out.println("Running gcm_AEADBadTag");
|
||||
|
||||
// Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
// Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
byte[] ct = encryptedText("GCM", 100);
|
||||
// Corrupt the encrypted message
|
||||
ct = corruptGCM(ct);
|
||||
@ -92,7 +92,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
/* Short read stream,
|
||||
* This test
|
||||
* 1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
* 1) Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
* 2) Reads 100 bytes from stream to decrypt the message and closes
|
||||
* 3) Make sure no value is returned by read()
|
||||
* 4) Make sure no exception is thrown
|
||||
@ -106,7 +106,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
byte[] pt = new byte[600];
|
||||
pt[0] = 1;
|
||||
// Encrypt provided 600 bytes with AES/GCM/PKCS5Padding
|
||||
// Encrypt provided 600 bytes with AES/GCM/NoPadding
|
||||
byte[] ct = encryptedText("GCM", pt);
|
||||
// Create stream for decryption
|
||||
CipherInputStream in = getStream("GCM", ct);
|
||||
@ -134,7 +134,7 @@ public class CipherInputStreamExceptions {
|
||||
* Verify doFinal() exception is suppressed when input stream is not
|
||||
* read before it is closed.
|
||||
* This test:
|
||||
* 1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
* 1) Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
* 2) Changes the last byte to invalidate the authetication tag.
|
||||
* 3) Opens a CipherInputStream and the closes it. Never reads from it.
|
||||
*
|
||||
@ -146,7 +146,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
System.out.println("Running supressUnreadCorrupt test");
|
||||
|
||||
// Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
// Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
byte[] ct = encryptedText("GCM", 100);
|
||||
// Corrupt the encrypted message
|
||||
ct = corruptGCM(ct);
|
||||
@ -166,7 +166,7 @@ public class CipherInputStreamExceptions {
|
||||
* Verify noexception thrown when 1 byte is read from a GCM stream
|
||||
* and then closed
|
||||
* This test:
|
||||
* 1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
* 1) Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
* 2) Read one byte from the stream, expect no exception thrown.
|
||||
* 4) Close stream,expect no exception thrown.
|
||||
*/
|
||||
@ -174,7 +174,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
System.out.println("Running gcm_oneReadByte test");
|
||||
|
||||
// Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
// Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
byte[] ct = encryptedText("GCM", 100);
|
||||
// Create stream for decryption
|
||||
CipherInputStream in = getStream("GCM", ct);
|
||||
@ -192,7 +192,7 @@ public class CipherInputStreamExceptions {
|
||||
* Verify exception thrown when 1 byte is read from a corrupted GCM stream
|
||||
* and then closed
|
||||
* This test:
|
||||
* 1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
* 1) Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
* 2) Changes the last byte to invalidate the authetication tag.
|
||||
* 3) Read one byte from the stream, expect exception thrown.
|
||||
* 4) Close stream,expect no exception thrown.
|
||||
@ -201,7 +201,7 @@ public class CipherInputStreamExceptions {
|
||||
|
||||
System.out.println("Running gcm_oneReadByteCorrupt test");
|
||||
|
||||
// Encrypt 100 bytes with AES/GCM/PKCS5Padding
|
||||
// Encrypt 100 bytes with AES/GCM/NoPadding
|
||||
byte[] ct = encryptedText("GCM", 100);
|
||||
// Corrupt the encrypted message
|
||||
ct = corruptGCM(ct);
|
||||
@ -357,7 +357,7 @@ public class CipherInputStreamExceptions {
|
||||
static byte[] encryptedText(String mode, byte[] pt) throws Exception{
|
||||
Cipher c;
|
||||
if (mode.compareTo("GCM") == 0) {
|
||||
c = Cipher.getInstance("AES/GCM/PKCS5Padding", "SunJCE");
|
||||
c = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
|
||||
c.init(Cipher.ENCRYPT_MODE, key, gcmspec);
|
||||
} else if (mode.compareTo("CBC") == 0) {
|
||||
c = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
|
||||
@ -380,7 +380,7 @@ public class CipherInputStreamExceptions {
|
||||
Cipher c;
|
||||
|
||||
if (mode.compareTo("GCM") == 0) {
|
||||
c = Cipher.getInstance("AES/GCM/PKCS5Padding", "SunJCE");
|
||||
c = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
|
||||
c.init(Cipher.DECRYPT_MODE, key, gcmspec);
|
||||
} else if (mode.compareTo("CBC") == 0) {
|
||||
c = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
|
||||
|
Loading…
x
Reference in New Issue
Block a user