8258419: RSA cipher buffer cleanup
Reviewed-by: valeriep
This commit is contained in:
parent
1f556d22ca
commit
b97fe6c410
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user