8258915: Temporary buffer cleanup

Reviewed-by: valeriep
This commit is contained in:
Weijun Wang 2021-04-22 18:11:43 +00:00
parent 31d8a19e47
commit f834557ae0
79 changed files with 1517 additions and 1039 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -40,6 +40,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.ProviderException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
/**
* This class implements the AES algorithm in its various modes
@ -163,9 +164,12 @@ abstract class AESCipher extends CipherSpi {
byte[] value = key.getEncoded();
if (value == null) {
throw new InvalidKeyException("Key encoding must not be null");
} else if (value.length != fixedKeySize) {
throw new InvalidKeyException("The key must be " +
fixedKeySize + " bytes");
} else {
Arrays.fill(value, (byte)0);
if (value.length != fixedKeySize) {
throw new InvalidKeyException("The key must be " +
fixedKeySize + " bytes");
}
}
}
}
@ -515,6 +519,7 @@ abstract class AESCipher extends CipherSpi {
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
Arrays.fill(encoded, (byte)0);
if (!AESCrypt.isKeySizeValid(encoded.length)) {
throw new InvalidKeyException("Invalid AES key length: " +
encoded.length + " bytes");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -94,6 +94,9 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
if (!MessageDigest.isEqual(key, lastKey)) {
// re-generate session key 'sessionK' when cipher key changes
makeSessionKey(key);
if (lastKey != null) {
Arrays.fill(lastKey, (byte)0);
}
lastKey = key.clone(); // save cipher key
}
@ -673,12 +676,23 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
// and expand them into arrays of ints.
int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
int[] expandedKd = expandToSubKey(Kd, true); // decrypting==true
Arrays.fill(tk, 0);
for (int[] ia: Ke) {
Arrays.fill(ia, 0);
}
for (int[] ia: Kd) {
Arrays.fill(ia, 0);
}
ROUNDS_12 = (ROUNDS>=12);
ROUNDS_14 = (ROUNDS==14);
limit = ROUNDS*4;
// store the expanded sub keys into 'sessionK'
if (sessionK != null) {
// erase the previous values in sessionK
Arrays.fill(sessionK[0], 0);
Arrays.fill(sessionK[1], 0);
}
sessionK = new int[][] { expandedKe, expandedKd };
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -30,6 +30,7 @@ import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@ -112,6 +113,7 @@ public final class AESKeyGenerator extends KeyGeneratorSpi {
byte[] keyBytes = new byte[keySize];
this.random.nextBytes(keyBytes);
aesKey = new SecretKeySpec(keyBytes, "AES");
Arrays.fill(keyBytes, (byte)0);
return aesKey;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2021, 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
@ -198,7 +198,12 @@ abstract class AESWrapCipher extends CipherSpi {
"only be used for key wrapping and unwrapping");
}
AESCipher.checkKeySize(key, fixedKeySize);
cipher.init(decrypting, key.getAlgorithm(), key.getEncoded());
byte[] encoded = key.getEncoded();
try {
cipher.init(decrypting, key.getAlgorithm(), encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
}
/**
@ -374,6 +379,7 @@ abstract class AESWrapCipher extends CipherSpi {
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
Arrays.fill(encoded, (byte)0);
if (!AESCrypt.isKeySizeValid(encoded.length)) {
throw new InvalidKeyException("Invalid key length: " +
encoded.length + " bytes");
@ -404,38 +410,42 @@ abstract class AESWrapCipher extends CipherSpi {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
}
byte[] out = new byte[Math.addExact(keyVal.length, 8)];
try {
byte[] out = new byte[Math.addExact(keyVal.length, 8)];
if (keyVal.length == 8) {
System.arraycopy(IV, 0, out, 0, IV.length);
System.arraycopy(keyVal, 0, out, IV.length, 8);
cipher.encryptBlock(out, 0, out, 0);
} else {
if (keyVal.length % 8 != 0) {
throw new IllegalBlockSizeException("length of the " +
"to be wrapped key should be multiples of 8 bytes");
}
System.arraycopy(IV, 0, out, 0, IV.length);
System.arraycopy(keyVal, 0, out, IV.length, keyVal.length);
int N = keyVal.length/8;
byte[] buffer = new byte[blksize];
for (int j = 0; j < 6; j++) {
for (int i = 1; i <= N; i++) {
int T = i + j*N;
System.arraycopy(out, 0, buffer, 0, IV.length);
System.arraycopy(out, i*8, buffer, IV.length, 8);
cipher.encryptBlock(buffer, 0, buffer, 0);
for (int k = 1; T != 0; k++) {
byte v = (byte) T;
buffer[IV.length - k] ^= v;
T >>>= 8;
if (keyVal.length == 8) {
System.arraycopy(IV, 0, out, 0, IV.length);
System.arraycopy(keyVal, 0, out, IV.length, 8);
cipher.encryptBlock(out, 0, out, 0);
} else {
if (keyVal.length % 8 != 0) {
throw new IllegalBlockSizeException("length of the " +
"to be wrapped key should be multiples of 8 bytes");
}
System.arraycopy(IV, 0, out, 0, IV.length);
System.arraycopy(keyVal, 0, out, IV.length, keyVal.length);
int N = keyVal.length / 8;
byte[] buffer = new byte[blksize];
for (int j = 0; j < 6; j++) {
for (int i = 1; i <= N; i++) {
int T = i + j * N;
System.arraycopy(out, 0, buffer, 0, IV.length);
System.arraycopy(out, i * 8, buffer, IV.length, 8);
cipher.encryptBlock(buffer, 0, buffer, 0);
for (int k = 1; T != 0; k++) {
byte v = (byte) T;
buffer[IV.length - k] ^= v;
T >>>= 8;
}
System.arraycopy(buffer, 0, out, 0, IV.length);
System.arraycopy(buffer, 8, out, 8 * i, 8);
}
System.arraycopy(buffer, 0, out, 0, IV.length);
System.arraycopy(buffer, 8, out, 8*i, 8);
}
}
return out;
} finally {
Arrays.fill(keyVal, (byte)0);
}
return out;
}
/**
@ -474,38 +484,43 @@ abstract class AESWrapCipher extends CipherSpi {
}
byte[] out = new byte[wrappedKeyLen - 8];
byte[] buffer = new byte[blksize];
if (wrappedKeyLen == 16) {
cipher.decryptBlock(wrappedKey, 0, buffer, 0);
for (int i = 0; i < IV.length; i++) {
if (IV[i] != buffer[i]) {
throw new InvalidKeyException("Integrity check failed");
}
}
System.arraycopy(buffer, IV.length, out, 0, out.length);
} else {
System.arraycopy(wrappedKey, 0, buffer, 0, IV.length);
System.arraycopy(wrappedKey, IV.length, out, 0, out.length);
int N = out.length/8;
for (int j = 5; j >= 0; j--) {
for (int i = N; i > 0; i--) {
int T = i + j*N;
System.arraycopy(out, 8*(i-1), buffer, IV.length, 8);
for (int k = 1; T != 0; k++) {
byte v = (byte) T;
buffer[IV.length - k] ^= v;
T >>>= 8;
try {
if (wrappedKeyLen == 16) {
cipher.decryptBlock(wrappedKey, 0, buffer, 0);
for (int i = 0; i < IV.length; i++) {
if (IV[i] != buffer[i]) {
throw new InvalidKeyException("Integrity check failed");
}
}
System.arraycopy(buffer, IV.length, out, 0, out.length);
} else {
System.arraycopy(wrappedKey, 0, buffer, 0, IV.length);
System.arraycopy(wrappedKey, IV.length, out, 0, out.length);
int N = out.length / 8;
for (int j = 5; j >= 0; j--) {
for (int i = N; i > 0; i--) {
int T = i + j * N;
System.arraycopy(out, 8 * (i - 1), buffer, IV.length, 8);
for (int k = 1; T != 0; k++) {
byte v = (byte) T;
buffer[IV.length - k] ^= v;
T >>>= 8;
}
cipher.decryptBlock(buffer, 0, buffer, 0);
System.arraycopy(buffer, IV.length, out, 8 * (i - 1), 8);
}
}
for (int i = 0; i < IV.length; i++) {
if (IV[i] != buffer[i]) {
throw new InvalidKeyException("Integrity check failed");
}
cipher.decryptBlock(buffer, 0, buffer, 0);
System.arraycopy(buffer, IV.length, out, 8*(i-1), 8);
}
}
for (int i = 0; i < IV.length; i++) {
if (IV[i] != buffer[i]) {
throw new InvalidKeyException("Integrity check failed");
}
}
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
wrappedKeyType);
} finally {
Arrays.fill(out, (byte)0);
Arrays.fill(buffer, (byte)0);
}
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
wrappedKeyType);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.*;
@ -180,6 +181,9 @@ public final class ARCFOURCipher extends CipherSpi {
// init method. Check opmode and key, then call init(byte[]).
private void init(int opmode, Key key) throws InvalidKeyException {
if (lastKey != null) {
Arrays.fill(lastKey, (byte)0);
}
if ((opmode < Cipher.ENCRYPT_MODE) || (opmode > Cipher.UNWRAP_MODE)) {
throw new InvalidKeyException("Unknown opmode: " + opmode);
}
@ -199,6 +203,7 @@ public final class ARCFOURCipher extends CipherSpi {
}
byte[] encodedKey = key.getEncoded();
if ((encodedKey.length < 5) || (encodedKey.length > 128)) {
Arrays.fill(encodedKey, (byte)0);
throw new InvalidKeyException
("Key length must be between 40 and 1024 bit");
}
@ -244,19 +249,31 @@ public final class ARCFOURCipher extends CipherSpi {
if ((encoded == null) || (encoded.length == 0)) {
throw new InvalidKeyException("Could not obtain encoded key");
}
return engineDoFinal(encoded, 0, encoded.length);
try {
return engineDoFinal(encoded, 0, encoded.length);
} finally {
Arrays.fill(encoded, (byte)0);
}
}
// see JCE spec
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
int type) throws InvalidKeyException, NoSuchAlgorithmException {
byte[] encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
return ConstructKeys.constructKey(encoded, algorithm, type);
byte[] encoded = null;
try {
encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
return ConstructKeys.constructKey(encoded, algorithm, type);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
}
// see JCE spec
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encodedKey = getEncodedKey(key);
Arrays.fill(encodedKey, (byte)0);
return Math.multiplyExact(encodedKey.length, 8);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, 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
@ -27,6 +27,8 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import sun.security.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -373,7 +375,9 @@ public final class BlowfishCipher extends CipherSpi {
* @exception InvalidKeyException if <code>key</code> is invalid.
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
return Math.multiplyExact(key.getEncoded().length, 8);
byte[] encodedKey = key.getEncoded();
Arrays.fill(encodedKey, (byte)0);
return Math.multiplyExact(encodedKey.length, 8);
}
/**

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, 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
@ -29,6 +29,7 @@ import java.security.SecureRandom;
import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@ -110,6 +111,10 @@ public final class BlowfishKeyGenerator extends KeyGeneratorSpi {
byte[] keyBytes = new byte[this.keysize];
this.random.nextBytes(keyBytes);
return new SecretKeySpec(keyBytes, "Blowfish");
try {
return new SecretKeySpec(keyBytes, "Blowfish");
} finally {
Arrays.fill(keyBytes, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, 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
@ -33,6 +33,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Objects;
import javax.crypto.*;
import javax.crypto.spec.ChaCha20ParameterSpec;
@ -546,6 +547,9 @@ abstract class ChaCha20Cipher extends CipherSpi {
// assigning them to the object.
byte[] newKeyBytes = getEncodedKey(key);
checkKeyAndNonce(newKeyBytes, newNonce);
if (this.keyBytes != null) {
Arrays.fill(this.keyBytes, (byte)0);
}
this.keyBytes = newKeyBytes;
nonce = newNonce;
@ -612,6 +616,9 @@ abstract class ChaCha20Cipher extends CipherSpi {
}
byte[] encodedKey = key.getEncoded();
if (encodedKey == null || encodedKey.length != 32) {
if (encodedKey != null) {
Arrays.fill(encodedKey, (byte)0);
}
throw new InvalidKeyException("Key length must be 256 bits");
}
return encodedKey;
@ -790,6 +797,7 @@ abstract class ChaCha20Cipher extends CipherSpi {
@Override
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encodedKey = getEncodedKey(key);
Arrays.fill(encodedKey, (byte)0);
return encodedKey.length << 3;
}

View file

@ -504,97 +504,106 @@ final class CipherCore {
|| (opmode == Cipher.UNWRAP_MODE);
byte[] keyBytes = getKeyBytes(key);
int tagLen = -1;
byte[] ivBytes = null;
if (params != null) {
if (cipherMode == GCM_MODE) {
if (params instanceof GCMParameterSpec) {
tagLen = ((GCMParameterSpec)params).getTLen();
if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
try {
int tagLen = -1;
byte[] ivBytes = null;
if (params != null) {
if (cipherMode == GCM_MODE) {
if (params instanceof GCMParameterSpec) {
tagLen = ((GCMParameterSpec) params).getTLen();
if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
throw new InvalidAlgorithmParameterException
("Unsupported TLen value; must be one of " +
"{128, 120, 112, 104, 96}");
}
tagLen = tagLen >> 3;
ivBytes = ((GCMParameterSpec) params).getIV();
} else {
throw new InvalidAlgorithmParameterException
("Unsupported TLen value; must be one of " +
"{128, 120, 112, 104, 96}");
}
tagLen = tagLen >> 3;
ivBytes = ((GCMParameterSpec)params).getIV();
} else {
throw new InvalidAlgorithmParameterException
("Unsupported parameter: " + params);
}
} else {
if (params instanceof IvParameterSpec) {
ivBytes = ((IvParameterSpec)params).getIV();
if ((ivBytes == null) || (ivBytes.length != blockSize)) {
throw new InvalidAlgorithmParameterException
("Wrong IV length: must be " + blockSize +
" bytes long");
}
} else if (params instanceof RC2ParameterSpec) {
ivBytes = ((RC2ParameterSpec)params).getIV();
if ((ivBytes != null) && (ivBytes.length != blockSize)) {
throw new InvalidAlgorithmParameterException
("Wrong IV length: must be " + blockSize +
" bytes long");
("Unsupported parameter: " + params);
}
} else {
throw new InvalidAlgorithmParameterException
("Unsupported parameter: " + params);
if (params instanceof IvParameterSpec) {
ivBytes = ((IvParameterSpec) params).getIV();
if ((ivBytes == null) || (ivBytes.length != blockSize)) {
throw new InvalidAlgorithmParameterException
("Wrong IV length: must be " + blockSize +
" bytes long");
}
} else if (params instanceof RC2ParameterSpec) {
ivBytes = ((RC2ParameterSpec) params).getIV();
if ((ivBytes != null) && (ivBytes.length != blockSize)) {
throw new InvalidAlgorithmParameterException
("Wrong IV length: must be " + blockSize +
" bytes long");
}
} else {
throw new InvalidAlgorithmParameterException
("Unsupported parameter: " + params);
}
}
}
}
if (cipherMode == ECB_MODE) {
if (ivBytes != null) {
throw new InvalidAlgorithmParameterException
("ECB mode cannot use IV");
}
} else if (ivBytes == null) {
if (decrypting) {
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
if (cipherMode == ECB_MODE) {
if (ivBytes != null) {
throw new InvalidAlgorithmParameterException
("ECB mode cannot use IV");
}
} else if (ivBytes == null) {
if (decrypting) {
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
}
if (random == null) {
random = SunJCE.getRandom();
}
if (cipherMode == GCM_MODE) {
ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
} else {
ivBytes = new byte[blockSize];
}
random.nextBytes(ivBytes);
}
if (random == null) {
random = SunJCE.getRandom();
}
buffered = 0;
diffBlocksize = blockSize;
String algorithm = key.getAlgorithm();
// GCM mode needs additional handling
if (cipherMode == GCM_MODE) {
ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
} else {
ivBytes = new byte[blockSize];
}
random.nextBytes(ivBytes);
}
buffered = 0;
diffBlocksize = blockSize;
String algorithm = key.getAlgorithm();
// GCM mode needs additional handling
if (cipherMode == GCM_MODE) {
if(tagLen == -1) {
tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
}
if (decrypting) {
minBytes = tagLen;
} else {
// check key+iv for encryption in GCM mode
requireReinit =
Arrays.equals(ivBytes, lastEncIv) &&
MessageDigest.isEqual(keyBytes, lastEncKey);
if (requireReinit) {
throw new InvalidAlgorithmParameterException
("Cannot reuse iv for GCM encryption");
if (tagLen == -1) {
tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
}
lastEncIv = ivBytes;
lastEncKey = keyBytes;
if (decrypting) {
minBytes = tagLen;
} else {
// check key+iv for encryption in GCM mode
requireReinit =
Arrays.equals(ivBytes, lastEncIv) &&
MessageDigest.isEqual(keyBytes, lastEncKey);
if (requireReinit) {
throw new InvalidAlgorithmParameterException
("Cannot reuse iv for GCM encryption");
}
lastEncIv = ivBytes;
if (lastEncKey != null) {
Arrays.fill(lastEncKey, (byte) 0);
}
lastEncKey = keyBytes;
}
((GaloisCounterMode) cipher).init
(decrypting, algorithm, keyBytes, ivBytes, tagLen);
} else {
cipher.init(decrypting, algorithm, keyBytes, ivBytes);
}
// skip checking key+iv from now on until after doFinal()
requireReinit = false;
} finally {
if (lastEncKey != keyBytes) {
Arrays.fill(keyBytes, (byte) 0);
}
((GaloisCounterMode) cipher).init
(decrypting, algorithm, keyBytes, ivBytes, tagLen);
} else {
cipher.init(decrypting, algorithm, keyBytes, ivBytes);
}
// skip checking key+iv from now on until after doFinal()
requireReinit = false;
}
void init(int opmode, Key key, AlgorithmParameters params,
@ -1156,7 +1165,11 @@ final class CipherCore {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
}
result = doFinal(encodedKey, 0, encodedKey.length);
try {
result = doFinal(encodedKey, 0, encodedKey.length);
} finally {
Arrays.fill(encodedKey, (byte)0);
}
} catch (BadPaddingException e) {
// Should never happen
}
@ -1197,8 +1210,12 @@ final class CipherCore {
throw new InvalidKeyException("The wrapped key does not have " +
"the correct length");
}
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
wrappedKeyType);
try {
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
wrappedKeyType);
} finally {
Arrays.fill(encodedKey, (byte)0);
}
}
/**

View file

@ -1,259 +0,0 @@
/*
* Copyright (c) 1999, 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.crypto.provider;
import java.security.Key;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.KeyFactory;
import java.security.InvalidKeyException;
import java.security.NoSuchProviderException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
import javax.crypto.SecretKey;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
import javax.crypto.spec.SecretKeySpec;
/**
* This class entends the javax.crypto.CipherSpi class with a concrete
* implementation of the methods for wrapping and unwrapping
* keys.
*
* @author Sharon Liu
*
*
* @see javax.crypto.CipherSpi
* @see BlowfishCipher
* @see DESCipher
* @see PBEWithMD5AndDESCipher
*/
public abstract class CipherWithWrappingSpi extends CipherSpi {
/**
* Wrap a key.
*
* @param key the key to be wrapped.
*
* @return the wrapped key.
*
* @exception IllegalBlockSizeException if this cipher is a block
* cipher, no padding has been requested, and the length of the
* encoding of the key to be wrapped is not a
* multiple of the block size.
*
* @exception InvalidKeyException if it is impossible or unsafe to
* wrap the key with this cipher (e.g., a hardware protected key is
* being passed to a software only cipher).
*/
protected final byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException
{
byte[] result = null;
try {
byte[] encodedKey = key.getEncoded();
if ((encodedKey == null) || (encodedKey.length == 0)) {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
}
result = engineDoFinal(encodedKey, 0, encodedKey.length);
} catch (BadPaddingException e) {
// Should never happen
}
return result;
}
/**
* Unwrap a previously wrapped key.
*
* @param wrappedKey the key to be unwrapped.
*
* @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
*
* @param wrappedKeyType the type of the wrapped key.
* This is one of <code>Cipher.SECRET_KEY</code>,
* <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
*
* @return the unwrapped key.
*
* @exception InvalidKeyException if <code>wrappedKey</code> does not
* represent a wrapped key, or if the algorithm associated with the
* wrapped key is different from <code>wrappedKeyAlgorithm</code>
* and/or its key type is different from <code>wrappedKeyType</code>.
*
* @exception NoSuchAlgorithmException if no installed providers
* can create keys for the <code>wrappedKeyAlgorithm</code>.
*/
protected final Key engineUnwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException
{
byte[] encodedKey;
Key result = null;
try {
encodedKey = engineDoFinal(wrappedKey, 0,
wrappedKey.length);
} catch (BadPaddingException ePadding) {
throw new InvalidKeyException();
} catch (IllegalBlockSizeException eBlockSize) {
throw new InvalidKeyException();
}
switch (wrappedKeyType) {
case Cipher.SECRET_KEY:
result = constructSecretKey(encodedKey,
wrappedKeyAlgorithm);
break;
case Cipher.PRIVATE_KEY:
result = constructPrivateKey(encodedKey,
wrappedKeyAlgorithm);
break;
case Cipher.PUBLIC_KEY:
result = constructPublicKey(encodedKey,
wrappedKeyAlgorithm);
break;
}
return result;
}
/**
* Construct a public key from its encoding.
*
* @param encodedKey the encoding of a public key.
*
* @param encodedKeyAlgorithm the algorithm the encodedKey is for.
*
* @return a public key constructed from the encodedKey.
*/
private final PublicKey constructPublicKey(byte[] encodedKey,
String encodedKeyAlgorithm)
throws InvalidKeyException, NoSuchAlgorithmException
{
PublicKey key = null;
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm,
SunJCE.getInstance());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
key = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException nsae) {
// Try to see whether there is another
// provider which supports this algorithm
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm);
X509EncodedKeySpec keySpec =
new X509EncodedKeySpec(encodedKey);
key = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException nsae2) {
throw new NoSuchAlgorithmException("No installed providers " +
"can create keys for the " +
encodedKeyAlgorithm +
"algorithm");
} catch (InvalidKeySpecException ikse2) {
// Should never happen.
}
} catch (InvalidKeySpecException ikse) {
// Should never happen.
}
return key;
}
/**
* Construct a private key from its encoding.
*
* @param encodedKey the encoding of a private key.
*
* @param encodedKeyAlgorithm the algorithm the wrapped key is for.
*
* @return a private key constructed from the encodedKey.
*/
private final PrivateKey constructPrivateKey(byte[] encodedKey,
String encodedKeyAlgorithm)
throws InvalidKeyException, NoSuchAlgorithmException
{
PrivateKey key = null;
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm,
SunJCE.getInstance());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
return keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException nsae) {
// Try to see whether there is another
// provider which supports this algorithm
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm);
PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKeySpec(encodedKey);
key = keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException nsae2) {
throw new NoSuchAlgorithmException("No installed providers " +
"can create keys for the " +
encodedKeyAlgorithm +
"algorithm");
} catch (InvalidKeySpecException ikse2) {
// Should never happen.
}
} catch (InvalidKeySpecException ikse) {
// Should never happen.
}
return key;
}
/**
* Construct a secret key from its encoding.
*
* @param encodedKey the encoding of a secret key.
*
* @param encodedKeyAlgorithm the algorithm the secret key is for.
*
* @return a secret key constructed from the encodedKey.
*/
private final SecretKey constructSecretKey(byte[] encodedKey,
String encodedKeyAlgorithm)
{
return (new SecretKeySpec(encodedKey, encodedKeyAlgorithm));
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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,8 @@
package com.sun.crypto.provider;
import jdk.internal.access.SharedSecrets;
import java.security.Key;
import java.security.PublicKey;
import java.security.PrivateKey;
@ -113,12 +115,11 @@ final class ConstructKeys {
throws InvalidKeyException, NoSuchAlgorithmException
{
PrivateKey key = null;
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm,
SunJCE.getInstance());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
return keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException nsae) {
// Try to see whether there is another
@ -126,8 +127,6 @@ final class ConstructKeys {
try {
KeyFactory keyFactory =
KeyFactory.getInstance(encodedKeyAlgorithm);
PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKeySpec(encodedKey);
key = keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException nsae2) {
throw new NoSuchAlgorithmException("No installed providers " +
@ -145,6 +144,8 @@ final class ConstructKeys {
new InvalidKeyException("Cannot construct private key");
ike.initCause(ikse);
throw ike;
} finally {
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(keySpec);
}
return key;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.BadPaddingException;
@ -369,6 +370,7 @@ public final class DESCipher extends CipherSpi {
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
Arrays.fill(encoded, (byte)0);
if (encoded.length != 8) {
throw new InvalidKeyException("Invalid key length: " +
encoded.length + " bytes");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -158,6 +158,6 @@ final class DESKey implements SecretKey {
return new KeyRep(KeyRep.Type.SECRET,
getAlgorithm(),
getFormat(),
getEncoded());
key);
}
}

View file

@ -31,6 +31,7 @@ import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.spec.SecretKeySpec;
/**
@ -63,17 +64,20 @@ public final class DESKeyFactory extends SecretKeyFactorySpi {
throws InvalidKeySpecException {
try {
byte[] encoded;
if (keySpec instanceof DESKeySpec) {
return new DESKey(((DESKeySpec)keySpec).getKey());
encoded = ((DESKeySpec)keySpec).getKey();
} else if (keySpec instanceof SecretKeySpec) {
encoded = ((SecretKeySpec)keySpec).getEncoded();
} else {
throw new InvalidKeySpecException(
"Inappropriate key specification");
}
if (keySpec instanceof SecretKeySpec) {
return new DESKey(((SecretKeySpec)keySpec).getEncoded());
try {
return new DESKey(encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
throw new InvalidKeySpecException(
"Inappropriate key specification");
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException(e.getMessage());
}
@ -106,9 +110,15 @@ public final class DESKeyFactory extends SecretKeyFactorySpi {
// Check if requested key spec is amongst the valid ones
if ((keySpec != null) &&
keySpec.isAssignableFrom(DESKeySpec.class)) {
return new DESKeySpec(key.getEncoded());
keySpec.isAssignableFrom(DESKeySpec.class)) {
byte[] encoded = key.getEncoded();
try {
return new DESKeySpec(encoded);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -30,6 +30,7 @@ import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.DESKeySpec;
@ -112,6 +113,7 @@ public final class DESKeyGenerator extends KeyGeneratorSpi {
setParityBit(key, 0);
} while (DESKeySpec.isWeak(key, 0));
desKey = new DESKey(key);
Arrays.fill(key, (byte)0);
} catch (InvalidKeyException e) {
// this is never thrown
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -366,6 +367,7 @@ public final class DESedeCipher extends CipherSpi {
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
Arrays.fill(encoded, (byte)0);
if (encoded.length != 24) {
throw new InvalidKeyException("Invalid key length: " +
encoded.length + " bytes");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -156,8 +156,8 @@ final class DESedeKey implements SecretKey {
@java.io.Serial
private Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.SECRET,
getAlgorithm(),
getFormat(),
getEncoded());
getAlgorithm(),
getFormat(),
key);
}
}

View file

@ -31,6 +31,7 @@ import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.spec.SecretKeySpec;
/**
@ -63,15 +64,20 @@ public final class DESedeKeyFactory extends SecretKeyFactorySpi {
throws InvalidKeySpecException {
try {
byte[] encoded;
if (keySpec instanceof DESedeKeySpec) {
return new DESedeKey(((DESedeKeySpec)keySpec).getKey());
encoded = ((DESedeKeySpec)keySpec).getKey();
} else if (keySpec instanceof SecretKeySpec) {
encoded = ((SecretKeySpec)keySpec).getEncoded();
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");
}
if (keySpec instanceof SecretKeySpec) {
return new DESedeKey(((SecretKeySpec)keySpec).getEncoded());
try {
return new DESedeKey(encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
throw new InvalidKeySpecException
("Inappropriate key specification");
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException(e.getMessage());
}
@ -103,8 +109,14 @@ public final class DESedeKeyFactory extends SecretKeyFactorySpi {
// Check if requested key spec is amongst the valid ones
if (keySpec.isAssignableFrom(DESedeKeySpec.class)) {
return new DESedeKeySpec(key.getEncoded());
byte[] encoded = key.getEncoded();
try {
return new DESedeKeySpec(encoded);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -241,8 +242,14 @@ public final class DESedeWrapCipher extends CipherSpi {
throw new UnsupportedOperationException("This cipher can " +
"only be used for key wrapping and unwrapping");
}
cipher.init(decrypting, key.getAlgorithm(), key.getEncoded(),
currIv);
byte[] encoded = key.getEncoded();
try {
cipher.init(decrypting, key.getAlgorithm(), encoded, currIv);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
cipherKey = key;
}
@ -416,6 +423,7 @@ public final class DESedeWrapCipher extends CipherSpi {
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encoded = key.getEncoded();
Arrays.fill(encoded, (byte)0);
if (encoded.length != 24) {
throw new InvalidKeyException("Invalid key length: " +
encoded.length + " bytes");
@ -448,47 +456,57 @@ public final class DESedeWrapCipher extends CipherSpi {
"the key to be wrapped");
}
byte[] cks = getChecksum(keyVal);
byte[] in = new byte[Math.addExact(keyVal.length, CHECKSUM_LEN)];
System.arraycopy(keyVal, 0, in, 0, keyVal.length);
System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN);
byte[] cipherKeyEncoded = cipherKey.getEncoded();
byte[] out = new byte[Math.addExact(iv.length, in.length)];
System.arraycopy(iv, 0, out, 0, iv.length);
cipher.encrypt(in, 0, in.length, out, iv.length);
// reverse the array content
for (int i = 0; i < out.length/2; i++) {
byte temp = out[i];
out[i] = out[out.length-1-i];
out[out.length-1-i] = temp;
}
try {
cipher.init(false, cipherKey.getAlgorithm(),
cipherKey.getEncoded(), IV2);
} catch (InvalidKeyException ike) {
// should never happen
throw new RuntimeException("Internal cipher key is corrupted");
} catch (InvalidAlgorithmParameterException iape) {
// should never happen
throw new RuntimeException("Internal cipher IV is invalid");
}
byte[] out2 = new byte[out.length];
cipher.encrypt(out, 0, out.length, out2, 0);
byte[] cks = getChecksum(keyVal);
System.arraycopy(keyVal, 0, in, 0, keyVal.length);
System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN);
// restore cipher state to prior to this call
try {
cipher.init(decrypting, cipherKey.getAlgorithm(),
cipherKey.getEncoded(), iv);
} catch (InvalidKeyException ike) {
// should never happen
throw new RuntimeException("Internal cipher key is corrupted");
} catch (InvalidAlgorithmParameterException iape) {
// should never happen
throw new RuntimeException("Internal cipher IV is invalid");
System.arraycopy(iv, 0, out, 0, iv.length);
cipher.encrypt(in, 0, in.length, out, iv.length);
// reverse the array content
for (int i = 0; i < out.length / 2; i++) {
byte temp = out[i];
out[i] = out[out.length - 1 - i];
out[out.length - 1 - i] = temp;
}
try {
cipher.init(false, cipherKey.getAlgorithm(),
cipherKeyEncoded, IV2);
} catch (InvalidKeyException ike) {
// should never happen
throw new RuntimeException("Internal cipher key is corrupted");
} catch (InvalidAlgorithmParameterException iape) {
// should never happen
throw new RuntimeException("Internal cipher IV is invalid");
}
byte[] out2 = new byte[out.length];
cipher.encrypt(out, 0, out.length, out2, 0);
// restore cipher state to prior to this call
try {
cipher.init(decrypting, cipherKey.getAlgorithm(),
cipherKeyEncoded, iv);
} catch (InvalidKeyException ike) {
// should never happen
throw new RuntimeException("Internal cipher key is corrupted");
} catch (InvalidAlgorithmParameterException iape) {
// should never happen
throw new RuntimeException("Internal cipher IV is invalid");
}
return out2;
} finally {
Arrays.fill(keyVal, (byte)0);
Arrays.fill(in, (byte)0);
Arrays.fill(out, (byte)0);
if (cipherKeyEncoded != null) {
Arrays.fill(cipherKeyEncoded, (byte) 0);
}
}
return out2;
}
/**
@ -530,34 +548,46 @@ public final class DESedeWrapCipher extends CipherSpi {
}
iv = new byte[IV_LEN];
System.arraycopy(buffer, 0, iv, 0, iv.length);
try {
cipher.init(true, cipherKey.getAlgorithm(), cipherKey.getEncoded(),
iv);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException("IV in wrapped key is invalid");
}
byte[] cipherKeyEncoded = cipherKey.getEncoded();
byte[] out = null;
byte[] buffer2 = new byte[buffer.length - iv.length];
cipher.decrypt(buffer, iv.length, buffer2.length,
buffer2, 0);
int keyValLen = buffer2.length - CHECKSUM_LEN;
byte[] cks = getChecksum(buffer2, 0, keyValLen);
int offset = keyValLen;
for (int i = 0; i < CHECKSUM_LEN; i++) {
if (buffer2[offset + i] != cks[i]) {
throw new InvalidKeyException("Checksum comparison failed");
}
}
// restore cipher state to prior to this call
try {
cipher.init(decrypting, cipherKey.getAlgorithm(),
cipherKey.getEncoded(), IV2);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException("IV in wrapped key is invalid");
try {
cipher.init(true, cipherKey.getAlgorithm(), cipherKeyEncoded,
iv);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException("IV in wrapped key is invalid");
}
cipher.decrypt(buffer, iv.length, buffer2.length,
buffer2, 0);
int keyValLen = buffer2.length - CHECKSUM_LEN;
byte[] cks = getChecksum(buffer2, 0, keyValLen);
int offset = keyValLen;
for (int i = 0; i < CHECKSUM_LEN; i++) {
if (buffer2[offset + i] != cks[i]) {
throw new InvalidKeyException("Checksum comparison failed");
}
}
// restore cipher state to prior to this call
try {
cipher.init(decrypting, cipherKey.getAlgorithm(),
cipherKeyEncoded, IV2);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException("IV in wrapped key is invalid");
}
out = new byte[keyValLen];
System.arraycopy(buffer2, 0, out, 0, keyValLen);
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
wrappedKeyType);
} finally {
if (out != null) {
Arrays.fill(out, (byte)0);
}
if (cipherKeyEncoded != null) {
Arrays.fill(cipherKeyEncoded, (byte) 0);
}
Arrays.fill(buffer2, (byte)0);
}
byte[] out = new byte[keyValLen];
System.arraycopy(buffer2, 0, out, 0, keyValLen);
return ConstructKeys.constructKey(out, wrappedKeyAlgorithm,
wrappedKeyType);
}
private static final byte[] getChecksum(byte[] in) {
@ -573,6 +603,7 @@ public final class DESedeWrapCipher extends CipherSpi {
md.update(in, offset, len);
byte[] cks = new byte[CHECKSUM_LEN];
System.arraycopy(md.digest(), 0, cks, 0, cks.length);
md.reset();
return cks;
}
}

View file

@ -34,6 +34,7 @@ import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.spec.DHPublicKeySpec;
import javax.crypto.spec.DHPrivateKeySpec;
import javax.crypto.spec.DHParameterSpec;
@ -99,8 +100,7 @@ public final class DHKeyFactory extends KeyFactorySpi {
* is inappropriate for this key factory to produce a private key.
*/
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException
{
throws InvalidKeySpecException {
try {
if (keySpec instanceof DHPrivateKeySpec) {
DHPrivateKeySpec dhPrivKeySpec = (DHPrivateKeySpec)keySpec;
@ -109,9 +109,12 @@ public final class DHKeyFactory extends KeyFactorySpi {
dhPrivKeySpec.getG());
} else if (keySpec instanceof PKCS8EncodedKeySpec) {
return new DHPrivateKey
(((PKCS8EncodedKeySpec)keySpec).getEncoded());
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
try {
return new DHPrivateKey(encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");
@ -172,8 +175,12 @@ public final class DHKeyFactory extends KeyFactorySpi {
params.getG()));
} else if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)) {
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
byte[] encoded = key.getEncoded();
try {
return keySpec.cast(new PKCS8EncodedKeySpec(encoded));
} finally {
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -26,6 +26,7 @@
package com.sun.crypto.provider;
import java.io.*;
import java.util.Arrays;
import java.util.Objects;
import java.math.BigInteger;
import java.security.KeyRep;
@ -46,7 +47,7 @@ import sun.security.util.*;
* @see java.security.KeyAgreement
*/
final class DHPrivateKey implements PrivateKey,
javax.crypto.interfaces.DHPrivateKey, Serializable {
javax.crypto.interfaces.DHPrivateKey, Serializable {
@java.io.Serial
static final long serialVersionUID = 7565477590005668886L;
@ -105,9 +106,12 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
this.g = g;
this.l = l;
try {
this.key = new DerValue(DerValue.tag_Integer,
this.x.toByteArray()).toByteArray();
this.encodedKey = getEncoded();
byte[] xbytes = x.toByteArray();
DerValue val = new DerValue(DerValue.tag_Integer, xbytes);
this.key = val.toByteArray();
val.clear();
Arrays.fill(xbytes, (byte)0);
encode();
} catch (IOException e) {
throw new ProviderException("Cannot produce ASN.1 encoding", e);
}
@ -122,9 +126,9 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
* a Diffie-Hellman private key
*/
DHPrivateKey(byte[] encodedKey) throws InvalidKeyException {
InputStream inStream = new ByteArrayInputStream(encodedKey);
DerValue val = null;
try {
DerValue val = new DerValue(inStream);
val = new DerValue(encodedKey);
if (val.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException ("Key not a SEQUENCE");
}
@ -182,6 +186,10 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
this.encodedKey = encodedKey.clone();
} catch (IOException | NumberFormatException e) {
throw new InvalidKeyException("Error parsing key encoding", e);
} finally {
if (val != null) {
val.clear();
}
}
}
@ -203,6 +211,15 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
* Get the encoding of the key.
*/
public synchronized byte[] getEncoded() {
encode();
return encodedKey.clone();
}
/**
* Generate the encodedKey field if it has not been calculated.
* Could generate null.
*/
private void encode() {
if (this.encodedKey == null) {
try {
DerOutputStream tmp = new DerOutputStream();
@ -238,14 +255,13 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
tmp.putOctetString(this.key);
// make it a SEQUENCE
DerOutputStream derKey = new DerOutputStream();
derKey.write(DerValue.tag_Sequence, tmp);
this.encodedKey = derKey.toByteArray();
DerValue val = DerValue.wrap(DerValue.tag_Sequence, tmp);
this.encodedKey = val.toByteArray();
val.clear();
} catch (IOException e) {
return null;
throw new AssertionError(e);
}
}
return this.encodedKey.clone();
}
/**
@ -314,9 +330,10 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
*/
@java.io.Serial
private Object writeReplace() throws java.io.ObjectStreamException {
encode();
return new KeyRep(KeyRep.Type.PRIVATE,
getAlgorithm(),
getFormat(),
getEncoded());
getAlgorithm(),
getFormat(),
encodedKey);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@ -29,6 +29,7 @@ import java.security.SecureRandom;
import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@ -104,6 +105,10 @@ public final class HmacMD5KeyGenerator extends KeyGeneratorSpi {
byte[] keyBytes = new byte[this.keysize];
this.random.nextBytes(keyBytes);
return new SecretKeySpec(keyBytes, "HmacMD5");
try {
return new SecretKeySpec(keyBytes, "HmacMD5");
} finally {
Arrays.fill(keyBytes, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@ -29,6 +29,7 @@ import java.security.SecureRandom;
import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@ -103,7 +104,10 @@ public final class HmacSHA1KeyGenerator extends KeyGeneratorSpi {
byte[] keyBytes = new byte[this.keysize];
this.random.nextBytes(keyBytes);
return new SecretKeySpec(keyBytes, "HmacSHA1");
try {
return new SecretKeySpec(keyBytes, "HmacSHA1");
} finally {
Arrays.fill(keyBytes, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
@ -102,7 +103,11 @@ final class KeyGeneratorCore {
}
byte[] b = new byte[(keySize + 7) >> 3];
random.nextBytes(b);
return new SecretKeySpec(b, name);
try {
return new SecretKeySpec(b, name);
} finally {
Arrays.fill(b, (byte)0);
}
}
// nested static classes for the Hmac key generator

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, 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
@ -46,6 +46,7 @@ import javax.crypto.SealedObject;
import javax.crypto.spec.*;
import javax.security.auth.DestroyFailedException;
import jdk.internal.access.SharedSecrets;
import sun.security.x509.AlgorithmId;
import sun.security.util.ObjectIdentifier;
import sun.security.util.KnownOIDs;
@ -201,10 +202,17 @@ final class KeyProtector {
// determine the private-key algorithm, and parse private key
// using the appropriate key factory
PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(plain);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(plain);
String oidName = new AlgorithmId
(new PrivateKeyInfo(plain).getAlgorithm().getOID()).getName();
KeyFactory kFac = KeyFactory.getInstance(oidName);
return kFac.generatePrivate(new PKCS8EncodedKeySpec(plain));
(privateKeyInfo.getAlgorithm().getOID()).getName();
try {
KeyFactory kFac = KeyFactory.getInstance(oidName);
return kFac.generatePrivate(spec);
} finally {
privateKeyInfo.clear();
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(spec);
}
} catch (NoSuchAlgorithmException ex) {
// Note: this catch needed to be here because of the
// later catch of GeneralSecurityException

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -167,8 +167,8 @@ final class PBEKey implements SecretKey {
@java.io.Serial
private Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.SECRET,
getAlgorithm(),
getFormat(),
getEncoded());
getAlgorithm(),
getFormat(),
key);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -292,8 +292,12 @@ abstract class PBEKeyFactory extends SecretKeyFactorySpi {
PBEKeySpec pbeKeySpec = (PBEKeySpec)engineGetKeySpec
(key, PBEKeySpec.class);
// Create key from spec, and return it
return engineGenerateSecret(pbeKeySpec);
try {
// Create key from spec, and return it
return engineGenerateSecret(pbeKeySpec);
} finally {
pbeKeySpec.clearPassword();
}
} else {
throw new InvalidKeyException("Invalid key format/algorithm");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -537,9 +537,14 @@ final class PBES1Core {
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException {
byte[] encodedKey;
try {
encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
byte[] encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
try {
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
wrappedKeyType);
} finally {
Arrays.fill(encodedKey, (byte)0);
}
} catch (BadPaddingException ePadding) {
throw new InvalidKeyException("The wrapped key is not padded " +
"correctly");
@ -547,7 +552,5 @@ final class PBES1Core {
throw new InvalidKeyException("The wrapped key does not have " +
"the correct length");
}
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
wrappedKeyType);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, 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
@ -274,18 +274,20 @@ abstract class PBES2Core extends CipherSpi {
if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
}
SecretKey s = null;
PBKDF2KeyImpl s;
try {
s = kdf.engineGenerateSecret(pbeSpec);
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
} catch (InvalidKeySpecException ikse) {
InvalidKeyException ike =
new InvalidKeyException("Cannot construct PBE key");
ike.initCause(ikse);
throw ike;
} finally {
pbeSpec.clearPassword();
}
byte[] derivedKey = s.getEncoded();
s.clearPassword();
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
// initialize the underlying cipher

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -28,6 +28,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactorySpi;
import javax.crypto.spec.PBEKeySpec;
@ -94,9 +95,17 @@ abstract class PBKDF2Core extends SecretKeyFactorySpi {
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
char[] passwd = pKey.getPassword();
byte[] encoded = pKey.getEncoded();
try {
return new PBEKeySpec(passwd, pKey.getSalt(),
pKey.getIterationCount(), encoded.length * 8);
} finally {
if (passwd != null) {
Arrays.fill(passwd, (char) 0);
}
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
@ -132,18 +141,26 @@ abstract class PBKDF2Core extends SecretKeyFactorySpi {
if (key instanceof javax.crypto.interfaces.PBEKey) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
char[] password = pKey.getPassword();
byte[] encoding = pKey.getEncoded();
PBEKeySpec spec =
new PBEKeySpec(password,
pKey.getSalt(),
pKey.getIterationCount(),
encoding.length*8);
try {
PBEKeySpec spec =
new PBEKeySpec(pKey.getPassword(),
pKey.getSalt(),
pKey.getIterationCount(),
pKey.getEncoded().length*8);
return new PBKDF2KeyImpl(spec, prfAlgo);
} catch (InvalidKeySpecException re) {
InvalidKeyException ike = new InvalidKeyException
("Invalid key component(s)");
ike.initCause(re);
throw ike;
} finally {
if (password != null) {
Arrays.fill(password, (char) 0);
spec.clearPassword();
}
Arrays.fill(encoding, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -28,6 +28,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactorySpi;
import javax.crypto.spec.PBEKeySpec;
@ -94,9 +95,17 @@ public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi {
&& PBEKeySpec.class.isAssignableFrom(keySpecCl)) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
return new PBEKeySpec
(pKey.getPassword(), pKey.getSalt(),
pKey.getIterationCount(), pKey.getEncoded().length*8);
char[] passwd = pKey.getPassword();
byte[] encoded = pKey.getEncoded();
try {
return new PBEKeySpec(passwd, pKey.getSalt(),
pKey.getIterationCount(), encoded.length * 8);
} finally {
if (passwd != null) {
Arrays.fill(passwd, (char) 0);
}
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeySpecException("Invalid key spec");
}
@ -132,18 +141,26 @@ public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi {
if (key instanceof javax.crypto.interfaces.PBEKey) {
javax.crypto.interfaces.PBEKey pKey =
(javax.crypto.interfaces.PBEKey) key;
char[] password = pKey.getPassword();
byte[] encoding = pKey.getEncoded();
PBEKeySpec spec =
new PBEKeySpec(password,
pKey.getSalt(),
pKey.getIterationCount(),
encoding.length*8);
try {
PBEKeySpec spec =
new PBEKeySpec(pKey.getPassword(),
pKey.getSalt(),
pKey.getIterationCount(),
pKey.getEncoded().length*8);
return new PBKDF2KeyImpl(spec, "HmacSHA1");
} catch (InvalidKeySpecException re) {
InvalidKeyException ike = new InvalidKeyException
("Invalid key component(s)");
ike.initCause(re);
throw ike;
} finally {
if (password != null) {
Arrays.fill(password, (char) 0);
spec.clearPassword();
}
Arrays.fill(encoding, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -73,6 +73,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
int len = bb.limit();
byte[] passwdBytes = new byte[len];
bb.get(passwdBytes, 0, len);
bb.clear().put(new byte[len]);
return passwdBytes;
}
@ -159,7 +160,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
}
@Override
public byte[] getEncoded() {
return password;
return password.clone();
}
@Override
public int hashCode() {
@ -225,6 +226,10 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
return iterCount;
}
public void clearPassword() {
Arrays.fill(passwd, (char)0);
}
public char[] getPassword() {
// The password is zeroized by finalize()
// The reachability fence ensures finalize() isn't called early
@ -282,7 +287,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
*/
@java.io.Serial
private Object writeReplace() throws ObjectStreamException {
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
getFormat(), getEncoded());
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
getFormat(), key);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@ -174,18 +174,25 @@ abstract class PBMAC1Core extends HmacCore {
Arrays.fill(passwdChars, '\0');
}
SecretKey s;
PBKDF2KeyImpl s = null;
PBKDF2Core kdf = getKDFImpl(kdfAlgo);
byte[] derivedKey;
try {
s = kdf.engineGenerateSecret(pbeSpec);
s = (PBKDF2KeyImpl)kdf.engineGenerateSecret(pbeSpec);
derivedKey = s.getEncoded();
} catch (InvalidKeySpecException ikse) {
InvalidKeyException ike =
new InvalidKeyException("Cannot construct PBE key");
ike.initCause(ikse);
throw ike;
} finally {
pbeSpec.clearPassword();
if (s != null) {
s.clearPassword();
}
}
byte[] derivedKey = s.getEncoded();
SecretKey cipherKey = new SecretKeySpec(derivedKey, kdfAlgo);
Arrays.fill(derivedKey, (byte)0);
super.engineInit(cipherKey, null);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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,12 +25,12 @@
package com.sun.crypto.provider;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.security.auth.DestroyFailedException;
/**
* This class implements password-base encryption algorithm with
@ -108,7 +108,6 @@ final class PKCS12PBECipherCore {
byte[] Ai;
byte[] B = new byte[v];
byte[] tmp = new byte[v];
int i = 0;
for (; ; i++, n -= u) {
@ -118,37 +117,45 @@ final class PKCS12PBECipherCore {
for (int r = 1; r < ic; r++)
Ai = sha.digest(Ai);
System.arraycopy(Ai, 0, key, u * i, Math.min(n, u));
if (i + 1 == c)
if (i + 1 == c) {
break;
concat(Ai, B, 0, B.length);
BigInteger B1;
B1 = new BigInteger(1, B).add(BigInteger.ONE);
}
concat(Ai, B, 0, v);
addOne(v, B); // add 1 into B
for (int j = 0; j < I.length; j += v) {
BigInteger Ij;
int trunc;
if (tmp.length != v)
tmp = new byte[v];
System.arraycopy(I, j, tmp, 0, v);
Ij = new BigInteger(1, tmp);
Ij = Ij.add(B1);
tmp = Ij.toByteArray();
trunc = tmp.length - v;
if (trunc >= 0) {
System.arraycopy(tmp, trunc, I, j, v);
} else if (trunc < 0) {
Arrays.fill(I, j, j + (-trunc), (byte)0);
System.arraycopy(tmp, 0, I, j + (-trunc), tmp.length);
}
addTwo(v, B, I, j); // add B into I from j
}
}
Arrays.fill(I, (byte)0);
} catch (Exception e) {
throw new RuntimeException("internal error: " + e);
}
return key;
}
// Add 1 to b (as integer)
private static void addOne(int len, byte[] b) {
for (int i = len - 1; i >= 0; i--) {
if ((b[i] & 0xff) != 255) {
b[i]++;
break;
} else {
b[i] = 0;
}
}
}
// Add src (as integer) to dst from offset (as integer)
private static void addTwo(int len, byte[] src, byte[] dst, int offset) {
int carry = 0;
for (int i = len - 1; i >= 0; i--) {
int sum = (src[i] & 0xff) + (dst[i + offset] & 0xff) + carry;
carry = sum >> 8;
dst[i + offset] = (byte)sum;
}
}
private static int roundup(int x, int y) {
return ((x + (y - 1)) / y) * y;
}
@ -341,17 +348,26 @@ final class PKCS12PBECipherCore {
byte[] derivedKey = derive(passwdChars, salt, iCount,
keySize, CIPHER_KEY);
SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
Arrays.fill(derivedKey, (byte)0);
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
try {
if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
((ARCFOURCipher) cipherImpl).engineInit(opmode, cipherKey, random);
} else {
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
CIPHER_IV);
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
} else {
byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
CIPHER_IV);
IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
}
} finally {
try {
cipherKey.destroy();
} catch (DestroyFailedException e) {
// Ignore the failure
}
}
} finally {
Arrays.fill(passwdChars, '\0');

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, 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
@ -27,6 +27,8 @@ package com.sun.crypto.provider;
import java.math.*;
import java.io.*;
import java.util.Arrays;
import sun.security.x509.AlgorithmId;
import sun.security.util.*;
@ -62,23 +64,27 @@ final class PrivateKeyInfo {
PrivateKeyInfo(byte[] encoded) throws IOException {
DerValue val = new DerValue(encoded);
if (val.tag != DerValue.tag_Sequence)
throw new IOException("private key parse error: not a sequence");
try {
if (val.tag != DerValue.tag_Sequence)
throw new IOException("private key parse error: not a sequence");
// version
BigInteger parsedVersion = val.data.getBigInteger();
if (!parsedVersion.equals(VERSION)) {
throw new IOException("version mismatch: (supported: " +
VERSION + ", parsed: " + parsedVersion);
// version
BigInteger parsedVersion = val.data.getBigInteger();
if (!parsedVersion.equals(VERSION)) {
throw new IOException("version mismatch: (supported: " +
VERSION + ", parsed: " + parsedVersion);
}
// privateKeyAlgorithm
this.algid = AlgorithmId.parse(val.data.getDerValue());
// privateKey
this.privkey = val.data.getOctetString();
// OPTIONAL attributes not supported yet
} finally {
val.clear();
}
// privateKeyAlgorithm
this.algid = AlgorithmId.parse(val.data.getDerValue());
// privateKey
this.privkey = val.data.getOctetString();
// OPTIONAL attributes not supported yet
}
/**
@ -87,4 +93,8 @@ final class PrivateKeyInfo {
AlgorithmId getAlgorithm() {
return this.algid;
}
public void clear() {
Arrays.fill(privkey, (byte)0);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.RC2ParameterSpec;
@ -133,6 +134,7 @@ public final class RC2Cipher extends CipherSpi {
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] keyBytes = CipherCore.getKeyBytes(key);
Arrays.fill(keyBytes, (byte)0);
RC2Crypt.checkKey(key.getAlgorithm(), keyBytes.length);
return keyBytes.length << 3;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -86,16 +87,18 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
throw new IllegalStateException(
"TlsKeyMaterialGenerator must be initialized");
}
byte[] masterSecret = spec.getMasterSecret().getEncoded();
try {
return engineGenerateKey0();
return engineGenerateKey0(masterSecret);
} catch (GeneralSecurityException e) {
throw new ProviderException(e);
} finally {
Arrays.fill(masterSecret, (byte)0);
}
}
@SuppressWarnings("deprecation")
private SecretKey engineGenerateKey0() throws GeneralSecurityException {
byte[] masterSecret = spec.getMasterSecret().getEncoded();
private SecretKey engineGenerateKey0(byte[] masterSecret) throws GeneralSecurityException {
byte[] clientRandom = spec.getClientRandom();
byte[] serverRandom = spec.getServerRandom();
@ -116,7 +119,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
int keyBlockLen = macLength + keyLength
+ (isExportable ? 0 : ivLength);
keyBlockLen <<= 1;
byte[] keyBlock = new byte[keyBlockLen];
byte[] keyBlock;
// These may be used again later for exportable suite calculations.
MessageDigest md5 = null;
@ -169,16 +172,11 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
int ofs = 0;
if (macLength != 0) {
byte[] tmp = new byte[macLength];
// mac keys
System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
clientMacKey = new SecretKeySpec(keyBlock, ofs, macLength, "Mac");
ofs += macLength;
clientMacKey = new SecretKeySpec(tmp, "Mac");
System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
serverMacKey = new SecretKeySpec(keyBlock, ofs, macLength, "Mac");
ofs += macLength;
serverMacKey = new SecretKeySpec(tmp, "Mac");
}
if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites
@ -196,82 +194,89 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
System.arraycopy(keyBlock, ofs, serverKeyBytes, 0, keyLength);
ofs += keyLength;
if (isExportable == false) {
// cipher keys
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
// IV keys if needed.
if (ivLength != 0) {
byte[] tmp = new byte[ivLength];
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
ofs += ivLength;
clientIv = new IvParameterSpec(tmp);
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
ofs += ivLength;
serverIv = new IvParameterSpec(tmp);
}
} else {
// if exportable suites, calculate the alternate
// cipher key expansion and IV generation
if (protocolVersion >= 0x0302) {
// TLS 1.1+
throw new RuntimeException(
"Internal Error: TLS 1.1+ should not be negotiating" +
"exportable ciphersuites");
} else if (protocolVersion == 0x0301) {
// TLS 1.0
byte[] seed = concat(clientRandom, serverRandom);
byte[] tmp = doTLS10PRF(clientKeyBytes,
LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
expandedKeyLength, md5, sha);
serverCipherKey = new SecretKeySpec(tmp, alg);
try {
if (isExportable == false) {
// cipher keys
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
// IV keys if needed.
if (ivLength != 0) {
tmp = new byte[ivLength];
byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
ivLength << 1, md5, sha);
System.arraycopy(block, 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp);
System.arraycopy(block, ivLength, tmp, 0, ivLength);
serverIv = new IvParameterSpec(tmp);
clientIv = new IvParameterSpec(keyBlock, ofs, ivLength);
ofs += ivLength;
serverIv = new IvParameterSpec(keyBlock, ofs, ivLength);
ofs += ivLength;
}
} else {
// SSLv3
byte[] tmp = new byte[expandedKeyLength];
// if exportable suites, calculate the alternate
// cipher key expansion and IV generation
if (protocolVersion >= 0x0302) {
// TLS 1.1+
throw new RuntimeException(
"Internal Error: TLS 1.1+ should not be negotiating" +
"exportable ciphersuites");
} else if (protocolVersion == 0x0301) {
// TLS 1.0
byte[] seed = concat(clientRandom, serverRandom);
md5.update(clientKeyBytes);
md5.update(clientRandom);
md5.update(serverRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, expandedKeyLength);
clientCipherKey = new SecretKeySpec(tmp, alg);
byte[] tmp = doTLS10PRF(clientKeyBytes,
LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg);
Arrays.fill(tmp, (byte) 0);
md5.update(serverKeyBytes);
md5.update(serverRandom);
md5.update(clientRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, expandedKeyLength);
serverCipherKey = new SecretKeySpec(tmp, alg);
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
expandedKeyLength, md5, sha);
serverCipherKey = new SecretKeySpec(tmp, alg);
Arrays.fill(tmp, (byte) 0);
if (ivLength != 0) {
tmp = new byte[ivLength];
if (ivLength != 0) {
byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
ivLength << 1, md5, sha);
clientIv = new IvParameterSpec(block, 0, ivLength);
serverIv = new IvParameterSpec(block, ivLength, ivLength);
}
} else {
// SSLv3
byte[] tmp = new byte[expandedKeyLength];
byte[] digest;
md5.update(clientKeyBytes);
md5.update(clientRandom);
md5.update(serverRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp);
digest = md5.digest();
System.arraycopy(digest, 0, tmp, 0, expandedKeyLength);
clientCipherKey = new SecretKeySpec(tmp, alg);
Arrays.fill(digest, (byte) 0);
md5.update(serverKeyBytes);
md5.update(serverRandom);
md5.update(clientRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
serverIv = new IvParameterSpec(tmp);
digest = md5.digest();
System.arraycopy(digest, 0, tmp, 0, expandedKeyLength);
serverCipherKey = new SecretKeySpec(tmp, alg);
Arrays.fill(digest, (byte) 0);
Arrays.fill(tmp, (byte) 0);
if (ivLength != 0) {
tmp = new byte[ivLength];
md5.update(clientRandom);
md5.update(serverRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp);
md5.update(serverRandom);
md5.update(clientRandom);
System.arraycopy(md5.digest(), 0, tmp, 0, ivLength);
serverIv = new IvParameterSpec(tmp);
}
}
}
} finally {
Arrays.fill(serverKeyBytes, (byte) 0);
Arrays.fill(clientKeyBytes, (byte) 0);
Arrays.fill(keyBlock, (byte) 0);
}
return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.*;
@ -135,20 +136,26 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
sha.update(clientRandom);
sha.update(serverRandom);
sha.digest(tmp, 0, 20);
sha.reset();
md5.update(premaster);
md5.update(tmp);
md5.digest(master, i << 4, 16);
md5.reset();
}
}
// master is referenced inside the TlsMasterSecretKey.
// Do not touch it anymore.
return new TlsMasterSecretKey(master, premasterMajor,
premasterMinor);
} catch (NoSuchAlgorithmException e) {
throw new ProviderException(e);
} catch (DigestException e) {
throw new ProviderException(e);
} finally {
if (premaster != null) {
Arrays.fill(premaster, (byte)0);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -162,9 +162,17 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
spec.getPRFHashAlg(), spec.getPRFHashLength(),
spec.getPRFBlockSize()) :
doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
return new SecretKeySpec(prfBytes, "TlsPrf");
try {
return new SecretKeySpec(prfBytes, "TlsPrf");
} finally {
Arrays.fill(prfBytes, (byte)0);
}
} catch (GeneralSecurityException e) {
throw new ProviderException("Could not generate PRF", e);
} finally {
if (secret != null) {
Arrays.fill(secret, (byte) 0);
}
}
}
@ -257,6 +265,7 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
if (seclen > 64) { // 64: block size of HMAC-MD5
md5.update(secret, 0, seclen);
secKey = md5.digest();
md5.reset();
keyLen = secKey.length;
}
expand(md5, 16, secKey, 0, keyLen, labelBytes, seed, output,
@ -267,6 +276,7 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
if (seclen > 64) { // 64: block size of HMAC-SHA1
sha.update(secret, off, seclen);
secKey = sha.digest();
sha.reset();
keyLen = secKey.length;
off = 0;
}
@ -351,12 +361,15 @@ abstract class TlsPrfGenerator extends KeyGeneratorSpi {
digest.update(tmp);
digest.digest(tmp, 0, hmacSize);
digest.reset();
int k = Math.min(hmacSize, remaining);
for (int i = 0; i < k; i++) {
output[ofs++] ^= tmp[i];
}
remaining -= k;
}
Arrays.fill(tmp, (byte)0);
}
/**

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -27,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
@ -87,7 +88,11 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
b[0] = (byte)spec.getMajorVersion();
b[1] = (byte)spec.getMinorVersion();
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
try {
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
} finally {
Arrays.fill(b, (byte)0);
}
}
}