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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package com.sun.crypto.provider; package com.sun.crypto.provider;
import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.security.*; import java.security.*;
@ -347,28 +348,40 @@ public final class RSACipher extends CipherSpi {
throw new IllegalBlockSizeException("Data must not be longer " throw new IllegalBlockSizeException("Data must not be longer "
+ "than " + buffer.length + " bytes"); + "than " + buffer.length + " bytes");
} }
byte[] paddingCopy = null;
byte[] result = null;
try { try {
byte[] data;
switch (mode) { switch (mode) {
case MODE_SIGN: case MODE_SIGN:
data = padding.pad(buffer, 0, bufOfs); paddingCopy = padding.pad(buffer, 0, bufOfs);
return RSACore.rsa(data, privateKey, true); result = RSACore.rsa(paddingCopy, privateKey, true);
break;
case MODE_VERIFY: case MODE_VERIFY:
byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs); byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
data = RSACore.rsa(verifyBuffer, publicKey); paddingCopy = RSACore.rsa(verifyBuffer, publicKey);
return padding.unpad(data); result = padding.unpad(paddingCopy);
break;
case MODE_ENCRYPT: case MODE_ENCRYPT:
data = padding.pad(buffer, 0, bufOfs); paddingCopy = padding.pad(buffer, 0, bufOfs);
return RSACore.rsa(data, publicKey); result = RSACore.rsa(paddingCopy, publicKey);
break;
case MODE_DECRYPT: case MODE_DECRYPT:
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
data = RSACore.rsa(decryptBuffer, privateKey, false); paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false);
return padding.unpad(data); result = padding.unpad(paddingCopy);
break;
default: default:
throw new AssertionError("Internal error"); throw new AssertionError("Internal error");
} }
return result;
} finally { } finally {
Arrays.fill(buffer, 0, bufOfs, (byte)0);
bufOfs = 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(); byte[] result = doFinal();
int n = result.length; int n = result.length;
System.arraycopy(result, 0, out, outOfs, n); System.arraycopy(result, 0, out, outOfs, n);
Arrays.fill(result, (byte)0);
return n; return n;
} }
@ -414,6 +428,7 @@ public final class RSACipher extends CipherSpi {
if ((encoded == null) || (encoded.length == 0)) { if ((encoded == null) || (encoded.length == 0)) {
throw new InvalidKeyException("Could not obtain encoded key"); throw new InvalidKeyException("Could not obtain encoded key");
} }
try {
if (encoded.length > buffer.length) { if (encoded.length > buffer.length) {
throw new InvalidKeyException("Key is too long for wrapping"); throw new InvalidKeyException("Key is too long for wrapping");
} }
@ -424,6 +439,9 @@ public final class RSACipher extends CipherSpi {
// should not occur // should not occur
throw new InvalidKeyException("Wrapping failed", e); throw new InvalidKeyException("Wrapping failed", e);
} }
} finally {
Arrays.fill(encoded, (byte)0);
}
} }
// see JCE spec // see JCE spec
@ -453,6 +471,7 @@ public final class RSACipher extends CipherSpi {
throw new InvalidKeyException("Unwrapping failed", e); throw new InvalidKeyException("Unwrapping failed", e);
} }
try {
if (isTlsRsaPremasterSecret) { if (isTlsRsaPremasterSecret) {
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
throw new IllegalStateException( throw new IllegalStateException(
@ -461,12 +480,17 @@ public final class RSACipher extends CipherSpi {
// polish the TLS premaster secret // polish the TLS premaster secret
encoded = KeyUtil.checkTlsPreMasterSecretKey( encoded = KeyUtil.checkTlsPreMasterSecretKey(
((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
random, encoded, (failover != null)); random, encoded, (failover != null));
} }
return ConstructKeys.constructKey(encoded, algorithm, type); return ConstructKeys.constructKey(encoded, algorithm, type);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
} }
// see JCE spec // 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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)) { if ((n == len + 1) && (b[0] == 0)) {
byte[] t = new byte[len]; byte[] t = new byte[len];
System.arraycopy(b, 1, t, 0, len); System.arraycopy(b, 1, t, 0, len);
Arrays.fill(b, (byte)0);
return t; return t;
} }
// must be smaller // must be smaller
assert (n < len); assert (n < len);
byte[] t = new byte[len]; byte[] t = new byte[len];
System.arraycopy(b, 0, t, (len - n), n); System.arraycopy(b, 0, t, (len - n), n);
Arrays.fill(b, (byte)0);
return t; 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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. * Pad the data and return the padded block.
*/ */
public byte[] pad(byte[] data, int ofs, int len) public byte[] pad(byte[] data) throws BadPaddingException {
throws BadPaddingException { return pad(data, 0, data.length);
return pad(RSACore.convert(data, ofs, len));
} }
/** /**
* Pad the data and return the padded block. * Pad the data and return the padded block.
*/ */
public byte[] pad(byte[] data) throws BadPaddingException { public byte[] pad(byte[] data, int ofs, int len)
if (data.length > maxDataSize) { throws BadPaddingException {
if (len > maxDataSize) {
throw new BadPaddingException("Data must be shorter than " throw new BadPaddingException("Data must be shorter than "
+ (maxDataSize + 1) + " bytes but received " + (maxDataSize + 1) + " bytes but received "
+ data.length + " bytes."); + len + " bytes.");
} }
switch (type) { switch (type) {
case PAD_NONE: case PAD_NONE:
return data; return RSACore.convert(data, ofs, len);
case PAD_BLOCKTYPE_1: case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2: case PAD_BLOCKTYPE_2:
return padV15(data); return padV15(data, ofs, len);
case PAD_OAEP_MGF1: case PAD_OAEP_MGF1:
return padOAEP(data); return padOAEP(data, ofs, len);
default: default:
throw new AssertionError(); 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. * 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). * 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]; byte[] padded = new byte[paddedSize];
System.arraycopy(data, 0, padded, paddedSize - data.length, System.arraycopy(data, ofs, padded, paddedSize - len, len);
data.length); int psSize = paddedSize - 3 - len;
int psSize = paddedSize - 3 - data.length;
int k = 0; int k = 0;
padded[k++] = 0; padded[k++] = 0;
padded[k++] = (byte)type; padded[k++] = (byte)type;
@ -388,7 +379,7 @@ public final class RSAPadding {
* PKCS#1 v2.0 OAEP padding (MGF1). * PKCS#1 v2.0 OAEP padding (MGF1).
* Paragraph references refer to PKCS#1 v2.1 (June 14, 2002) * 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) { if (random == null) {
random = JCAUtil.getSecureRandom(); random = JCAUtil.getSecureRandom();
} }
@ -415,7 +406,7 @@ public final class RSAPadding {
int dbLen = EM.length - dbStart; int dbLen = EM.length - dbStart;
// start of message M in EM // start of message M in EM
int mStart = paddedSize - M.length; int mStart = paddedSize - len;
// build DB // build DB
// 2.b: Concatenate lHash, PS, a single octet with hexadecimal value // 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) // (note that PS is all zeros)
System.arraycopy(lHash, 0, EM, dbStart, hLen); System.arraycopy(lHash, 0, EM, dbStart, hLen);
EM[mStart - 1] = 1; EM[mStart - 1] = 1;
System.arraycopy(M, 0, EM, mStart, M.length); System.arraycopy(M, ofs, EM, mStart, len);
// produce maskedDB // produce maskedDB
mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart); mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart);