Skip to content

Commit 2131e40

Browse files
author
Alexey Bakhtin
committed
8302017: Allocate BadPaddingException only if it will be thrown
Reviewed-by: mbalao, andrew Backport-of: 334b977259930368160db705c1f2feda0b0e8707
1 parent 31162fb commit 2131e40

File tree

5 files changed

+137
-62
lines changed

5 files changed

+137
-62
lines changed

jdk/src/share/classes/com/sun/crypto/provider/RSACipher.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 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
@@ -353,21 +353,38 @@ private byte[] doFinal() throws BadPaddingException,
353353
switch (mode) {
354354
case MODE_SIGN:
355355
paddingCopy = padding.pad(buffer, 0, bufOfs);
356-
result = RSACore.rsa(paddingCopy, privateKey, true);
356+
if (paddingCopy != null) {
357+
result = RSACore.rsa(paddingCopy, privateKey, true);
358+
} else {
359+
throw new BadPaddingException("Padding error in signing");
360+
}
357361
break;
358362
case MODE_VERIFY:
359363
byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
360364
paddingCopy = RSACore.rsa(verifyBuffer, publicKey);
361365
result = padding.unpad(paddingCopy);
366+
if (result == null) {
367+
throw new BadPaddingException
368+
("Padding error in verification");
369+
}
362370
break;
363371
case MODE_ENCRYPT:
364372
paddingCopy = padding.pad(buffer, 0, bufOfs);
365-
result = RSACore.rsa(paddingCopy, publicKey);
373+
if (paddingCopy != null) {
374+
result = RSACore.rsa(paddingCopy, publicKey);
375+
} else {
376+
throw new BadPaddingException
377+
("Padding error in encryption");
378+
}
366379
break;
367380
case MODE_DECRYPT:
368381
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
369382
paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
370383
result = padding.unpad(paddingCopy);
384+
if (result == null) {
385+
throw new BadPaddingException
386+
("Padding error in decryption");
387+
}
371388
break;
372389
default:
373390
throw new AssertionError("Internal error");
@@ -376,9 +393,9 @@ private byte[] doFinal() throws BadPaddingException,
376393
} finally {
377394
Arrays.fill(buffer, 0, bufOfs, (byte)0);
378395
bufOfs = 0;
379-
if (paddingCopy != null // will not happen
396+
if (paddingCopy != null
380397
&& paddingCopy != buffer // already cleaned
381-
&& paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT!
398+
&& paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT
382399
Arrays.fill(paddingCopy, (byte)0);
383400
}
384401
}

jdk/src/share/classes/sun/security/pkcs11/P11Signature.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 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
@@ -728,9 +728,12 @@ private byte[] pkcs1Pad(byte[] data) {
728728
int len = (p11Key.length() + 7) >> 3;
729729
RSAPadding padding = RSAPadding.getInstance
730730
(RSAPadding.PAD_BLOCKTYPE_1, len);
731-
byte[] padded = padding.pad(data);
732-
return padded;
733-
} catch (GeneralSecurityException e) {
731+
byte[] result = padding.pad(data);
732+
if (result == null) {
733+
throw new ProviderException("Error padding data");
734+
}
735+
return result;
736+
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
734737
throw new ProviderException(e);
735738
}
736739
}

jdk/src/share/classes/sun/security/rsa/RSAPadding.java

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.security.*;
3131
import java.security.spec.*;
3232

33-
import javax.crypto.BadPaddingException;
3433
import javax.crypto.spec.PSource;
3534
import javax.crypto.spec.OAEPParameterSpec;
3635

@@ -236,24 +235,22 @@ public int getMaxDataSize() {
236235
}
237236

