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);
}
}
}

View File

@ -688,7 +688,23 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* @see #bitLength()
*/
public BigInteger(int numBits, Random rnd) {
this(1, randomBits(numBits, rnd));
byte[] magnitude = randomBits(numBits, rnd);
try {
// stripLeadingZeroBytes() returns a zero length array if len == 0
this.mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
if (this.mag.length == 0) {
this.signum = 0;
} else {
this.signum = 1;
}
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} finally {
Arrays.fill(magnitude, (byte)0);
}
}
private static byte[] randomBits(int numBits, Random rnd) {

View File

@ -159,8 +159,14 @@ class MutableBigInteger {
* supposed to modify the returned array.
*/
private int[] getMagnitudeArray() {
if (offset > 0 || value.length != intLen)
return Arrays.copyOfRange(value, offset, offset + intLen);
if (offset > 0 || value.length != intLen) {
// Shrink value to be the total magnitude
int[] tmp = Arrays.copyOfRange(value, offset, offset + intLen);
Arrays.fill(value, 0);
offset = 0;
intLen = tmp.length;
value = tmp;
}
return value;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, 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
@ -25,6 +25,11 @@
package java.security.spec;
import jdk.internal.access.JavaSecuritySpecAccess;
import jdk.internal.access.SharedSecrets;
import java.util.Arrays;
/**
* This class represents a public or private key in encoded format.
*
@ -45,7 +50,17 @@ public abstract class EncodedKeySpec implements KeySpec {
private byte[] encodedKey;
private String algorithmName;
/**
static {
SharedSecrets.setJavaSecuritySpecAccess(
new JavaSecuritySpecAccess() {
@Override
public void clearEncodedKeySpec(EncodedKeySpec keySpec) {
keySpec.clear();
}
});
}
/**
* Creates a new {@code EncodedKeySpec} with the given encoded key.
*
* @param encodedKey the encoded key. The contents of the
@ -125,4 +140,11 @@ public abstract class EncodedKeySpec implements KeySpec {
* @return a string representation of the encoding format.
*/
public abstract String getFormat();
/**
* Clear the encoding inside.
*/
void clear() {
Arrays.fill(encodedKey, (byte)0);
}
}

View File

@ -34,6 +34,7 @@ import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Arrays;
/**
* This class enables a programmer to create an object and protect its
@ -171,10 +172,11 @@ public class SealedObject implements Serializable {
*/
try {
this.encryptedContent = c.doFinal(content);
}
catch (BadPaddingException ex) {
} catch (BadPaddingException ex) {
// if sealing is encryption only
// Should never happen??
} finally {
Arrays.fill(content, (byte)0);
}
// Save the parameters

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2020, 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
@ -25,8 +25,12 @@
package javax.crypto.spec;
import jdk.internal.access.JavaxCryptoSpecAccess;
import jdk.internal.access.SharedSecrets;
import java.security.MessageDigest;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Locale;
import javax.crypto.SecretKey;
@ -66,6 +70,16 @@ public class SecretKeySpec implements KeySpec, SecretKey {
*/
private String algorithm;
static {
SharedSecrets.setJavaxCryptoSpecAccess(
new JavaxCryptoSpecAccess() {
@Override
public void clearSecretKeySpec(SecretKeySpec keySpec) {
keySpec.clear();
}
});
}
/**
* Constructs a secret key from the given byte array.
*
@ -227,7 +241,19 @@ public class SecretKeySpec implements KeySpec, SecretKey {
}
byte[] thatKey = ((SecretKey)obj).getEncoded();
try {
return MessageDigest.isEqual(this.key, thatKey);
} finally {
if (thatKey != null) {
Arrays.fill(thatKey, (byte)0);
}
}
}
return MessageDigest.isEqual(this.key, thatKey);
/**
* Clear the key bytes inside.
*/
void clear() {
Arrays.fill(key, (byte)0);
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 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
* 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 jdk.internal.access;
import java.security.spec.EncodedKeySpec;
public interface JavaSecuritySpecAccess {
void clearEncodedKeySpec(EncodedKeySpec keySpec);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 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
* 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 jdk.internal.access;
import javax.crypto.spec.SecretKeySpec;
public interface JavaxCryptoSpecAccess {
void clearSecretKeySpec(SecretKeySpec keySpec);
}

View File

@ -26,9 +26,11 @@
package jdk.internal.access;
import javax.crypto.SealedObject;
import javax.crypto.spec.SecretKeySpec;
import java.io.ObjectInputFilter;
import java.lang.invoke.MethodHandles;
import java.lang.module.ModuleDescriptor;
import java.security.spec.EncodedKeySpec;
import java.util.ResourceBundle;
import java.util.jar.JarFile;
import java.io.Console;
@ -76,7 +78,9 @@ public class SharedSecrets {
private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
private static JavaSecurityAccess javaSecurityAccess;
private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
private static JavaSecuritySpecAccess javaSecuritySpecAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
private static JavaxCryptoSpecAccess javaxCryptoSpecAccess;
public static void setJavaUtilCollectionAccess(JavaUtilCollectionAccess juca) {
javaUtilCollectionAccess = juca;
@ -398,6 +402,28 @@ public class SharedSecrets {
return access;
}
public static void setJavaSecuritySpecAccess(JavaSecuritySpecAccess jssa) {
javaSecuritySpecAccess = jssa;
}
public static JavaSecuritySpecAccess getJavaSecuritySpecAccess() {
if (javaSecuritySpecAccess == null) {
ensureClassInitialized(EncodedKeySpec.class);
}
return javaSecuritySpecAccess;
}
public static void setJavaxCryptoSpecAccess(JavaxCryptoSpecAccess jcsa) {
javaxCryptoSpecAccess = jcsa;
}
public static JavaxCryptoSpecAccess getJavaxCryptoSpecAccess() {
if (javaxCryptoSpecAccess == null) {
ensureClassInitialized(SecretKeySpec.class);
}
return javaxCryptoSpecAccess;
}
public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) {
javaxCryptoSealedObjectAccess = jcsoa;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -37,6 +37,7 @@ import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import jdk.internal.access.SharedSecrets;
import sun.security.x509.*;
import sun.security.util.*;
@ -95,8 +96,9 @@ public class PKCS8Key implements PrivateKey {
}
private void decode(InputStream is) throws InvalidKeyException {
DerValue val = null;
try {
DerValue val = new DerValue(is);
val = new DerValue(is);
if (val.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("invalid key format");
}
@ -106,7 +108,7 @@ public class PKCS8Key implements PrivateKey {
throw new InvalidKeyException("unknown version: " + version);
}
algid = AlgorithmId.parse (val.data.getDerValue ());
key = val.data.getOctetString ();
key = val.data.getOctetString();
DerValue next;
if (val.data.available() == 0) {
@ -131,11 +133,15 @@ public class PKCS8Key implements PrivateKey {
throw new InvalidKeyException("Extra bytes");
} catch (IOException e) {
throw new InvalidKeyException("IOException : " + e.getMessage());
} finally {
if (val != null) {
val.clear();
}
}
}
/**
* Construct PKCS#8 subject public key from a DER value. If a
* Construct PKCS#8 subject public key from a DER encoding. If a
* security provider supports the key algorithm with a specific class,
* a PrivateKey from the provider is returned. Otherwise, a raw
* PKCS8Key object is returned.
@ -145,21 +151,29 @@ public class PKCS8Key implements PrivateKey {
* information. Also, when a key (or algorithm) needs some special
* handling, that specific need can be accommodated.
*
* @param in the DER-encoded SubjectPublicKeyInfo value
* @param encoded the DER-encoded SubjectPublicKeyInfo value
* @exception IOException on data format errors
*/
public static PrivateKey parseKey(DerValue in) throws IOException {
public static PrivateKey parseKey(byte[] encoded) throws IOException {
try {
PKCS8Key rawKey = new PKCS8Key(in.toByteArray());
PKCS8EncodedKeySpec pkcs8KeySpec
= new PKCS8EncodedKeySpec(rawKey.getEncoded());
PKCS8Key rawKey = new PKCS8Key(encoded);
byte[] internal = rawKey.getEncodedInternal();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(internal);
PrivateKey result = null;
try {
return KeyFactory.getInstance(rawKey.algid.getName())
result = KeyFactory.getInstance(rawKey.algid.getName())
.generatePrivate(pkcs8KeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
// Ignore and return raw key
return rawKey;
result = rawKey;
} finally {
if (result != rawKey) {
rawKey.clear();
}
SharedSecrets.getJavaSecuritySpecAccess()
.clearEncodedKeySpec(pkcs8KeySpec);
}
return result;
} catch (InvalidKeyException e) {
throw new IOException("corrupt private key", e);
}
@ -183,14 +197,9 @@ public class PKCS8Key implements PrivateKey {
* Returns the DER-encoded form of the key as a byte array,
* or {@code null} if an encoding error occurs.
*/
public synchronized byte[] getEncoded() {
try {
encode();
return encodedKey.clone();
} catch (InvalidKeyException e) {
// ignored and return null
}
return null;
public byte[] getEncoded() {
byte[] b = getEncodedInternal();
return (b == null) ? null : b.clone();
}
/**
@ -201,34 +210,34 @@ public class PKCS8Key implements PrivateKey {
}
/**
* DER-encodes this key as a byte array that can be retrieved
* by the {@link #getEncoded()} method.
* DER-encodes this key as a byte array stored inside this object
* and return it.
*
* @exception InvalidKeyException if an encoding error occurs.
* @return the encoding, or null if there is an I/O error.
*/
private void encode() throws InvalidKeyException {
private synchronized byte[] getEncodedInternal() {
if (encodedKey == null) {
try {
DerOutputStream out = new DerOutputStream ();
DerOutputStream tmp = new DerOutputStream();
tmp.putInteger(V1);
algid.encode(tmp);
tmp.putOctetString(key);
out.write(DerValue.tag_Sequence, tmp);
DerValue out = DerValue.wrap(DerValue.tag_Sequence, tmp);
encodedKey = out.toByteArray();
out.clear();
} catch (IOException e) {
throw new InvalidKeyException ("IOException : " +
e.getMessage());
// encodedKey is still null
}
}
return encodedKey;
}
@java.io.Serial
protected Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.PRIVATE,
getAlgorithm(),
getFormat(),
getEncoded());
getAlgorithm(),
getFormat(),
getEncodedInternal());
}
/**
@ -258,11 +267,23 @@ public class PKCS8Key implements PrivateKey {
if (this == object) {
return true;
}
if (object instanceof Key) {
if (object instanceof PKCS8Key) {
// time-constant comparison
return MessageDigest.isEqual(
getEncoded(),
((Key)object).getEncoded());
getEncodedInternal(),
((PKCS8Key)object).getEncodedInternal());
} else if (object instanceof Key) {
// time-constant comparison
byte[] otherEncoded = ((Key)object).getEncoded();
try {
return MessageDigest.isEqual(
getEncodedInternal(),
otherEncoded);
} finally {
if (otherEncoded != null) {
Arrays.fill(otherEncoded, (byte) 0);
}
}
}
return false;
}
@ -272,6 +293,13 @@ public class PKCS8Key implements PrivateKey {
* which are equal will also have the same hashcode.
*/
public int hashCode() {
return Arrays.hashCode(getEncoded());
return Arrays.hashCode(getEncodedInternal());
}
public void clear() {
if (encodedKey != null) {
Arrays.fill(encodedKey, (byte)0);
}
Arrays.fill(key, (byte)0);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2020, 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
@ -65,6 +65,7 @@ import javax.crypto.Mac;
import javax.security.auth.DestroyFailedException;
import javax.security.auth.x500.X500Principal;
import jdk.internal.access.SharedSecrets;
import sun.security.action.GetPropertyAction;
import sun.security.tools.KeyStoreUtil;
import sun.security.util.*;
@ -359,63 +360,87 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
key = RetryWithZero.run(pass -> {
// Use JCE
SecretKey skey = getPBEKey(pass);
Cipher cipher = Cipher.getInstance(
mapPBEParamsToAlgorithm(algOid, algParams));
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
SecretKey skey = getPBEKey(pass);
try {
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
} finally {
destroyPBEKey(skey);
}
byte[] keyInfo = cipher.doFinal(encryptedKey);
/*
* Parse the key algorithm and then use a JCA key factory
* to re-create the key.
*/
DerValue val = new DerValue(keyInfo);
DerInputStream in = val.toDerInputStream();
int i = in.getInteger();
DerValue[] value = in.getSequence(2);
if (value.length < 1 || value.length > 2) {
throw new IOException("Invalid length for AlgorithmIdentifier");
}
AlgorithmId algId = new AlgorithmId(value[0].getOID());
String keyAlgo = algId.getName();
// decode private key
if (entry instanceof PrivateKeyEntry) {
KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
Key tmp = kfac.generatePrivate(kspec);
if (debug != null) {
debug.println("Retrieved a protected private key at alias" +
" '" + alias + "' (" +
mapPBEParamsToAlgorithm(algOid, algParams) +
" iterations: " + ic + ")");
try {
DerInputStream in = val.toDerInputStream();
int i = in.getInteger();
DerValue[] value = in.getSequence(2);
if (value.length < 1 || value.length > 2) {
throw new IOException("Invalid length for AlgorithmIdentifier");
}
return tmp;
// decode secret key
} else {
byte[] keyBytes = in.getOctetString();
SecretKeySpec secretKeySpec =
new SecretKeySpec(keyBytes, keyAlgo);
AlgorithmId algId = new AlgorithmId(value[0].getOID());
String keyAlgo = algId.getName();
// Special handling required for PBE: needs a PBEKeySpec
Key tmp;
if (keyAlgo.startsWith("PBE")) {
SecretKeyFactory sKeyFactory =
SecretKeyFactory.getInstance(keyAlgo);
KeySpec pbeKeySpec =
sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
tmp = sKeyFactory.generateSecret(pbeKeySpec);
// decode private key
if (entry instanceof PrivateKeyEntry) {
KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
try {
Key tmp = kfac.generatePrivate(kspec);
if (debug != null) {
debug.println("Retrieved a protected private key at alias" +
" '" + alias + "' (" +
mapPBEParamsToAlgorithm(algOid, algParams) +
" iterations: " + ic + ")");
}
return tmp;
} finally {
SharedSecrets.getJavaSecuritySpecAccess()
.clearEncodedKeySpec(kspec);
}
// decode secret key
} else {
tmp = secretKeySpec;
}
byte[] keyBytes = in.getOctetString();
SecretKeySpec secretKeySpec =
new SecretKeySpec(keyBytes, keyAlgo);
if (debug != null) {
debug.println("Retrieved a protected secret key at alias " +
"'" + alias + "' (" +
mapPBEParamsToAlgorithm(algOid, algParams) +
" iterations: " + ic + ")");
try {
// Special handling required for PBE: needs a PBEKeySpec
Key tmp;
if (keyAlgo.startsWith("PBE")) {
SecretKeyFactory sKeyFactory =
SecretKeyFactory.getInstance(keyAlgo);
KeySpec pbeKeySpec =
sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
try {
tmp = sKeyFactory.generateSecret(pbeKeySpec);
} finally {
((PBEKeySpec)pbeKeySpec).clearPassword();
SharedSecrets.getJavaxCryptoSpecAccess()
.clearSecretKeySpec(secretKeySpec);
}
} else {
tmp = secretKeySpec;
}
if (debug != null) {
debug.println("Retrieved a protected secret key at alias " +
"'" + alias + "' (" +
mapPBEParamsToAlgorithm(algOid, algParams) +
" iterations: " + ic + ")");
}
return tmp;
} finally {
Arrays.fill(keyBytes, (byte)0);
}
}
return tmp;
} finally {
val.clear();
Arrays.fill(keyInfo, (byte) 0);
}
}, password);
@ -600,8 +625,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
}
// Encrypt the private key
keyEntry.protectedPrivKey =
encryptPrivateKey(key.getEncoded(), passwordProtection);
byte[] encoded = key.getEncoded();
try {
keyEntry.protectedPrivKey =
encryptPrivateKey(encoded, passwordProtection);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte) 0);
}
}
} else {
throw new KeyStoreException("Private key is not encoded" +
"as PKCS#8");
@ -629,17 +661,25 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
keyEntry.date = new Date();
// Encode secret key in a PKCS#8
DerOutputStream pkcs8 = new DerOutputStream();
DerOutputStream secretKeyInfo = new DerOutputStream();
secretKeyInfo.putInteger(0);
AlgorithmId algId = AlgorithmId.get(key.getAlgorithm());
algId.encode(secretKeyInfo);
secretKeyInfo.putOctetString(key.getEncoded());
pkcs8.write(DerValue.tag_Sequence, secretKeyInfo);
// Encrypt the secret key (using same PBE as for private keys)
keyEntry.protectedSecretKey =
encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
byte[] encoded = key.getEncoded();
secretKeyInfo.putOctetString(encoded);
Arrays.fill(encoded, (byte)0);
DerValue pkcs8 = DerValue.wrap(DerValue.tag_Sequence, secretKeyInfo);
byte[] p8Array = pkcs8.toByteArray();
pkcs8.clear();
try {
// Encrypt the secret key (using same PBE as for private keys)
keyEntry.protectedSecretKey =
encryptPrivateKey(p8Array, passwordProtection);
} finally {
Arrays.fill(p8Array, (byte)0);
}
if (debug != null) {
debug.println("Setting a protected secret key at alias '" +
@ -830,6 +870,17 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
return skey;
}
/*
* Destroy the key obtained from getPBEKey().
*/
private void destroyPBEKey(SecretKey key) {
try {
key.destroy();
} catch (DestroyFailedException e) {
// Accept this
}
}
/*
* Encrypt private key or secret key using Password-based encryption (PBE)
* as defined in PKCS#5.
@ -874,9 +925,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
}
// Use JCE
SecretKey skey = getPBEKey(passwordProtection.getPassword());
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
SecretKey skey = getPBEKey(passwordProtection.getPassword());
try {
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
} finally {
destroyPBEKey(skey);
}
byte[] encryptedKey = cipher.doFinal(data);
algid = new AlgorithmId(pbeOID, cipher.getParameters());
@ -1462,7 +1517,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
PBEParameterSpec params =
new PBEParameterSpec(salt, macIterationCount);
SecretKey key = getPBEKey(passwd);
m.init(key, params);
try {
m.init(key, params);
} finally {
destroyPBEKey(key);
}
m.update(data);
byte[] macResult = m.doFinal();
@ -1867,9 +1926,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
DerOutputStream bytes = new DerOutputStream();
// Use JCE
SecretKey skey = getPBEKey(password);
Cipher cipher = Cipher.getInstance(certProtectionAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
SecretKey skey = getPBEKey(password);
try {
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
} finally {
destroyPBEKey(skey);
}
encryptedData = cipher.doFinal(data);
AlgorithmId algId = new AlgorithmId(
@ -2075,10 +2138,14 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
try {
RetryWithZero.run(pass -> {
// Use JCE
SecretKey skey = getPBEKey(pass);
Cipher cipher = Cipher.getInstance(
mapPBEParamsToAlgorithm(algOid, algParams));
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
SecretKey skey = getPBEKey(pass);
try {
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
} finally {
destroyPBEKey(skey);
}
loadSafeContents(new DerInputStream(cipher.doFinal(rawData)));
return null;
}, password);
@ -2128,7 +2195,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
RetryWithZero.run(pass -> {
SecretKey key = getPBEKey(pass);
m.init(key, params);
try {
m.init(key, params);
} finally {
destroyPBEKey(key);
}
m.update(authSafeData);
byte[] macResult = m.doFinal();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -495,13 +495,16 @@ public class CtrDrbg extends AbstractDrbg {
// Step 4.1. Increment
addOne(v, ctrLen);
try {
// Step 4.2. Encrypt
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k, keyAlg));
byte[] out = cipher.doFinal(v);
// Step 4.2. Encrypt
// Step 4.3 and 5. Cat bytes and leftmost
System.arraycopy(out, 0, result, pos,
(len > blockLen) ? blockLen : len);
if (len > blockLen) {
cipher.doFinal(v, 0, blockLen, result, pos);
} else {
byte[] out = cipher.doFinal(v);
System.arraycopy(out, 0, result, pos, len);
Arrays.fill(out, (byte)0);
}
} catch (GeneralSecurityException e) {
throw new InternalError(e);
}

View File

@ -37,6 +37,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;
/**
* This class implements the DSA key factory of the Sun provider.
@ -93,7 +94,7 @@ public class DSAKeyFactory 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 DSAPrivateKeySpec) {
DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec)keySpec;
@ -103,9 +104,12 @@ public class DSAKeyFactory extends KeyFactorySpi {
dsaPrivKeySpec.getG());
} else if (keySpec instanceof PKCS8EncodedKeySpec) {
return new DSAPrivateKey
(((PKCS8EncodedKeySpec)keySpec).getEncoded());
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
try {
return new DSAPrivateKey(encoded);
} finally {
Arrays.fill(encoded, (byte) 0);
}
} else {
throw new InvalidKeySpecException
("Inappropriate key specification");
@ -183,8 +187,12 @@ public class DSAKeyFactory extends KeyFactorySpi {
params.getG()));
} else if (keySpec.isAssignableFrom(pkcs8KeySpec)) {
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) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -32,6 +32,7 @@ import java.security.AlgorithmParameters;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.interfaces.DSAParams;
import java.util.Arrays;
import sun.security.x509.AlgIdDSA;
import sun.security.pkcs.PKCS8Key;
@ -68,8 +69,11 @@ public final class DSAPrivateKey extends PKCS8Key
algid = new AlgIdDSA(p, q, g);
try {
key = new DerValue(DerValue.tag_Integer,
x.toByteArray()).toByteArray();
byte[] xbytes = x.toByteArray();
DerValue val = new DerValue(DerValue.tag_Integer, xbytes);
key = val.toByteArray();
val.clear();
Arrays.fill(xbytes, (byte)0);
} catch (IOException e) {
throw new AssertionError("Should not happen", e);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -254,15 +254,15 @@ public class HashDrbg extends AbstractHashDrbg {
int len = output.length;
while (len > 0) {
// Step 4.1 w = Hash (data).
digest.update(data);
if (len < outLen) {
// Step 4.1 w = Hash (data).
// Step 4.2 W = W || w.
System.arraycopy(digest.digest(data), 0, output, pos,
len);
byte[] out = digest.digest();
System.arraycopy(out, 0, output, pos, len);
Arrays.fill(out, (byte)0);
} else {
try {
// Step 4.1 w = Hash (data).
digest.update(data);
// Step 4.2 digest into right position, no need to cat
digest.digest(output, pos, outLen);
} catch (DigestException e) {

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
@ -206,6 +206,7 @@ final class KeyProtector {
digest = md.digest();
md.reset();
System.arraycopy(digest, 0, encrKey, encrKeyOffset, digest.length);
Arrays.fill(plainKey, (byte)0);
// wrap the protected private key in a PKCS#8-style
// EncryptedPrivateKeyInfo, and returns its encoding
@ -308,9 +309,11 @@ final class KeyProtector {
// algorithm and instantiates the appropriate key factory,
// which in turn parses the key material.
try {
return PKCS8Key.parseKey(new DerValue(plainKey));
return PKCS8Key.parseKey(plainKey);
} catch (IOException ioe) {
throw new UnrecoverableKeyException(ioe.getMessage());
} finally {
Arrays.fill(plainKey, (byte)0);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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
@ -42,4 +42,8 @@ public final class SHAKE256 extends SHA3 {
public byte[] digest() {
return engineDigest();
}
public void reset() {
engineReset();
}
}

View File

@ -30,6 +30,7 @@ import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.Arrays;
import sun.security.action.GetPropertyAction;
import sun.security.rsa.RSAUtil.KeyType;
@ -308,8 +309,14 @@ public class RSAKeyFactory extends KeyFactorySpi {
throw new InvalidKeyException("Invalid key", e);
}
} else {
return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(),
key.getEncoded());
byte[] encoded = key.getEncoded();
try {
return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(), encoded);
} finally {
if (encoded != null) {
Arrays.fill(encoded, (byte)0);
}
}
}
}
@ -340,8 +347,12 @@ public class RSAKeyFactory extends KeyFactorySpi {
private PrivateKey generatePrivate(KeySpec keySpec)
throws GeneralSecurityException {
if (keySpec instanceof PKCS8EncodedKeySpec) {
return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8",
((PKCS8EncodedKeySpec)keySpec).getEncoded());
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
try {
return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8", encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
} else if (keySpec instanceof RSAPrivateCrtKeySpec) {
RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
try {
@ -404,7 +415,12 @@ public class RSAKeyFactory extends KeyFactorySpi {
}
} else if (key instanceof RSAPrivateKey) {
if (keySpec.isAssignableFrom(PKCS8_KEYSPEC_CLS)) {
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 if (keySpec.isAssignableFrom(RSA_PRIVCRT_KEYSPEC_CLS)) {
// All supported keyspecs (other than PKCS8_KEYSPEC_CLS) descend from RSA_PRIVCRT_KEYSPEC_CLS
if (key instanceof RSAPrivateCrtKey) {

View File

@ -31,6 +31,7 @@ import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import java.util.Arrays;
import sun.security.util.*;
@ -192,20 +193,44 @@ public final class RSAPrivateCrtKeyImpl
this.keyParams = keyParams;
try {
// generate the key encoding
DerOutputStream out = new DerOutputStream();
byte[][] nbytes = new byte[8][];
nbytes[0] = n.toByteArray();
nbytes[1] = e.toByteArray();
nbytes[2] = d.toByteArray();
nbytes[3] = p.toByteArray();
nbytes[4] = q.toByteArray();
nbytes[5] = pe.toByteArray();
nbytes[6] = qe.toByteArray();
nbytes[7] = coeff.toByteArray();
// Initiate with a big enough size so there's no need to
// reallocate memory later and thus can be cleaned up
// reliably.
DerOutputStream out = new DerOutputStream(
nbytes[0].length + nbytes[1].length +
nbytes[2].length + nbytes[3].length +
nbytes[4].length + nbytes[5].length +
nbytes[6].length + nbytes[7].length +
100); // Enough for version(3) and 8 tag+length(3 or 4)
out.putInteger(0); // version must be 0
out.putInteger(n);
out.putInteger(e);
out.putInteger(d);
out.putInteger(p);
out.putInteger(q);
out.putInteger(pe);
out.putInteger(qe);
out.putInteger(coeff);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
out.putInteger(nbytes[0]);
out.putInteger(nbytes[1]);
out.putInteger(nbytes[2]);
out.putInteger(nbytes[3]);
out.putInteger(nbytes[4]);
out.putInteger(nbytes[5]);
out.putInteger(nbytes[6]);
out.putInteger(nbytes[7]);
// Private values from [2] on.
Arrays.fill(nbytes[2], (byte)0);
Arrays.fill(nbytes[3], (byte)0);
Arrays.fill(nbytes[4], (byte)0);
Arrays.fill(nbytes[5], (byte)0);
Arrays.fill(nbytes[6], (byte)0);
Arrays.fill(nbytes[7], (byte)0);
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
key = val.toByteArray();
val.clear();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
@ -285,29 +310,33 @@ public final class RSAPrivateCrtKeyImpl
// e, d, p, q, pe, qe, and coeff, and return the parsed components.
private static BigInteger[] parseASN1(byte[] raw) throws IOException {
DerValue derValue = new DerValue(raw);
if (derValue.tag != DerValue.tag_Sequence) {
throw new IOException("Not a SEQUENCE");
}
int version = derValue.data.getInteger();
if (version != 0) {
throw new IOException("Version must be 0");
}
try {
if (derValue.tag != DerValue.tag_Sequence) {
throw new IOException("Not a SEQUENCE");
}
int version = derValue.data.getInteger();
if (version != 0) {
throw new IOException("Version must be 0");
}
BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff
/*
* Some implementations do not correctly encode ASN.1 INTEGER values
* in 2's complement format, resulting in a negative integer when
* decoded. Correct the error by converting it to a positive integer.
*
* See CR 6255949
*/
for (int i = 0; i < result.length; i++) {
result[i] = derValue.data.getPositiveBigInteger();
BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff
/*
* Some implementations do not correctly encode ASN.1 INTEGER values
* in 2's complement format, resulting in a negative integer when
* decoded. Correct the error by converting it to a positive integer.
*
* See CR 6255949
*/
for (int i = 0; i < result.length; i++) {
result[i] = derValue.data.getPositiveBigInteger();
}
if (derValue.data.available() != 0) {
throw new IOException("Extra data available");
}
return result;
} finally {
derValue.clear();
}
if (derValue.data.available() != 0) {
throw new IOException("Extra data available");
}
return result;
}
private void parseKeyBits() throws InvalidKeyException {

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
@ -31,6 +31,7 @@ import java.math.BigInteger;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.interfaces.*;
import java.util.Arrays;
import sun.security.util.*;
import sun.security.pkcs.PKCS8Key;
@ -90,19 +91,25 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
try {
// generate the key encoding
DerOutputStream out = new DerOutputStream();
byte[] nbytes = n.toByteArray();
byte[] dbytes = d.toByteArray();
DerOutputStream out = new DerOutputStream(
nbytes.length + dbytes.length + 50);
// Enough for 7 zeroes (21) and 2 tag+length(4)
out.putInteger(0); // version must be 0
out.putInteger(n);
out.putInteger(nbytes);
Arrays.fill(nbytes, (byte)0);
out.putInteger(0);
out.putInteger(d);
out.putInteger(dbytes);
Arrays.fill(dbytes, (byte)0);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
key = val.toByteArray();
val.clear();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -169,6 +169,17 @@ extends ByteArrayOutputStream implements DerEncoder {
write(buf, 0, buf.length);
}
/**
* Marshals a DER integer on the output stream.
*
* @param i the integer in bytes, equivalent to BigInteger::toByteArray.
*/
public void putInteger(byte[] buf) throws IOException {
write(DerValue.tag_Integer);
putLength(buf.length);
write(buf, 0, buf.length);
}
/**
* Marshals a DER integer on the output stream.
* @param i the integer in the form of an Integer.
@ -575,4 +586,8 @@ extends ByteArrayOutputStream implements DerEncoder {
public void derEncode(OutputStream out) throws IOException {
out.write(toByteArray());
}
byte[] buf() {
return buf;
}
}

View File

@ -286,6 +286,22 @@ public class DerValue {
this(tag, buffer.clone(), true);
}
/**
* Wraps an DerOutputStream. All bytes currently written
* into the stream will become the content of the newly
* created DerValue.
*
* Attention: do not reset the DerOutputStream after this call.
* No array copying is made.
*
* @param tag the tag
* @param out the DerOutputStream
* @returns a new DerValue using out as its content
*/
public static DerValue wrap(byte tag, DerOutputStream out) {
return new DerValue(tag, out.buf(), 0, out.size(), false);
}
/**
* Parse an ASN.1/BER encoded datum. The entire encoding must hold exactly
* one datum, including its tag and length.
@ -1072,10 +1088,15 @@ public class DerValue {
* @return DER-encoded value, including tag and length.
*/
public byte[] toByteArray() throws IOException {
data.pos = data.start; // Compatibility. At head.
// Minimize content duplication by writing out tag and length only
DerOutputStream out = new DerOutputStream();
encode(out);
data.pos = data.start; // encode go last, should go back
return out.toByteArray();
out.write(tag);
out.putLength(end - start);
int headLen = out.size();
byte[] result = Arrays.copyOf(out.buf(), end - start + headLen);
System.arraycopy(buffer, start, result, headLen, end - start);
return result;
}
/**
@ -1216,4 +1237,8 @@ public class DerValue {
}
return result.toArray(new DerValue[0]);
}
public void clear() {
Arrays.fill(buffer, start, end, (byte)0);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 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 sun.security.util;
import jdk.internal.access.SharedSecrets;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
@ -122,8 +124,11 @@ public final class ECUtil {
throws InvalidKeySpecException {
KeyFactory keyFactory = getKeyFactory();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
return (ECPrivateKey)keyFactory.generatePrivate(keySpec);
try {
return (ECPrivateKey) keyFactory.generatePrivate(keySpec);
} finally {
SharedSecrets.getJavaSecuritySpecAccess().clearEncodedKeySpec(keySpec);
}
}
public static ECPrivateKey generateECPrivateKey(BigInteger s,

View File

@ -47,6 +47,7 @@ import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
import java.math.BigInteger;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;
import sun.security.jca.JCAUtil;
@ -82,8 +83,12 @@ public final class KeyUtil {
if (key instanceof SecretKey) {
SecretKey sk = (SecretKey)key;
String format = sk.getFormat();
if ("RAW".equals(format) && sk.getEncoded() != null) {
size = (sk.getEncoded().length * 8);
if ("RAW".equals(format)) {
byte[] encoded = sk.getEncoded();
if (encoded != null) {
size = (encoded.length * 8);
Arrays.fill(encoded, (byte)0);
}
} // Otherwise, it may be a unextractable key of PKCS#11, or
// a key we are not able to handle.
} else if (key instanceof RSAKey) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -100,32 +100,6 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
@Deprecated
public AlgIdDSA () {}
AlgIdDSA (DerValue val) throws IOException
{ super(val.getOID()); }
/**
* Construct an AlgIdDSA from an X.509 encoded byte array.
*/
public AlgIdDSA (byte[] encodedAlg) throws IOException
{ super (new DerValue(encodedAlg).getOID()); }
/**
* Constructs a DSS/DSA Algorithm ID from unsigned integers that
* define the algorithm parameters. Those integers are encoded
* as big-endian byte arrays.
*
* @param p the DSS/DSA parameter "P"
* @param q the DSS/DSA parameter "Q"
* @param g the DSS/DSA parameter "G"
*/
public AlgIdDSA (byte[] p, byte[] q, byte[] g)
throws IOException
{
this (new BigInteger (1, p),
new BigInteger (1, q),
new BigInteger (1, g));
}
/**
* Constructs a DSS/DSA Algorithm ID from numeric parameters.
* If all three are null, then the parameters portion of the algorithm id
@ -135,8 +109,7 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
* @param q the DSS/DSA parameter "Q"
* @param g the DSS/DSA parameter "G"
*/
public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g)
{
public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g) {
super (DSA_oid);
if (p != null || q != null || g != null) {
@ -168,28 +141,29 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
* For algorithm IDs which haven't been created from a DER encoded
* value, "params" must be created.
*/
private void initializeParams ()
throws IOException
{
DerOutputStream out = new DerOutputStream ();
private void initializeParams () throws IOException {
DerOutputStream out = new DerOutputStream();
out.putInteger(p);
out.putInteger(q);
out.putInteger(g);
params = new DerValue (DerValue.tag_Sequence,out.toByteArray ());
DerOutputStream result = new DerOutputStream();
result.write(DerValue.tag_Sequence, out);
encodedParams = result.toByteArray();
}
/**
* Parses algorithm parameters P, Q, and G. They're found
* in the "params" member, which never needs to be changed.
*/
protected void decodeParams ()
throws IOException
{
if (params == null)
protected void decodeParams () throws IOException {
if (encodedParams == null) {
throw new IOException("DSA alg params are null");
if (params.tag != DerValue.tag_Sequence)
throw new IOException("DSA alg parsing error");
}
DerValue params = new DerValue(encodedParams);
if (params.tag != DerValue.tag_Sequence) {
throw new IOException("DSA alg parsing error");
}
params.data.reset ();
@ -206,21 +180,21 @@ class AlgIdDSA extends AlgorithmId implements DSAParams
/*
* Returns a formatted string describing the parameters.
*/
public String toString ()
{ return paramsToString (); }
public String toString () {
return paramsToString();
}
/*
* Returns a string describing the parameters.
*/
protected String paramsToString ()
{
if (params == null)
protected String paramsToString () {
if (encodedParams == null) {
return " null\n";
else
return
"\n p:\n" + Debug.toHexString(p) +
"\n q:\n" + Debug.toHexString(q) +
"\n g:\n" + Debug.toHexString(g) +
"\n";
} else {
return "\n p:\n" + Debug.toHexString(p) +
"\n q:\n" + Debug.toHexString(q) +
"\n g:\n" + Debug.toHexString(g) +
"\n";
}
}
}

View File

@ -70,17 +70,13 @@ public class AlgorithmId implements Serializable, DerEncoder {
// The (parsed) parameters
@SuppressWarnings("serial") // Not statically typed as Serializable
private AlgorithmParameters algParams;
private boolean constructedFromDer = true;
/**
* Parameters for this algorithm. These are stored in unparsed
* DER-encoded form; subclasses can be made to automaticaly parse
* them so there is fast access to these parameters.
*/
@SuppressWarnings("serial") // Not statically typed as Serializable
protected DerValue params;
private transient byte[] encodedParams;
protected transient byte[] encodedParams;
/**
* Constructs an algorithm ID which will be initialized
@ -107,17 +103,14 @@ public class AlgorithmId implements Serializable, DerEncoder {
*/
public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters algparams) {
algid = oid;
algParams = algparams;
constructedFromDer = false;
this.algParams = algparams;
if (algParams != null) {
try {
encodedParams = algParams.getEncoded();
} catch (IOException ioe) {
// It should be safe to ignore this.
// This exception can occur if AlgorithmParameters was not
// initialized (which should not occur), or if it was
// initialized with bogus parameters, which should have
// been detected when init was called.
// Ignore this at the moment. This exception can occur
// if AlgorithmParameters was not initialized yet. Will
// try to re-getEncoded() again later.
}
}
}
@ -131,8 +124,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
public AlgorithmId(ObjectIdentifier oid, DerValue params)
throws IOException {
this.algid = oid;
this.params = params;
if (this.params != null) {
if (params != null) {
encodedParams = params.toByteArray();
decodeParams();
}
@ -177,20 +169,14 @@ public class AlgorithmId implements Serializable, DerEncoder {
DerOutputStream tmp = new DerOutputStream();
bytes.putOID(algid);
// Setup params from algParams since no DER encoding is given
if (constructedFromDer == false) {
if (algParams != null) {
if (encodedParams == null) {
// call getEncoded again in case algParams were initialized
// after being passed in to ctor.
encodedParams = algParams.getEncoded();
}
params = new DerValue(encodedParams);
} else {
params = null;
}
// Re-getEncoded() from algParams if it was not initialized
if (algParams != null && encodedParams == null) {
encodedParams = algParams.getEncoded();
// If still not initialized. Let the IOE be thrown.
}
if (params == null) {
if (encodedParams == null) {
// Changes backed out for compatibility with Solaris
// Several AlgorithmId should omit the whole parameter part when
@ -242,7 +228,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
bytes.putNull();
}
} else {
bytes.putDerValue(params);
bytes.write(encodedParams);
}
tmp.write(DerValue.tag_Sequence, bytes);
out.write(tmp.toByteArray());
@ -285,7 +271,7 @@ public class AlgorithmId implements Serializable, DerEncoder {
// first check the list of support oids
KnownOIDs o = KnownOIDs.findMatch(oidStr);
if (o == KnownOIDs.SpecifiedSHA2withECDSA) {
if (params != null) {
if (encodedParams != null) {
try {
AlgorithmId digestParams =
AlgorithmId.parse(new DerValue(encodedParams));

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
@ -228,7 +228,7 @@ abstract class P11Key implements Key, Length {
throw new NotSerializableException
("Cannot serialize sensitive and unextractable keys");
}
return new KeyRep(type, getAlgorithm(), format, getEncoded());
return new KeyRep(type, getAlgorithm(), format, getEncodedInternal());
}
public String toString() {

View File

@ -28,6 +28,7 @@ package sun.security.ec;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.Arrays;
/**
* KeyFactory for EC keys. Keys must be instances of PublicKey or PrivateKey
@ -204,7 +205,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
ecKey.getParams()
);
} else if ("PKCS#8".equals(key.getFormat())) {
return new ECPrivateKeyImpl(key.getEncoded());
byte[] encoded = key.getEncoded();
try {
return new ECPrivateKeyImpl(encoded);
} finally {
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeyException("Private keys must be instance "
+ "of ECPrivateKey or have PKCS#8 encoding");
@ -234,7 +240,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
throws GeneralSecurityException {
if (keySpec instanceof PKCS8EncodedKeySpec) {
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
return new ECPrivateKeyImpl(pkcsSpec.getEncoded());
byte[] encoded = pkcsSpec.getEncoded();
try {
return new ECPrivateKeyImpl(encoded);
} finally {
Arrays.fill(encoded, (byte) 0);
}
} else if (keySpec instanceof ECPrivateKeySpec) {
ECPrivateKeySpec ecSpec = (ECPrivateKeySpec)keySpec;
return new ECPrivateKeyImpl(ecSpec.getS(), ecSpec.getParams());
@ -270,7 +281,12 @@ public final class ECKeyFactory extends KeyFactorySpi {
}
} else if (key instanceof ECPrivateKey) {
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 if (keySpec.isAssignableFrom(ECPrivateKeySpec.class)) {
ECPrivateKey ecKey = (ECPrivateKey)key;
return keySpec.cast(new ECPrivateKeySpec(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 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.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.Optional;
import sun.security.jca.JCAUtil;
@ -200,6 +201,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
AffinePoint affPub = pub.asAffine();
PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
Arrays.fill(privArr, (byte)0);
ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
affPub.getY().asBigInteger());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 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
@ -31,6 +31,7 @@ import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.Arrays;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
@ -103,9 +104,10 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
byte[] privBytes = s.clone();
ArrayUtil.reverse(privBytes);
out.putOctetString(privBytes);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
Arrays.fill(privBytes, (byte)0);
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
key = val.toByteArray();
val.clear();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
@ -124,13 +126,15 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
int outPos = Math.max(sOctets.length - sArr.length, 0);
int length = Math.min(sArr.length, sOctets.length);
System.arraycopy(sArr, inPos, sOctets, outPos, length);
Arrays.fill(sArr, (byte)0);
DerOutputStream out = new DerOutputStream();
out.putInteger(1); // version 1
out.putOctetString(sOctets);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
Arrays.fill(sOctets, (byte)0);
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
key = val.toByteArray();
val.clear();
} catch (IOException exc) {
throw new AssertionError("Should not happen", exc);
}
@ -147,6 +151,7 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
byte[] arrCopy = arrayS.clone();
ArrayUtil.reverse(arrCopy);
s = new BigInteger(1, arrCopy);
Arrays.fill(arrCopy, (byte)0);
}
return s;
}

View File

@ -42,6 +42,7 @@ import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.XECPublicKeySpec;
import java.security.spec.XECPrivateKeySpec;
import java.util.Arrays;
import java.util.function.Function;
public class XDHKeyFactory extends KeyFactorySpi {
@ -87,9 +88,14 @@ public class XDHKeyFactory extends KeyFactorySpi {
return result;
} else if (key instanceof PrivateKey &&
key.getFormat().equals("PKCS#8")) {
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(key.getEncoded());
checkLockedParams(InvalidKeyException::new, result.getParams());
return result;
byte[] encoded = key.getEncoded();
try {
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(encoded);
checkLockedParams(InvalidKeyException::new, result.getParams());
return result;
} finally {
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeyException("Unsupported key type or format");
}
@ -165,17 +171,26 @@ public class XDHKeyFactory extends KeyFactorySpi {
if (keySpec instanceof PKCS8EncodedKeySpec) {
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec;
XDHPrivateKeyImpl result =
new XDHPrivateKeyImpl(pkcsSpec.getEncoded());
checkLockedParams(InvalidKeySpecException::new,
result.getParams());
return result;
byte[] encoded = pkcsSpec.getEncoded();
try {
XDHPrivateKeyImpl result = new XDHPrivateKeyImpl(encoded);
checkLockedParams(InvalidKeySpecException::new,
result.getParams());
return result;
} finally {
Arrays.fill(encoded, (byte) 0);
}
} else if (keySpec instanceof XECPrivateKeySpec) {
XECPrivateKeySpec privateKeySpec = (XECPrivateKeySpec) keySpec;
XECParameters params = XECParameters.get(
InvalidKeySpecException::new, privateKeySpec.getParams());
checkLockedParams(InvalidKeySpecException::new, params);
return new XDHPrivateKeyImpl(params, privateKeySpec.getScalar());
byte[] scalar = privateKeySpec.getScalar();
try {
return new XDHPrivateKeyImpl(params, scalar);
} finally {
Arrays.fill(scalar, (byte)0);
}
} else {
throw new InvalidKeySpecException(
"Only PKCS8EncodedKeySpec and XECPrivateKeySpec supported");
@ -210,14 +225,23 @@ public class XDHKeyFactory extends KeyFactorySpi {
if (!key.getFormat().equals("PKCS#8")) {
throw new InvalidKeySpecException("Format is not PKCS#8");
}
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 if (keySpec.isAssignableFrom(XECPrivateKeySpec.class)) {
XECPrivateKey xecKey = (XECPrivateKey) key;
byte[] scalar = xecKey.getScalar().orElseThrow(
() -> new InvalidKeySpecException("No private key value")
);
return keySpec.cast(
new XECPrivateKeySpec(xecKey.getParams(), scalar));
try {
return keySpec.cast(
new XECPrivateKeySpec(xecKey.getParams(), scalar));
} finally {
Arrays.fill(scalar, (byte)0);
}
} else {
throw new InvalidKeySpecException
("KeySpec must be PKCS8EncodedKeySpec or XECPrivateKeySpec");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 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
@ -35,6 +35,7 @@ import java.security.ProviderException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;
import sun.security.jca.JCAUtil;
@ -104,7 +105,9 @@ public class XDHKeyPairGenerator extends KeyPairGeneratorSpi {
byte[] privateKey = ops.generatePrivate(random);
// computePublic may modify the private key, so clone it first
BigInteger publicKey = ops.computePublic(privateKey.clone());
byte[] cloned = privateKey.clone();
BigInteger publicKey = ops.computePublic(cloned);
Arrays.fill(cloned, (byte)0);
try {
return new KeyPair(
@ -113,6 +116,8 @@ public class XDHKeyPairGenerator extends KeyPairGeneratorSpi {
);
} catch (InvalidKeyException ex) {
throw new ProviderException(ex);
} finally {
Arrays.fill(privateKey, (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
@ -49,12 +49,14 @@ public final class XDHPrivateKeyImpl extends PKCS8Key implements XECPrivateKey {
this.k = k.clone();
this.algid = new AlgorithmId(params.getOid());
DerOutputStream derKey = new DerOutputStream();
DerValue val = new DerValue(DerValue.tag_OctetString, k);
try {
derKey.putOctetString(k);
this.key = derKey.toByteArray();
this.key = val.toByteArray();
} catch (IOException ex) {
throw new AssertionError("Should not happen", ex);
} finally {
val.clear();
}
checkLength(params);
}

View File

@ -33,6 +33,7 @@ import java.security.InvalidKeyException;
import java.security.ProviderException;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.Arrays;
import java.util.function.Function;
public class EdDSAKeyFactory extends KeyFactorySpi {
@ -79,10 +80,15 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
return result;
} else if (key instanceof PrivateKey &&
key.getFormat().equals("PKCS#8")) {
EdDSAPrivateKeyImpl result =
new EdDSAPrivateKeyImpl(key.getEncoded());
checkLockedParams(InvalidKeyException::new, result.getParams());
return result;
byte[] encoded = key.getEncoded();
try {
EdDSAPrivateKeyImpl result =
new EdDSAPrivateKeyImpl(encoded);
checkLockedParams(InvalidKeyException::new, result.getParams());
return result;
} finally {
Arrays.fill(encoded, (byte)0);
}
} else {
throw new InvalidKeyException("Unsupported key type or format");
}
@ -158,17 +164,27 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
if (keySpec instanceof PKCS8EncodedKeySpec) {
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec;
EdDSAPrivateKeyImpl result =
new EdDSAPrivateKeyImpl(pkcsSpec.getEncoded());
checkLockedParams(InvalidKeySpecException::new,
result.getParams());
return result;
byte[] encoded = pkcsSpec.getEncoded();
try {
EdDSAPrivateKeyImpl result =
new EdDSAPrivateKeyImpl(encoded);
checkLockedParams(InvalidKeySpecException::new,
result.getParams());
return result;
} finally {
Arrays.fill(encoded, (byte) 0);
}
} else if (keySpec instanceof EdECPrivateKeySpec) {
EdECPrivateKeySpec privateKeySpec = (EdECPrivateKeySpec) keySpec;
EdDSAParameters params = EdDSAParameters.get(
InvalidKeySpecException::new, privateKeySpec.getParams());
checkLockedParams(InvalidKeySpecException::new, params);
return new EdDSAPrivateKeyImpl(params, privateKeySpec.getBytes());
byte[] bytes = privateKeySpec.getBytes();
try {
return new EdDSAPrivateKeyImpl(params, bytes);
} finally {
Arrays.fill(bytes, (byte)0);
}
} else {
throw new InvalidKeySpecException(
"Only PKCS8EncodedKeySpec and EdECPrivateKeySpec supported");
@ -203,14 +219,23 @@ public class EdDSAKeyFactory extends KeyFactorySpi {
if (!key.getFormat().equals("PKCS#8")) {
throw new InvalidKeySpecException("Format is not PKCS#8");
}
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 if (keySpec.isAssignableFrom(EdECPrivateKeySpec.class)) {
EdECPrivateKey edKey = (EdECPrivateKey) key;
byte[] scalar = edKey.getBytes().orElseThrow(
() -> new InvalidKeySpecException("No private key value")
);
return keySpec.cast(
new EdECPrivateKeySpec(edKey.getParams(), scalar));
try {
return keySpec.cast(
new EdECPrivateKeySpec(edKey.getParams(), scalar));
} finally {
Arrays.fill(scalar, (byte)0);
}
} else {
throw new InvalidKeySpecException
("KeySpec must be PKCS8EncodedKeySpec or EdECPrivateKeySpec");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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
@ -37,6 +37,7 @@ import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.EdECPoint;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;
import sun.security.jca.JCAUtil;
import sun.security.util.SecurityProviderConstants;
@ -120,6 +121,8 @@ public class EdDSAKeyPairGenerator extends KeyPairGeneratorSpi {
);
} catch (InvalidKeyException ex) {
throw new ProviderException(ex);
} finally {
Arrays.fill(privateKey, (byte)0);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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
@ -115,7 +115,11 @@ public class EdDSAParameters {
}
@Override
public byte[] digest() {
return md.digest();
try {
return md.digest();
} finally {
md.reset();
}
}
}
@ -135,7 +139,11 @@ public class EdDSAParameters {
}
@Override
public byte[] digest() {
return md.digest();
try {
return md.digest();
} finally {
md.reset();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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
@ -51,12 +51,13 @@ public final class EdDSAPrivateKeyImpl
this.algid = new AlgorithmId(params.getOid());
this.h = h.clone();
DerOutputStream derKey = new DerOutputStream();
DerValue val = new DerValue(DerValue.tag_OctetString, h);
try {
derKey.putOctetString(h);
this.key = derKey.toByteArray();
this.key = val.toByteArray();
} catch (IOException ex) {
throw new AssertionError("Should not happen", ex);
} finally {
val.clear();
}
checkLength(params);
}

View File

@ -76,8 +76,7 @@ public class PKCS8Test {
.formatter(ASN1Formatter.formatter())
.toString(encodedKey));
PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(
new DerValue(encodedKey));
PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(encodedKey);
Assert.assertEquals(decodedKey.getAlgorithm(), ALGORITHM);
Assert.assertEquals(decodedKey.getFormat(), FORMAT);
@ -120,6 +119,6 @@ public class PKCS8Test {
Assert.assertTrue(length < 127);
original[1] = (byte)(length - 2); // the length field inside DER
original[4] = (byte)newVersion; // the version inside DER
PKCS8Key.parseKey(new DerValue(original));
PKCS8Key.parseKey(original);
}
}

View File

@ -98,8 +98,7 @@ public class TestKeyFactory extends PKCS11Test {
}
@Override
public byte[] getEncoded() {
// skip cloning for testing key.
return encodedPriv;
return encodedPriv.clone();
}
};
byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR);
@ -114,8 +113,7 @@ public class TestKeyFactory extends PKCS11Test {
}
@Override
public byte[] getEncoded() {
// skip cloning for testing key.
return encodedPub;
return encodedPub.clone();
}
};
}

View File

@ -97,8 +97,7 @@ public class TestKeyFactory {
}
@Override
public byte[] getEncoded() {
// skip cloning for testing key.
return encodedPriv;
return encodedPriv.clone();
}
};
byte[] encodedPub = Base64.getDecoder().decode(PKCS1_PUB_STR);
@ -113,8 +112,7 @@ public class TestKeyFactory {
}
@Override
public byte[] getEncoded() {
// skip cloning for testing key.
return encodedPub;
return encodedPub.clone();
}
};
}