8258419: RSA cipher buffer cleanup

Reviewed-by: valeriep
This commit is contained in:
Weijun Wang 2020-12-15 22:49:35 +00:00
parent 1f556d22ca
commit b97fe6c410
3 changed files with 72 additions and 55 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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,6 +25,7 @@
package com.sun.crypto.provider;
import java.util.Arrays;
import java.util.Locale;
import java.security.*;
@ -347,28 +348,40 @@ public final class RSACipher extends CipherSpi {
throw new IllegalBlockSizeException("Data must not be longer "
+ "than " + buffer.length + " bytes");
}
byte[] paddingCopy = null;
byte[] result = null;
try {
byte[] data;
switch (mode) {
case MODE_SIGN:
data = padding.pad(buffer, 0, bufOfs);
return RSACore.rsa(data, privateKey, true);
paddingCopy = padding.pad(buffer, 0, bufOfs);
result = RSACore.rsa(paddingCopy, privateKey, true);
break;
case MODE_VERIFY:
byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
data = RSACore.rsa(verifyBuffer, publicKey);
return padding.unpad(data);
paddingCopy = RSACore.rsa(verifyBuffer, publicKey);
result = padding.unpad(paddingCopy);
break;
case MODE_ENCRYPT:
data = padding.pad(buffer, 0, bufOfs);
return RSACore.rsa(data, publicKey);
paddingCopy = padding.pad(buffer, 0, bufOfs);
result = RSACore.rsa(paddingCopy, publicKey);
break;
case MODE_DECRYPT:
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
data = RSACore.rsa(decryptBuffer, privateKey, false);
return padding.unpad(data);
paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
result = padding.unpad(paddingCopy);
break;
default:
throw new AssertionError("Internal error");
}
return result;
} finally {
Arrays.fill(buffer, 0, bufOfs, (byte)0);
bufOfs = 0;
if (paddingCopy != null // will not happen
&& paddingCopy != buffer // already cleaned
&& paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT!
Arrays.fill(paddingCopy, (byte)0);
}
}
}
@ -404,6 +417,7 @@ public final class RSACipher extends CipherSpi {
byte[] result = doFinal();
int n = result.length;
System.arraycopy(result, 0, out, outOfs, n);
Arrays.fill(result, (byte)0);
return n;
}
@ -414,15 +428,19 @@ public final class RSACipher extends CipherSpi {
if ((encoded == null) || (encoded.length == 0)) {
throw new InvalidKeyException("Could not obtain encoded key");
}
if (encoded.length > buffer.length) {
throw new InvalidKeyException("Key is too long for wrapping");
}
update(encoded, 0, encoded.length);
try {
return doFinal();
} catch (BadPaddingException e) {
// should not occur
throw new InvalidKeyException("Wrapping failed", e);
if (encoded.length > buffer.length) {
throw new InvalidKeyException("Key is too long for wrapping");
}
update(encoded, 0, encoded.length);
try {
return doFinal();
} catch (BadPaddingException e) {
// should not occur
throw new InvalidKeyException("Wrapping failed", e);
}
} finally {
Arrays.fill(encoded, (byte)0);
}
}
@ -453,20 +471,26 @@ public final class RSACipher extends CipherSpi {
throw new InvalidKeyException("Unwrapping failed", e);
}
if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException(
"No TlsRsaPremasterSecretParameterSpec specified");
try {
if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException(
"No TlsRsaPremasterSecretParameterSpec specified");
}
// polish the TLS premaster secret
encoded = KeyUtil.checkTlsPreMasterSecretKey(
((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
random, encoded, (failover != null));
}
// polish the TLS premaster secret
encoded = KeyUtil.checkTlsPreMasterSecretKey(
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
random, encoded, (failover != null));
return ConstructKeys.constructKey(encoded, algorithm, type);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
return ConstructKeys.constructKey(encoded, algorithm, type);
}
// see JCE spec

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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
@ -231,12 +231,14 @@ public final class RSACore {
if ((n == len + 1) && (b[0] == 0)) {
byte[] t = new byte[len];
System.arraycopy(b, 1, t, 0, len);
Arrays.fill(b, (byte)0);
return t;
}
// must be smaller
assert (n < len);
byte[] t = new byte[len];
System.arraycopy(b, 0, t, (len - n), n);
Arrays.fill(b, (byte)0);
return t;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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
@ -238,41 +238,33 @@ public final class RSAPadding {
/**
* Pad the data and return the padded block.
*/
public byte[] pad(byte[] data, int ofs, int len)
throws BadPaddingException {
return pad(RSACore.convert(data, ofs, len));
public byte[] pad(byte[] data) throws BadPaddingException {
return pad(data, 0, data.length);
}
/**
* Pad the data and return the padded block.
*/
public byte[] pad(byte[] data) throws BadPaddingException {
if (data.length > maxDataSize) {
public byte[] pad(byte[] data, int ofs, int len)
throws BadPaddingException {
if (len > maxDataSize) {
throw new BadPaddingException("Data must be shorter than "
+ (maxDataSize + 1) + " bytes but received "
+ data.length + " bytes.");
+ len + " bytes.");
}
switch (type) {
case PAD_NONE:
return data;
return RSACore.convert(data, ofs, len);
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
return padV15(data);
return padV15(data, ofs, len);
case PAD_OAEP_MGF1:
return padOAEP(data);
return padOAEP(data, ofs, len);
default:
throw new AssertionError();
}
}
/**
* Unpad the padded block and return the data.
*/
public byte[] unpad(byte[] padded, int ofs, int len)
throws BadPaddingException {
return unpad(RSACore.convert(padded, ofs, len));
}
/**
* Unpad the padded block and return the data.
*/
@ -298,11 +290,10 @@ public final class RSAPadding {
/**
* PKCS#1 v1.5 padding (blocktype 1 and 2).
*/
private byte[] padV15(byte[] data) throws BadPaddingException {
private byte[] padV15(byte[] data, int ofs, int len) throws BadPaddingException {
byte[] padded = new byte[paddedSize];
System.arraycopy(data, 0, padded, paddedSize - data.length,
data.length);
int psSize = paddedSize - 3 - data.length;
System.arraycopy(data, ofs, padded, paddedSize - len, len);
int psSize = paddedSize - 3 - len;
int k = 0;
padded[k++] = 0;
padded[k++] = (byte)type;
@ -388,7 +379,7 @@ public final class RSAPadding {
* PKCS#1 v2.0 OAEP padding (MGF1).
* Paragraph references refer to PKCS#1 v2.1 (June 14, 2002)
*/
private byte[] padOAEP(byte[] M) throws BadPaddingException {
private byte[] padOAEP(byte[] M, int ofs, int len) throws BadPaddingException {
if (random == null) {
random = JCAUtil.getSecureRandom();
}
@ -415,7 +406,7 @@ public final class RSAPadding {
int dbLen = EM.length - dbStart;
// start of message M in EM
int mStart = paddedSize - M.length;
int mStart = paddedSize - len;
// build DB
// 2.b: Concatenate lHash, PS, a single octet with hexadecimal value
@ -424,7 +415,7 @@ public final class RSAPadding {
// (note that PS is all zeros)
System.arraycopy(lHash, 0, EM, dbStart, hLen);
EM[mStart - 1] = 1;
System.arraycopy(M, 0, EM, mStart, M.length);
System.arraycopy(M, ofs, EM, mStart, len);
// produce maskedDB
mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart);