8302225: SunJCE Provider doesn't validate key sizes when using 'constrained' transforms for AES/KW and AES/KWP

Reviewed-by: xuelei
This commit is contained in:
Valerie Peng 2023-02-16 21:58:34 +00:00
parent a39cf2e3b2
commit 4ce493f09e
2 changed files with 47 additions and 24 deletions
src/java.base/share/classes/com/sun/crypto/provider
test/jdk/com/sun/crypto/provider/Cipher/KeyWrap

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2023, 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
@ -123,6 +123,25 @@ abstract class KeyWrapCipher extends CipherSpi {
}
}
// validate the key algorithm/encoding and then returns the key bytes
// which callers should erase after use
private static byte[] checkKey(Key key, int fixedKeySize)
throws InvalidKeyException {
byte[] keyBytes = key.getEncoded();
if (keyBytes == null) {
throw new InvalidKeyException("Null key");
}
int keyLen = keyBytes.length;
if (!key.getAlgorithm().equalsIgnoreCase("AES") ||
!AESCrypt.isKeySizeValid(keyLen) ||
(fixedKeySize != -1 && fixedKeySize != keyLen)) {
throw new InvalidKeyException("Invalid key length: " +
keyLen + " bytes");
}
return keyBytes;
}
// store the specified bytes, e.g. in[inOfs...(inOfs+inLen-1)] into
// 'dataBuf' starting at 'dataIdx'.
// NOTE: if 'in' is null, this method will ensure that 'dataBuf' has enough
@ -292,10 +311,8 @@ abstract class KeyWrapCipher extends CipherSpi {
// actual impl for various engineInit(...) methods
private void implInit(int opmode, Key key, byte[] iv, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
byte[] keyBytes = key.getEncoded();
if (keyBytes == null) {
throw new InvalidKeyException("Null key");
}
byte[] keyBytes = checkKey(key, fixedKeySize);
this.opmode = opmode;
boolean decrypting = (opmode == Cipher.DECRYPT_MODE ||
opmode == Cipher.UNWRAP_MODE);
@ -656,21 +673,11 @@ abstract class KeyWrapCipher extends CipherSpi {
* @exception InvalidKeyException if <code>key</code> is invalid.
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
if (encoded == null) {
throw new InvalidKeyException("Cannot decide key length");
}
byte[] keyBytes = checkKey(key, fixedKeySize);
// only need length; erase immediately
Arrays.fill(keyBytes, (byte) 0);
return Math.multiplyExact(keyBytes.length, 8);
// only need length
Arrays.fill(encoded, (byte) 0);
int keyLen = encoded.length;
if (!key.getAlgorithm().equalsIgnoreCase("AES") ||
!AESCrypt.isKeySizeValid(keyLen) ||
(fixedKeySize != -1 && fixedKeySize != keyLen)) {
throw new InvalidKeyException("Invalid key length: " +
keyLen + " bytes");
}
return Math.multiplyExact(keyLen, 8);
}
/**

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, 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 8248268
* @bug 8248268 8302225
* @summary Verify cipher key size restriction is enforced properly with IKE
* @run main TestKeySizeCheck
*/
@ -43,6 +43,8 @@ public class TestKeySizeCheck {
}
}
private static final int[] AES_KEYSIZES = { 128, 192, 256 };
private static SecretKey getKey(int sizeInBytes) {
if (sizeInBytes <= BYTES_32.length) {
return new SecretKeySpec(BYTES_32, 0, sizeInBytes, "AES");
@ -64,7 +66,7 @@ public class TestKeySizeCheck {
int[] modes = { Cipher.ENCRYPT_MODE, Cipher.WRAP_MODE };
for (int ks : invalidKeySizes) {
System.out.println("keysize: " + ks);
SecretKey key = getKey(ks);
SecretKey key = getKey(ks >> 3);
for (int m : modes) {
try {
@ -72,11 +74,25 @@ public class TestKeySizeCheck {
throw new RuntimeException("Expected IKE not thrown for "
+ getModeStr(m));
} catch (InvalidKeyException ike) {
System.out.println(" => expected IKE thrown for "
+ getModeStr(m));
System.out.println(getModeStr(m) + " => got expected IKE");
}
}
}
// now test against the valid key size(s) and make sure they work
int underscoreIdx = algo.indexOf("_");
int[] validKeySizes = (algo.indexOf("_") == -1 ?
AES_KEYSIZES : new int[] { Integer.parseInt(algo.substring
(underscoreIdx + 1, underscoreIdx + 4)) });
for (int ks : validKeySizes) {
System.out.println("keysize: " + ks);
SecretKey key = getKey(ks >> 3);
for (int m : modes) {
c.init(m, key);
System.out.println(getModeStr(m) + " => ok");
}
}
}
public static void main(String[] argv) throws Exception {