238237
/**
239-
* Pad the data and return the padded block.
238+
* Pad the data and return the result or null if error occurred.
240239
*/
241-
public byte[] pad(byte[] data) throws BadPaddingException {
240+
public byte[] pad(byte[] data) {
242241
return pad(data, 0, data.length);
243242
}
244243

245244
/**
246-
* Pad the data and return the padded block.
245+
* Pad the data and return the result or null if error occurred.
247246
*/
248-
public byte[] pad(byte[] data, int ofs, int len)
249-
throws BadPaddingException {
247+
public byte[] pad(byte[] data, int ofs, int len) {
250248
if (len > maxDataSize) {
251-
throw new BadPaddingException("Data must be shorter than "
252-
+ (maxDataSize + 1) + " bytes but received "
253-
+ len + " bytes.");
249+
return null;
254250
}
255251
switch (type) {
256252
case PAD_NONE:
253+
// assert len == paddedSize and data.length - ofs > len?
257254
return RSACore.convert(data, ofs, len);
258255
case PAD_BLOCKTYPE_1:
259256
case PAD_BLOCKTYPE_2:
@@ -266,31 +263,30 @@ public byte[] pad(byte[] data, int ofs, int len)
266263
}
267264

268265
/**
269-
* Unpad the padded block and return the data.
266+
* Unpad the padded block and return the result or null if error occurred.
270267
*/
271-
public byte[] unpad(byte[] padded) throws BadPaddingException {
272-
if (padded.length != paddedSize) {
273-
throw new BadPaddingException("Decryption error." +
274-
"The padded array length (" + padded.length +
275-
") is not the specified padded size (" + paddedSize + ")");
276-
}
277-
switch (type) {
278-
case PAD_NONE:
279-
return padded;
280-
case PAD_BLOCKTYPE_1:
281-
case PAD_BLOCKTYPE_2:
282-
return unpadV15(padded);
283-
case PAD_OAEP_MGF1:
284-
return unpadOAEP(padded);
285-
default:
286-
throw new AssertionError();
268+
public byte[] unpad(byte[] padded) {
269+
if (padded.length == paddedSize) {
270+
switch (type) {
271+
case PAD_NONE:
272+
return padded;
273+
case PAD_BLOCKTYPE_1:
274+
case PAD_BLOCKTYPE_2:
275+
return unpadV15(padded);
276+
case PAD_OAEP_MGF1:
277+
return unpadOAEP(padded);
278+
default:
279+
throw new AssertionError();
280+
}
281+
} else {
282+
return null;
287283
}
288284
}
289285

290286
/**
291287
* PKCS#1 v1.5 padding (blocktype 1 and 2).
292288
*/
293-
private byte[] padV15(byte[] data, int ofs, int len) throws BadPaddingException {
289+
private byte[] padV15(byte[] data, int ofs, int len) {
294290
byte[] padded = new byte[paddedSize];
295291
System.arraycopy(data, ofs, padded, paddedSize - len, len);
296292
int psSize = paddedSize - 3 - len;
@@ -328,10 +324,10 @@ private byte[] padV15(byte[] data, int ofs, int len) throws BadPaddingException
328324

329325
/**
330326
* PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)).
331-
*
327+
* Return the result or null if error occurred.
332328
* Note that we want to make it a constant-time operation
333329
*/
334-
private byte[] unpadV15(byte[] padded) throws BadPaddingException {
330+
private byte[] unpadV15(byte[] padded) {
335331
int k = 0;
336332
boolean bp = false;
337333

@@ -367,10 +363,8 @@ private byte[] unpadV15(byte[] padded) throws BadPaddingException {
367363
byte[] data = new byte[n];
368364
System.arraycopy(padded, p, data, 0, n);
369365

370-
BadPaddingException bpe = new BadPaddingException("Decryption error");
371-
372366
if (bp) {
373-
throw bpe;
367+
return null;
374368
} else {
375369
return data;
376370
}
@@ -379,8 +373,9 @@ private byte[] unpadV15(byte[] padded) throws BadPaddingException {
379373
/**
380374
* PKCS#1 v2.0 OAEP padding (MGF1).
381375
* Paragraph references refer to PKCS#1 v2.1 (June 14, 2002)
376+
* Return the result or null if error occurred.
382377
*/
383-
private byte[] padOAEP(byte[] M, int ofs, int len) throws BadPaddingException {
378+
private byte[] padOAEP(byte[] M, int ofs, int len) {
384379
if (random == null) {
385380
random = JCAUtil.getSecureRandom();
386381
}
@@ -429,8 +424,9 @@ private byte[] padOAEP(byte[] M, int ofs, int len) throws BadPaddingException {
429424

430425
/**
431426
* PKCS#1 v2.1 OAEP unpadding (MGF1).
427+
* Return the result or null if error occurred.
432428
*/
433-
private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
429+
private byte[] unpadOAEP(byte[] padded) {
434430
byte[] EM = padded;
435431
boolean bp = false;
436432
int hLen = lHash.length;
@@ -486,12 +482,6 @@ private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
486482
byte [] m = new byte[EM.length - mStart];
487483
System.arraycopy(EM, mStart, m, 0, m.length);
488484

489-
BadPaddingException bpe = new BadPaddingException("Decryption error");
490-
491-
if (bp) {
492-
throw bpe;
493-
} else {
494-
return m;
495-
}
485+
return (bp? null : m);
496486
}
497487
}

jdk/src/share/classes/sun/security/rsa/RSASignature.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 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
@@ -189,13 +189,15 @@ protected byte[] engineSign() throws SignatureException {
189189
try {
190190
byte[] encoded = encodeSignature(digestOID, digest);
191191
byte[] padded = padding.pad(encoded);
192-
byte[] encrypted = RSACore.rsa(padded, privateKey, true);
193-
return encrypted;
192+
if (padded != null) {
193+
return RSACore.rsa(padded, privateKey, true);
194+
}
194195
} catch (GeneralSecurityException e) {
195196
throw new SignatureException("Could not sign data", e);
196197
} catch (IOException e) {
197198
throw new SignatureException("Could not encode data", e);
198199
}
200+
throw new SignatureException("Could not sign data");
199201
}
200202

201203
// verify the data and return the result. See JCA doc
@@ -206,21 +208,21 @@ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
206208
}
207209

208210
if (sigBytes.length != RSACore.getByteLength(publicKey)) {
209-
throw new SignatureException("Signature length not correct: got " +
211+
throw new SignatureException("Bad signature length: got " +
210212
sigBytes.length + " but was expecting " +
211213
RSACore.getByteLength(publicKey));
212214
}
213-
byte[] digest = getDigestValue();
215+
214216
try {
217+
// https://www.rfc-editor.org/rfc/rfc8017.html#section-8.2.2
218+
// Step 4 suggests comparing the encoded message
215219
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
216-
byte[] unpadded = padding.unpad(decrypted);
217-
byte[] decodedDigest = decodeSignature(digestOID, unpadded);
218-
return MessageDigest.isEqual(digest, decodedDigest);
220+
221+
byte[] digest = getDigestValue();
222+
byte[] encoded = encodeSignature(digestOID, digest);
223+
byte[] padded = padding.pad(encoded);
224+
return MessageDigest.isEqual(padded, decrypted);
219225
} catch (javax.crypto.BadPaddingException e) {
220-
// occurs if the app has used the wrong RSA public key
221-
// or if sigBytes is invalid
222-
// return false rather than propagating the exception for
223-
// compatibility/ease of use
224226
return false;
225227
} catch (IOException e) {
226228
throw new SignatureException("Signature encoding error", e);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
/*
24+
* @test
25+
* @bug 8302017
26+
* @summary Ensure that RSAPadding class works as expected after refactoring
27+
* @modules java.base/sun.security.rsa
28+
*/
29+
import java.util.Arrays;
30+
import sun.security.rsa.RSAPadding;
31+
32+
public class RSAPaddingCheck {
33+
34+
private static int[] PADDING_TYPES = {
35+
RSAPadding.PAD_BLOCKTYPE_1,
36+
RSAPadding.PAD_BLOCKTYPE_2,
37+
RSAPadding.PAD_NONE,
38+
RSAPadding.PAD_OAEP_MGF1,
39+
};
40+
41+
public static void main(String[] args) throws Exception {
42+
int size = 2048 >> 3;
43+
byte[] testData = "This is some random to-be-padded Data".getBytes();
44+
for (int type : PADDING_TYPES) {
45+
byte[] data = (type == RSAPadding.PAD_NONE?
46+
Arrays.copyOf(testData, size) : testData);
47+
System.out.println("Testing PaddingType: " + type);
48+
RSAPadding padding = RSAPadding.getInstance(type, size);
49+
byte[] paddedData = padding.pad(data);
50+
if (paddedData == null) {
51+
throw new RuntimeException("Unexpected padding op failure!");
52+
}
53+
54+
byte[] data2 = padding.unpad(paddedData);
55+
if (data2 == null) {
56+
throw new RuntimeException("Unexpected unpadding op failure!");
57+
}
58+
if (!Arrays.equals(data, data2)) {
59+
throw new RuntimeException("diff check failure!");
60+
}
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)