Skip to content

Commit 4ce493f

Browse files
author
Valerie Peng
committed
8302225: SunJCE Provider doesn't validate key sizes when using 'constrained' transforms for AES/KW and AES/KWP
Reviewed-by: xuelei
1 parent a39cf2e commit 4ce493f

File tree

2 files changed

+47
-24
lines changed

2 files changed

+47
-24
lines changed

src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -123,6 +123,25 @@ public AES256_KWP_NoPadding() {
123123
}
124124
}
125125

126+
// validate the key algorithm/encoding and then returns the key bytes
127+
// which callers should erase after use
128+
private static byte[] checkKey(Key key, int fixedKeySize)
129+
throws InvalidKeyException {
130+
131+
byte[] keyBytes = key.getEncoded();
132+
if (keyBytes == null) {
133+
throw new InvalidKeyException("Null key");
134+
}
135+
int keyLen = keyBytes.length;
136+
if (!key.getAlgorithm().equalsIgnoreCase("AES") ||
137+
!AESCrypt.isKeySizeValid(keyLen) ||
138+
(fixedKeySize != -1 && fixedKeySize != keyLen)) {
139+
throw new InvalidKeyException("Invalid key length: " +
140+
keyLen + " bytes");
141+
}
142+
return keyBytes;
143+
}
144+
126145
// store the specified bytes, e.g. in[inOfs...(inOfs+inLen-1)] into
127146
// 'dataBuf' starting at 'dataIdx'.
128147
// NOTE: if 'in' is null, this method will ensure that 'dataBuf' has enough
@@ -292,10 +311,8 @@ protected byte[] engineGetIV() {
292311
// actual impl for various engineInit(...) methods
293312
private void implInit(int opmode, Key key, byte[] iv, SecureRandom random)
294313
throws InvalidKeyException, InvalidAlgorithmParameterException {
295-
byte[] keyBytes = key.getEncoded();
296-
if (keyBytes == null) {
297-
throw new InvalidKeyException("Null key");
298-
}
314+
byte[] keyBytes = checkKey(key, fixedKeySize);
315+
299316
this.opmode = opmode;
300317
boolean decrypting = (opmode == Cipher.DECRYPT_MODE ||
301318
opmode == Cipher.UNWRAP_MODE);
@@ -656,21 +673,11 @@ protected AlgorithmParameters engineGetParameters() {
656673
* @exception InvalidKeyException if <code>key</code> is invalid.
657674
*/
658675
protected int engineGetKeySize(Key key) throws InvalidKeyException {
659-
byte[] encoded = key.getEncoded();
660-
if (encoded == null) {
661-
throw new InvalidKeyException("Cannot decide key length");
662-
}
676+
byte[] keyBytes = checkKey(key, fixedKeySize);
677+
// only need length; erase immediately
678+
Arrays.fill(keyBytes, (byte) 0);
679+
return Math.multiplyExact(keyBytes.length, 8);
663680

664-
// only need length
665-
Arrays.fill(encoded, (byte) 0);
666-
int keyLen = encoded.length;
667-
if (!key.getAlgorithm().equalsIgnoreCase("AES") ||
668-
!AESCrypt.isKeySizeValid(keyLen) ||
669-
(fixedKeySize != -1 && fixedKeySize != keyLen)) {
670-
throw new InvalidKeyException("Invalid key length: " +
671-
keyLen + " bytes");
672-
}
673-
return Math.multiplyExact(keyLen, 8);
674681
}
675682

676683
/**

test/jdk/com/sun/crypto/provider/Cipher/KeyWrap/TestKeySizeCheck.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8248268
26+
* @bug 8248268 8302225
2727
* @summary Verify cipher key size restriction is enforced properly with IKE
2828
* @run main TestKeySizeCheck
2929
*/
@@ -43,6 +43,8 @@ public class TestKeySizeCheck {
4343
}
4444
}
4545

46+
private static final int[] AES_KEYSIZES = { 128, 192, 256 };
47+
4648
private static SecretKey getKey(int sizeInBytes) {
4749
if (sizeInBytes <= BYTES_32.length) {
4850
return new SecretKeySpec(BYTES_32, 0, sizeInBytes, "AES");
@@ -64,19 +66,33 @@ public static void test(String algo, int[] invalidKeySizes)
6466
int[] modes = { Cipher.ENCRYPT_MODE, Cipher.WRAP_MODE };
6567
for (int ks : invalidKeySizes) {
6668
System.out.println("keysize: " + ks);
67-
SecretKey key = getKey(ks);
69+
SecretKey key = getKey(ks >> 3);
6870

6971
for (int m : modes) {
7072
try {
7173
c.init(m, key);
7274
throw new RuntimeException("Expected IKE not thrown for "
7375
+ getModeStr(m));
7476
} catch (InvalidKeyException ike) {
75-
System.out.println(" => expected IKE thrown for "
76-
+ getModeStr(m));
77+
System.out.println(getModeStr(m) + " => got expected IKE");
7778
}
7879
}
7980
}
81+
82+
// now test against the valid key size(s) and make sure they work
83+
int underscoreIdx = algo.indexOf("_");
84+
int[] validKeySizes = (algo.indexOf("_") == -1 ?
85+
AES_KEYSIZES : new int[] { Integer.parseInt(algo.substring
86+
(underscoreIdx + 1, underscoreIdx + 4)) });
87+
for (int ks : validKeySizes) {
88+
System.out.println("keysize: " + ks);
89+
SecretKey key = getKey(ks >> 3);
90+
91+
for (int m : modes) {
92+
c.init(m, key);
93+
System.out.println(getModeStr(m) + " => ok");
94+
}
95+
}
8096
}
8197

8298
public static void main(String[] argv) throws Exception {

0 commit comments

Comments
 (0)