8302017: Allocate BadPaddingException only if it will be thrown

Reviewed-by: xuelei
This commit is contained in:
Valerie Peng 2023-07-27 21:24:03 +00:00
parent c55d29ff11
commit c27c87786a
5 changed files with 130 additions and 66 deletions

View file

@ -30,7 +30,6 @@ import java.util.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.BadPaddingException;
import javax.crypto.spec.PSource;
import javax.crypto.spec.OAEPParameterSpec;
@ -235,24 +234,22 @@ public final class RSAPadding {
}
/**
* Pad the data and return the padded block.
* Pad the data and return the result or null if error occurred.
*/
public byte[] pad(byte[] data) throws BadPaddingException {
public byte[] pad(byte[] data) {
return pad(data, 0, data.length);
}
/**
* Pad the data and return the padded block.
* Pad the data and return the result or null if error occurred.
*/
public byte[] pad(byte[] data, int ofs, int len)
throws BadPaddingException {
public byte[] pad(byte[] data, int ofs, int len) {
if (len > maxDataSize) {
throw new BadPaddingException("Data must be shorter than "
+ (maxDataSize + 1) + " bytes but received "
+ len + " bytes.");
return null;
}
switch (type) {
case PAD_NONE:
// assert len == paddedSize and data.length - ofs > len?
return RSACore.convert(data, ofs, len);
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
@ -265,24 +262,18 @@ public final class RSAPadding {
}
/**
* Unpad the padded block and return the data.
* Unpad the padded block and return the result or null if error occurred.
*/
public byte[] unpad(byte[] padded) throws BadPaddingException {
if (padded.length != paddedSize) {
throw new BadPaddingException("Decryption error. " +
"The padded array length (" + padded.length +
") is not the specified padded size (" + paddedSize + ")");
}
switch (type) {
case PAD_NONE:
return padded;
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
return unpadV15(padded);
case PAD_OAEP_MGF1:
return unpadOAEP(padded);
default:
throw new AssertionError();
public byte[] unpad(byte[] padded) {
if (padded.length == paddedSize) {
return switch(type) {
case PAD_NONE -> padded;
case PAD_BLOCKTYPE_1, PAD_BLOCKTYPE_2 -> unpadV15(padded);
case PAD_OAEP_MGF1 -> unpadOAEP(padded);
default -> throw new AssertionError();
};
} else {
return null;
}
}
@ -326,10 +317,10 @@ public final class RSAPadding {
/**
* PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)).
*
* Return the result or null if error occurred.
* Note that we want to make it a constant-time operation
*/
private byte[] unpadV15(byte[] padded) throws BadPaddingException {
private byte[] unpadV15(byte[] padded) {
int k = 0;
boolean bp = false;
@ -365,10 +356,8 @@ public final class RSAPadding {
byte[] data = new byte[n];
System.arraycopy(padded, p, data, 0, n);
BadPaddingException bpe = new BadPaddingException("Decryption error");
if (bp) {
throw bpe;
return null;
} else {
return data;
}
@ -377,6 +366,7 @@ public final class RSAPadding {
/**
* PKCS#1 v2.0 OAEP padding (MGF1).
* Paragraph references refer to PKCS#1 v2.1 (June 14, 2002)
* Return the result or null if error occurred.
*/
private byte[] padOAEP(byte[] M, int ofs, int len) {
if (random == null) {
@ -427,8 +417,9 @@ public final class RSAPadding {
/**
* PKCS#1 v2.1 OAEP unpadding (MGF1).
* Return the result or null if error occurred.
*/
private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
private byte[] unpadOAEP(byte[] padded) {
byte[] EM = padded;
boolean bp = false;
int hLen = lHash.length;
@ -484,12 +475,6 @@ public final class RSAPadding {
byte [] m = new byte[EM.length - mStart];
System.arraycopy(EM, mStart, m, 0, m.length);
BadPaddingException bpe = new BadPaddingException("Decryption error");
if (bp) {
throw bpe;
} else {
return m;
}
return (bp? null : m);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -25,7 +25,6 @@
package sun.security.rsa;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.*;
@ -190,10 +189,13 @@ abstract class RSASignature extends SignatureSpi {
try {
byte[] encoded = RSAUtil.encodeSignature(digestOID, digest);
byte[] padded = padding.pad(encoded);
return RSACore.rsa(padded, privateKey, true);
if (padded != null) {
return RSACore.rsa(padded, privateKey, true);
}
} catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e);
}
throw new SignatureException("Could not sign data");
}
// verify the data and return the result. See JCA doc
@ -205,27 +207,21 @@ abstract class RSASignature extends SignatureSpi {
}
try {
if (sigBytes.length != RSACore.getByteLength(publicKey)) {
throw new SignatureException("Signature length not correct: got " +
throw new SignatureException("Bad signature length: got " +
sigBytes.length + " but was expecting " +
RSACore.getByteLength(publicKey));
}
byte[] digest = getDigestValue();
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
byte[] unpadded = padding.unpad(decrypted);
// https://www.rfc-editor.org/rfc/rfc8017.html#section-8.2.2
// Step 4 suggests comparing the encoded message instead of the
// decoded, but some vendors might omit the NULL params in
// digest algorithm identifier.
byte[] decodedDigest = RSAUtil.decodeSignature(digestOID, unpadded);
return MessageDigest.isEqual(digest, decodedDigest);
// Step 4 suggests comparing the encoded message
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
byte[] digest = getDigestValue();
byte[] encoded = RSAUtil.encodeSignature(digestOID, digest);
byte[] padded = padding.pad(encoded);
return MessageDigest.isEqual(padded, decrypted);
} catch (javax.crypto.BadPaddingException e) {
// occurs if the app has used the wrong RSA public key
// or if sigBytes is invalid
// return false rather than propagating the exception for
// compatibility/ease of use
return false;
} catch (IOException e) {
throw new SignatureException("Signature encoding error", e);
} finally {
resetDigest();
}