diff --git a/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java index 5d6e70fe7ab..dfd2ec2b04b 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java @@ -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 key 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); } /** diff --git a/test/jdk/com/sun/crypto/provider/Cipher/KeyWrap/TestKeySizeCheck.java b/test/jdk/com/sun/crypto/provider/Cipher/KeyWrap/TestKeySizeCheck.java index f1b686707e2..4732836d6d9 100644 --- a/test/jdk/com/sun/crypto/provider/Cipher/KeyWrap/TestKeySizeCheck.java +++ b/test/jdk/com/sun/crypto/provider/Cipher/KeyWrap/TestKeySizeCheck.java @@ -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 {