This commit is contained in:
Henry Jen 2017-10-20 09:49:02 -07:00
commit 4e93f8fc9f
108 changed files with 2493 additions and 1429 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, 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,7 +156,7 @@ abstract class AESCipher extends CipherSpi {
throw new InvalidKeyException("Key encoding must not be null");
} else if (value.length != fixedKeySize) {
throw new InvalidKeyException("The key must be " +
fixedKeySize*8 + " bits");
fixedKeySize + " bytes");
}
}
}
@ -509,7 +509,7 @@ abstract class AESCipher extends CipherSpi {
throw new InvalidKeyException("Invalid AES key length: " +
encoded.length + " bytes");
}
return encoded.length * 8;
return Math.multiplyExact(encoded.length, 8);
}
/**
@ -628,9 +628,9 @@ abstract class AESCipher extends CipherSpi {
}
if (src != null) {
int aadLen = src.limit() - src.position();
if (aadLen != 0) {
if (aadLen > 0) {
if (src.hasArray()) {
int aadOfs = src.arrayOffset() + src.position();
int aadOfs = Math.addExact(src.arrayOffset(), src.position());
core.updateAAD(src.array(), aadOfs, aadLen);
src.position(src.limit());
} else {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2017, 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,7 +156,7 @@ abstract class AESWrapCipher extends CipherSpi {
if (decrypting) {
result = inputLen - 8;
} else {
result = inputLen + 8;
result = Math.addExact(inputLen, 8);
}
return (result < 0? 0:result);
}
@ -378,7 +378,7 @@ abstract class AESWrapCipher extends CipherSpi {
throw new InvalidKeyException("Invalid key length: " +
encoded.length + " bytes");
}
return encoded.length * 8;
return Math.multiplyExact(encoded.length, 8);
}
/**
@ -404,7 +404,7 @@ abstract class AESWrapCipher extends CipherSpi {
throw new InvalidKeyException("Cannot get an encoding of " +
"the key to be wrapped");
}
byte[] out = new byte[keyVal.length + 8];
byte[] out = new byte[Math.addExact(keyVal.length, 8)];
if (keyVal.length == 8) {
System.arraycopy(IV, 0, out, 0, IV.length);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2017, 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
@ -257,7 +257,7 @@ public final class ARCFOURCipher extends CipherSpi {
// see JCE spec
protected int engineGetKeySize(Key key) throws InvalidKeyException {
byte[] encodedKey = getEncodedKey(key);
return encodedKey.length << 3;
return Math.multiplyExact(encodedKey.length, 8);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2017, 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
@ -373,7 +373,7 @@ public final class BlowfishCipher extends CipherSpi {
* @exception InvalidKeyException if <code>key</code> is invalid.
*/
protected int engineGetKeySize(Key key) throws InvalidKeyException {
return (key.getEncoded().length * 8);
return Math.multiplyExact(key.getEncoded().length, 8);
}
/**

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, 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
@ -324,13 +324,14 @@ final class CipherCore {
}
private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
int totalLen = buffered + inputLen + cipher.getBufferedLength();
int totalLen = Math.addExact(buffered, cipher.getBufferedLength());
totalLen = Math.addExact(totalLen, inputLen);
switch (cipherMode) {
case GCM_MODE:
if (isDoFinal) {
int tagLen = ((GaloisCounterMode) cipher).getTagLen();
if (!decrypting) {
totalLen += tagLen;
totalLen = Math.addExact(totalLen, tagLen);
} else {
totalLen -= tagLen;
}
@ -346,10 +347,10 @@ final class CipherCore {
totalLen = diffBlocksize;
} else {
int residue = (totalLen - diffBlocksize) % blockSize;
totalLen += (blockSize - residue);
totalLen = Math.addExact(totalLen, (blockSize - residue));
}
} else {
totalLen += padding.padLength(totalLen);
totalLen = Math.addExact(totalLen, padding.padLength(totalLen));
}
}
break;
@ -711,7 +712,8 @@ final class CipherCore {
}
// figure out how much can be sent to crypto function
int len = buffered + inputLen - minBytes;
int len = Math.addExact(buffered, inputLen);
len -= minBytes;
if (padding != null && decrypting) {
// do not include the padding bytes when decrypting
len -= blockSize;
@ -730,12 +732,12 @@ final class CipherCore {
int outLen = 0;
if (len != 0) { // there is some work to do
if ((input == output)
&& (outputOffset < (inputOffset + inputLen))
&& (inputOffset < (outputOffset + buffer.length))) {
&& (outputOffset - inputOffset < inputLen)
&& (inputOffset - outputOffset < buffer.length)) {
// copy 'input' out to avoid its content being
// overwritten prematurely.
input = Arrays.copyOfRange(input, inputOffset,
inputOffset + inputLen);
Math.addExact(inputOffset, inputLen));
inputOffset = 0;
}
if (len <= buffered) {
@ -757,13 +759,13 @@ final class CipherCore {
if (bufferCapacity != 0) {
temp = Math.min(bufferCapacity, inputConsumed);
if (unitBytes != blockSize) {
temp -= ((buffered + temp) % unitBytes);
temp -= (Math.addExact(buffered, temp) % unitBytes);
}
System.arraycopy(input, inputOffset, buffer, buffered, temp);
inputOffset += temp;
inputOffset = Math.addExact(inputOffset, temp);
inputConsumed -= temp;
inputLen -= temp;
buffered += temp;
buffered = Math.addExact(buffered, temp);
}
// process 'buffer'
if (decrypting) {
@ -771,7 +773,7 @@ final class CipherCore {
} else {
outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset);
}
outputOffset += outLen;
outputOffset = Math.addExact(outputOffset, outLen);
buffered = 0;
}
if (inputConsumed > 0) { // still has input to process
@ -802,7 +804,7 @@ final class CipherCore {
if (inputLen > 0) {
System.arraycopy(input, inputOffset, buffer, buffered,
inputLen);
buffered += inputLen;
buffered = Math.addExact(buffered, inputLen);
}
return outLen;
}
@ -912,10 +914,10 @@ final class CipherCore {
}
// calculate total input length
int len = buffered + inputLen;
int len = Math.addExact(buffered, inputLen);
// calculate padding length
int totalLen = len + cipher.getBufferedLength();
int totalLen = Math.addExact(len, cipher.getBufferedLength());
int paddingLen = 0;
// will the total input length be a multiple of blockSize?
if (unitBytes != blockSize) {
@ -948,12 +950,12 @@ final class CipherCore {
int finalBufLen = inputLen;
if ((buffered != 0) || (!decrypting && padding != null) ||
((input == output)
&& (outputOffset < (inputOffset + inputLen))
&& (inputOffset < (outputOffset + buffer.length)))) {
&& (outputOffset - inputOffset < inputLen)
&& (inputOffset - outputOffset < buffer.length))) {
if (decrypting || padding == null) {
paddingLen = 0;
}
finalBuf = new byte[len + paddingLen];
finalBuf = new byte[Math.addExact(len, paddingLen)];
finalOffset = 0;
if (buffered != 0) {
System.arraycopy(buffer, 0, finalBuf, 0, buffered);
@ -963,7 +965,7 @@ final class CipherCore {
buffered, inputLen);
}
if (paddingLen != 0) {
padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen);
padding.padWithLen(finalBuf, Math.addExact(buffered, inputLen), paddingLen);
}
finalBufLen = finalBuf.length;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2017, 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
@ -140,7 +140,7 @@ public final class DESedeWrapCipher extends CipherSpi {
if (decrypting) {
result = inputLen - 16; // CHECKSUM_LEN + IV_LEN;
} else {
result = inputLen + 16;
result = Math.addExact(inputLen, 16);
}
return (result < 0? 0:result);
}
@ -449,11 +449,11 @@ public final class DESedeWrapCipher extends CipherSpi {
}
byte[] cks = getChecksum(keyVal);
byte[] in = new byte[keyVal.length + CHECKSUM_LEN];
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[] out = new byte[iv.length + in.length];
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);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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 javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHGenParameterSpec;
import sun.security.provider.ParameterCache;
import static sun.security.util.SecurityProviderConstants.DEF_DH_KEY_SIZE;
/**
* This class represents the key pair generator for Diffie-Hellman key pairs.
@ -42,8 +43,7 @@ import sun.security.provider.ParameterCache;
* <ul>
* <li>By providing the size in bits of the prime modulus -
* This will be used to create a prime modulus and base generator, which will
* then be used to create the Diffie-Hellman key pair. The default size of the
* prime modulus is 2048 bits.
* then be used to create the Diffie-Hellman key pair.
* <li>By providing a prime modulus and base generator
* </ul>
*
@ -68,7 +68,7 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
public DHKeyPairGenerator() {
super();
initialize(2048, null);
initialize(DEF_DH_KEY_SIZE, null);
}
private static void checkKeySize(int keysize)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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,8 @@ import java.security.spec.*;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHGenParameterSpec;
import static sun.security.util.SecurityProviderConstants.DEF_DH_KEY_SIZE;
/*
* This class generates parameters for the Diffie-Hellman algorithm.
* The parameters are a prime, a base, and optionally the length in bits of
@ -38,7 +40,6 @@ import javax.crypto.spec.DHGenParameterSpec;
*
* <p>The Diffie-Hellman parameter generation accepts the size in bits of the
* prime modulus and the size in bits of the random exponent as input.
* The size of the prime modulus defaults to 2048 bits.
*
* @author Jan Luehe
*
@ -50,7 +51,7 @@ import javax.crypto.spec.DHGenParameterSpec;
public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
// The size in bits of the prime modulus
private int primeSize = 2048;
private int primeSize = DEF_DH_KEY_SIZE;
// The size in bits of the random exponent (private value)
private int exponentSize = 0;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2017, 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
@ -63,7 +63,8 @@ final class ISO10126Padding implements Padding {
if (in == null)
return;
if ((off + len) > in.length) {
int idx = Math.addExact(off, len);
if (idx > in.length) {
throw new ShortBufferException("Buffer too small to hold padding");
}
@ -71,7 +72,7 @@ final class ISO10126Padding implements Padding {
byte[] padding = new byte[len - 1];
SunJCE.getRandom().nextBytes(padding);
System.arraycopy(padding, 0, in, off, len - 1);
in[off + len - 1] = paddingOctet;
in[idx - 1] = paddingOctet;
return;
}
@ -94,14 +95,15 @@ final class ISO10126Padding implements Padding {
return 0;
}
byte lastByte = in[off + len - 1];
int idx = Math.addExact(off, len);
byte lastByte = in[idx - 1];
int padValue = (int)lastByte & 0x0ff;
if ((padValue < 0x01)
|| (padValue > blockSize)) {
return -1;
}
int start = off + len - padValue;
int start = idx - padValue;
if (start < off) {
return -1;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2017, 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,12 +27,14 @@ package com.sun.crypto.provider;
import java.io.*;
import java.util.*;
import java.security.AccessController;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PrivilegedAction;
import java.security.KeyStoreSpi;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
@ -835,11 +837,21 @@ public final class JceKeyStore extends KeyStoreSpi {
// read the sealed key
try {
ois = new ObjectInputStream(dis);
final ObjectInputStream ois2 = ois;
// Set a deserialization checker
AccessController.doPrivileged(
(PrivilegedAction<Void>)() -> {
ois2.setObjectInputFilter(
new DeserializationChecker());
return null;
});
entry.sealedKey = (SealedObject)ois.readObject();
// NOTE: don't close ois here since we are still
// using dis!!!
} catch (ClassNotFoundException cnfe) {
throw new IOException(cnfe.getMessage());
} catch (InvalidClassException ice) {
throw new IOException("Invalid secret key format");
}
// Add the entry to the list
@ -916,4 +928,34 @@ public final class JceKeyStore extends KeyStoreSpi {
return JCEKS_MAGIC == dataStream.readInt();
}
/*
* An ObjectInputFilter that checks the format of the secret key being
* deserialized.
*/
private static class DeserializationChecker implements ObjectInputFilter {
private static final int MAX_NESTED_DEPTH = 2;
@Override
public ObjectInputFilter.Status
checkInput(ObjectInputFilter.FilterInfo info) {
// First run a custom filter
long nestedDepth = info.depth();
if ((nestedDepth == 1 &&
info.serialClass() != SealedObjectForKeyProtector.class) ||
nestedDepth > MAX_NESTED_DEPTH) {
return Status.REJECTED;
}
// Next run the default filter, if available
ObjectInputFilter defaultFilter =
ObjectInputFilter.Config.getSerialFilter();
if (defaultFilter != null) {
return defaultFilter.checkInput(info);
}
return Status.UNDECIDED;
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2017, 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
@ -38,6 +38,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.AlgorithmParameters;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher;
@ -74,6 +75,8 @@ final class KeyProtector {
// keys in the keystore implementation that comes with JDK 1.2)
private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1";
private static final int MAX_ITERATION_COUNT = 5000000;
private static final int ITERATION_COUNT = 200000;
private static final int SALT_LEN = 20; // the salt length
private static final int DIGEST_LEN = 20;
@ -100,7 +103,7 @@ final class KeyProtector {
SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
// create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
@ -155,6 +158,9 @@ final class KeyProtector {
pbeParams.init(encodedParams);
PBEParameterSpec pbeSpec =
pbeParams.getParameterSpec(PBEParameterSpec.class);
if (pbeSpec.getIterationCount() > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
// create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
@ -285,7 +291,7 @@ final class KeyProtector {
SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
// create PBE key from password
PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password);
@ -326,6 +332,15 @@ final class KeyProtector {
throw new UnrecoverableKeyException("Cannot get " +
"algorithm parameters");
}
PBEParameterSpec pbeSpec;
try {
pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException("Invalid PBE algorithm parameters");
}
if (pbeSpec.getIterationCount() > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
PBEWithMD5AndTripleDESCipher cipherSpi;
cipherSpi = new PBEWithMD5AndTripleDESCipher();
Cipher cipher = new CipherForKeyProtector(cipherSpi,

View file

@ -1,535 +0,0 @@
/*
* Copyright (c) 2002, 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.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
/**
* This class represents password-based encryption as defined by the PKCS #5
* standard.
*
* @author Jan Luehe
*
*
* @see javax.crypto.Cipher
*/
final class PBECipherCore {
// the encapsulated DES cipher
private CipherCore cipher;
private MessageDigest md;
private int blkSize;
private String algo = null;
private byte[] salt = null;
private int iCount = 10;
/**
* Creates an instance of PBE Cipher using the specified CipherSpi
* instance.
*
*/
PBECipherCore(String cipherAlg) throws NoSuchAlgorithmException,
NoSuchPaddingException {
algo = cipherAlg;
if (algo.equals("DES")) {
cipher = new CipherCore(new DESCrypt(),
DESConstants.DES_BLOCK_SIZE);
} else if (algo.equals("DESede")) {
cipher = new CipherCore(new DESedeCrypt(),
DESConstants.DES_BLOCK_SIZE);
} else {
throw new NoSuchAlgorithmException("No Cipher implementation " +
"for PBEWithMD5And" + algo);
}
cipher.setMode("CBC");
cipher.setPadding("PKCS5Padding");
// get instance of MD5
md = MessageDigest.getInstance("MD5");
}
/**
* Sets the mode of this cipher. This algorithm can only be run in CBC
* mode.
*
* @param mode the cipher mode
*
* @exception NoSuchAlgorithmException if the requested cipher mode is
* invalid
*/
void setMode(String mode) throws NoSuchAlgorithmException {
cipher.setMode(mode);
}
/**
* Sets the padding mechanism of this cipher. This algorithm only uses
* PKCS #5 padding.
*
* @param padding the padding mechanism
*
* @exception NoSuchPaddingException if the requested padding mechanism
* is invalid
*/
void setPadding(String paddingScheme) throws NoSuchPaddingException {
cipher.setPadding(paddingScheme);
}
/**
* Returns the block size (in bytes).
*
* @return the block size (in bytes)
*/
int getBlockSize() {
return DESConstants.DES_BLOCK_SIZE;
}
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next <code>update</code> or
* <code>doFinal</code> operation, given the input length
* <code>inputLen</code> (in bytes).
*
* <p>This call takes into account any unprocessed (buffered) data from a
* previous <code>update</code> call, and padding.
*
* <p>The actual output length of the next <code>update</code> or
* <code>doFinal</code> call may be smaller than the length returned by
* this method.
*
* @param inputLen the input length (in bytes)
*
* @return the required output buffer size (in bytes)
*
*/
int getOutputSize(int inputLen) {
return cipher.getOutputSize(inputLen);
}
/**
* Returns the initialization vector (IV) in a new buffer.
*
* <p> This is useful in the case where a random IV has been created
* (see <a href = "#init">init</a>),
* or in the context of password-based encryption or
* decryption, where the IV is derived from a user-supplied password.
*
* @return the initialization vector in a new buffer, or null if the
* underlying algorithm does not use an IV, or if the IV has not yet
* been set.
*/
byte[] getIV() {
return cipher.getIV();
}
/**
* Returns the parameters used with this cipher.
*
* <p>The returned parameters may be the same that were used to initialize
* this cipher, or may contain the default set of parameters or a set of
* randomly generated parameters used by the underlying cipher
* implementation (provided that the underlying cipher implementation
* uses a default set of parameters or creates new parameters if it needs
* parameters but was not initialized with any).
*
* @return the parameters used with this cipher, or null if this cipher
* does not use any parameters.
*/
AlgorithmParameters getParameters() {
AlgorithmParameters params = null;
if (salt == null) {
salt = new byte[8];
SunJCE.getRandom().nextBytes(salt);
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
try {
params = AlgorithmParameters.getInstance("PBEWithMD5And" +
(algo.equalsIgnoreCase("DES")? "DES":"TripleDES"),
SunJCE.getInstance());
params.init(pbeSpec);
} catch (NoSuchAlgorithmException nsae) {
// should never happen
throw new RuntimeException("SunJCE called, but not configured");
} catch (InvalidParameterSpecException ipse) {
// should never happen
throw new RuntimeException("PBEParameterSpec not supported");
}
return params;
}
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness.
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
*
* <p>If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes, it will get them from <code>random</code>.
*
* @param opmode the operation mode of this cipher (this is one of
* the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param params the algorithm parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this cipher
*/
void init(int opmode, Key key, AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (((opmode == Cipher.DECRYPT_MODE) ||
(opmode == Cipher.UNWRAP_MODE)) && (params == null)) {
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
}
if ((key == null) ||
(key.getEncoded() == null) ||
!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
throw new InvalidKeyException("Missing password");
}
if (params == null) {
// create random salt and use default iteration count
salt = new byte[8];
random.nextBytes(salt);
} else {
if (!(params instanceof PBEParameterSpec)) {
throw new InvalidAlgorithmParameterException
("Wrong parameter type: PBE expected");
}
salt = ((PBEParameterSpec) params).getSalt();
// salt must be 8 bytes long (by definition)
if (salt.length != 8) {
throw new InvalidAlgorithmParameterException
("Salt must be 8 bytes long");
}
iCount = ((PBEParameterSpec) params).getIterationCount();
if (iCount <= 0) {
throw new InvalidAlgorithmParameterException
("IterationCount must be a positive number");
}
}
byte[] derivedKey = deriveCipherKey(key);
// use all but the last 8 bytes as the key value
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
derivedKey.length-8, algo);
// use the last 8 bytes as the IV
IvParameterSpec ivSpec = new IvParameterSpec(derivedKey,
derivedKey.length-8,
8);
// initialize the underlying cipher
cipher.init(opmode, cipherKey, ivSpec, random);
}
private byte[] deriveCipherKey(Key key) {
byte[] result = null;
byte[] passwdBytes = key.getEncoded();
if (algo.equals("DES")) {
// P || S (password concatenated with salt)
byte[] concat = new byte[passwdBytes.length + salt.length];
System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
java.util.Arrays.fill(passwdBytes, (byte)0x00);
System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
// digest P || S with c iterations
byte[] toBeHashed = concat;
for (int i = 0; i < iCount; i++) {
md.update(toBeHashed);
toBeHashed = md.digest(); // this resets the digest
}
java.util.Arrays.fill(concat, (byte)0x00);
result = toBeHashed;
} else if (algo.equals("DESede")) {
// if the 2 salt halves are the same, invert one of them
int i;
for (i=0; i<4; i++) {
if (salt[i] != salt[i+4])
break;
}
if (i==4) { // same, invert 1st half
for (i=0; i<2; i++) {
byte tmp = salt[i];
salt[i] = salt[3-i];
salt[3-1] = tmp;
}
}
// Now digest each half (concatenated with password). For each
// half, go through the loop as many times as specified by the
// iteration count parameter (inner for loop).
// Concatenate the output from each digest round with the
// password, and use the result as the input to the next digest
// operation.
byte[] kBytes = null;
IvParameterSpec iv = null;
byte[] toBeHashed = null;
result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
DESConstants.DES_BLOCK_SIZE];
for (i = 0; i < 2; i++) {
toBeHashed = new byte[salt.length/2];
System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0,
toBeHashed.length);
for (int j=0; j < iCount; j++) {
md.update(toBeHashed);
md.update(passwdBytes);
toBeHashed = md.digest(); // this resets the digest
}
System.arraycopy(toBeHashed, 0, result, i*16,
toBeHashed.length);
}
}
return result;
}
void init(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
PBEParameterSpec pbeSpec = null;
if (params != null) {
try {
pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new InvalidAlgorithmParameterException("Wrong parameter "
+ "type: PBE "
+ "expected");
}
}
init(opmode, key, pbeSpec, random);
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code>, are processed, and the
* result is stored in a new buffer.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
*
* @return the new buffer with the result
*
*/
byte[] update(byte[] input, int inputOffset, int inputLen) {
return cipher.update(input, inputOffset, inputLen);
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code>, are processed, and the
* result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code>.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception ShortBufferException if the given output buffer is too small
* to hold the result
*/
int update(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset)
throws ShortBufferException {
return cipher.update(input, inputOffset, inputLen,
output, outputOffset);
}
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code>, and any input bytes that
* may have been buffered during a previous <code>update</code> operation,
* are processed, with padding (if requested) being applied.
* The result is stored in a new buffer.
*
* <p>The cipher is reset to its initial state (uninitialized) after this
* call.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
*
* @return the new buffer with the result
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested (only in encryption mode), and the total
* input length of the data processed by this cipher is not a multiple of
* block size
* @exception BadPaddingException if decrypting and padding is chosen,
* but the last input data does not have proper padding bytes.
*/
byte[] doFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
return cipher.doFinal(input, inputOffset, inputLen);
}
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code>, and any input bytes that
* may have been buffered during a previous <code>update</code> operation,
* are processed, with padding (if requested) being applied.
* The result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code>.
*
* <p>The cipher is reset to its initial state (uninitialized) after this
* call.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested (only in encryption mode), and the total
* input length of the data processed by this cipher is not a multiple of
* block size
* @exception ShortBufferException if the given output buffer is too small
* to hold the result
* @exception BadPaddingException if decrypting and padding is chosen,
* but the last input data does not have proper padding bytes.
*/
int doFinal(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset)
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
return cipher.doFinal(input, inputOffset, inputLen,
output, outputOffset);
}
/**
* 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).
*/
byte[] wrap(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 = doFinal(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 NoSuchAlgorithmException if no installed providers
* can create keys of type <code>wrappedKeyType</code> for the
* <code>wrappedKeyAlgorithm</code>.
*
* @exception InvalidKeyException if <code>wrappedKey</code> does not
* represent a wrapped key of type <code>wrappedKeyType</code> for
* the <code>wrappedKeyAlgorithm</code>.
*/
Key unwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException {
byte[] encodedKey;
try {
encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
} catch (BadPaddingException ePadding) {
throw new InvalidKeyException("The wrapped key is not padded " +
"correctly");
} catch (IllegalBlockSizeException eBlockSize) {
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) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, 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
@ -260,7 +260,7 @@ final class PBES1Core {
if (algo.equals("DES")) {
// P || S (password concatenated with salt)
byte[] concat = new byte[passwdBytes.length + salt.length];
byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
java.util.Arrays.fill(passwdBytes, (byte)0x00);
System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
@ -284,7 +284,7 @@ final class PBES1Core {
for (i=0; i<2; i++) {
byte tmp = salt[i];
salt[i] = salt[3-i];
salt[3-1] = tmp;
salt[3-i] = tmp;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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 javax.crypto.ShortBufferException;
import java.util.Arrays;
/**
* This class implements padding as specified in the PKCS#5 standard.
@ -63,14 +64,13 @@ final class PKCS5Padding implements Padding {
if (in == null)
return;
if ((off + len) > in.length) {
int idx = Math.addExact(off, len);
if (idx > in.length) {
throw new ShortBufferException("Buffer too small to hold padding");
}
byte paddingOctet = (byte) (len & 0xff);
for (int i = 0; i < len; i++) {
in[i + off] = paddingOctet;
}
Arrays.fill(in, off, idx, paddingOctet);
return;
}
@ -92,25 +92,24 @@ final class PKCS5Padding implements Padding {
(len == 0)) { // this can happen if input is really a padded buffer
return 0;
}
byte lastByte = in[off + len - 1];
int idx = Math.addExact(off, len);
byte lastByte = in[idx - 1];
int padValue = (int)lastByte & 0x0ff;
if ((padValue < 0x01)
|| (padValue > blockSize)) {
return -1;
}
int start = off + len - ((int)lastByte & 0x0ff);
int start = idx - padValue;
if (start < off) {
return -1;
}
for (int i = 0; i < ((int)lastByte & 0x0ff); i++) {
if (in[start+i] != lastByte) {
for (int i = start; i < idx; i++) {
if (in[i] != lastByte) {
return -1;
}
}
return start;
}

View file

@ -38,6 +38,7 @@ package com.sun.net.ssl.internal.www.protocol.https;
import java.net.URL;
import java.net.Proxy;
import java.net.ProtocolException;
import java.net.MalformedURLException;
import java.io.*;
import java.net.Authenticator;
import javax.net.ssl.*;
@ -78,10 +79,18 @@ public class HttpsURLConnectionOldImpl
this(u, null, handler);
}
static URL checkURL(URL u) throws IOException {
if (u != null) {
if (u.toExternalForm().indexOf('\n') > -1) {
throw new MalformedURLException("Illegal character in URL");
}
}
return u;
}
// For both copies of the file, uncomment one line and comment the other
// HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
super(u);
super(checkURL(u));
delegate = new DelegateHttpsURLConnection(url, p, handler, this);
}

View file

@ -44,7 +44,6 @@ import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
import jdk.internal.misc.ObjectStreamClassValidator;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.Unsafe;
import sun.reflect.misc.ReflectUtil;
@ -1282,6 +1281,33 @@ public class ObjectInputStream
}
}
/**
* Checks the given array type and length to ensure that creation of such
* an array is permitted by this ObjectInputStream. The arrayType argument
* must represent an actual array type.
*
* This private method is called via SharedSecrets.
*
* @param arrayType the array type
* @param arrayLength the array length
* @throws NullPointerException if arrayType is null
* @throws IllegalArgumentException if arrayType isn't actually an array type
* @throws NegativeArraySizeException if arrayLength is negative
* @throws InvalidClassException if the filter rejects creation
*/
private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
Objects.requireNonNull(arrayType);
if (! arrayType.isArray()) {
throw new IllegalArgumentException("not an array type");
}
if (arrayLength < 0) {
throw new NegativeArraySizeException();
}
filterCheck(arrayType, arrayLength);
}
/**
* Provide access to the persistent fields read from the input stream.
*/
@ -1740,9 +1766,6 @@ public class ObjectInputStream
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
if (descriptor != null) {
validateDescriptor(descriptor);
}
return descriptor;
}
@ -1770,6 +1793,10 @@ public class ObjectInputStream
passHandle = NULL_HANDLE;
int numIfaces = bin.readInt();
if (numIfaces > 65535) {
throw new InvalidObjectException("interface limit exceeded: "
+ numIfaces);
}
String[] ifaces = new String[numIfaces];
for (int i = 0; i < numIfaces; i++) {
ifaces[i] = bin.readUTF();
@ -3978,20 +4005,8 @@ public class ObjectInputStream
}
}
private void validateDescriptor(ObjectStreamClass descriptor) {
ObjectStreamClassValidator validating = validator;
if (validating != null) {
validating.validateDescriptor(descriptor);
}
}
// controlled access to ObjectStreamClassValidator
private volatile ObjectStreamClassValidator validator;
private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
ois.validator = validator;
}
static {
SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
}
}

View file

@ -32,14 +32,19 @@ import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -53,7 +58,8 @@ import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
import sun.reflect.misc.ReflectUtil;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaSecurityAccess;
import static java.io.ObjectStreamField.*;
/**
@ -176,6 +182,9 @@ public class ObjectStreamClass implements Serializable {
/** serialization-appropriate constructor, or null if none */
private Constructor<?> cons;
/** protection domains that need to be checked when calling the constructor */
private ProtectionDomain[] domains;
/** class-defined writeObject method, or null if none */
private Method writeObjectMethod;
/** class-defined readObject method, or null if none */
@ -508,6 +517,7 @@ public class ObjectStreamClass implements Serializable {
cl, "readObjectNoData", null, Void.TYPE);
hasWriteObjectData = (writeObjectMethod != null);
}
domains = getProtectionDomains(cons, cl);
writeReplaceMethod = getInheritableMethod(
cl, "writeReplace", null, Object.class);
readResolveMethod = getInheritableMethod(
@ -550,6 +560,65 @@ public class ObjectStreamClass implements Serializable {
ObjectStreamClass() {
}
/**
* Creates a PermissionDomain that grants no permission.
*/
private ProtectionDomain noPermissionsDomain() {
PermissionCollection perms = new Permissions();
perms.setReadOnly();
return new ProtectionDomain(null, perms);
}
/**
* Aggregate the ProtectionDomains of all the classes that separate
* a concrete class {@code cl} from its ancestor's class declaring
* a constructor {@code cons}.
*
* If {@code cl} is defined by the boot loader, or the constructor
* {@code cons} is declared by {@code cl}, or if there is no security
* manager, then this method does nothing and {@code null} is returned.
*
* @param cons A constructor declared by {@code cl} or one of its
* ancestors.
* @param cl A concrete class, which is either the class declaring
* the constructor {@code cons}, or a serializable subclass
* of that class.
* @return An array of ProtectionDomain representing the set of
* ProtectionDomain that separate the concrete class {@code cl}
* from its ancestor's declaring {@code cons}, or {@code null}.
*/
private ProtectionDomain[] getProtectionDomains(Constructor<?> cons,
Class<?> cl) {
ProtectionDomain[] domains = null;
if (cons != null && cl.getClassLoader() != null
&& System.getSecurityManager() != null) {
Class<?> cls = cl;
Class<?> fnscl = cons.getDeclaringClass();
Set<ProtectionDomain> pds = null;
while (cls != fnscl) {
ProtectionDomain pd = cls.getProtectionDomain();
if (pd != null) {
if (pds == null) pds = new HashSet<>();
pds.add(pd);
}
cls = cls.getSuperclass();
if (cls == null) {
// that's not supposed to happen
// make a ProtectionDomain with no permission.
// should we throw instead?
if (pds == null) pds = new HashSet<>();
else pds.clear();
pds.add(noPermissionsDomain());
break;
}
}
if (pds != null) {
domains = pds.toArray(new ProtectionDomain[0]);
}
}
return domains;
}
/**
* Initializes class descriptor representing a proxy class.
*/
@ -580,6 +649,7 @@ public class ObjectStreamClass implements Serializable {
writeReplaceMethod = localDesc.writeReplaceMethod;
readResolveMethod = localDesc.readResolveMethod;
deserializeEx = localDesc.deserializeEx;
domains = localDesc.domains;
cons = localDesc.cons;
}
fieldRefl = getReflector(fields, localDesc);
@ -666,6 +736,7 @@ public class ObjectStreamClass implements Serializable {
if (deserializeEx == null) {
deserializeEx = localDesc.deserializeEx;
}
domains = localDesc.domains;
cons = localDesc.cons;
}
@ -1006,7 +1077,35 @@ public class ObjectStreamClass implements Serializable {
requireInitialized();
if (cons != null) {
try {
return cons.newInstance();
if (domains == null || domains.length == 0) {
return cons.newInstance();
} else {
JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess();
PrivilegedAction<?> pea = () -> {
try {
return cons.newInstance();
} catch (InstantiationException
| InvocationTargetException
| IllegalAccessException x) {
throw new UndeclaredThrowableException(x);
}
}; // Can't use PrivilegedExceptionAction with jsa
try {
return jsa.doIntersectionPrivilege(pea,
AccessController.getContext(),
new AccessControlContext(domains));
} catch (UndeclaredThrowableException x) {
Throwable cause = x.getCause();
if (cause instanceof InstantiationException)
throw (InstantiationException) cause;
if (cause instanceof InvocationTargetException)
throw (InvocationTargetException) cause;
if (cause instanceof IllegalAccessException)
throw (IllegalAccessException) cause;
// not supposed to happen
throw x;
}
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
throw new InternalError(ex);

View file

@ -35,6 +35,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.*;
import sun.net.util.URLUtil;
import sun.security.util.IOUtils;
/**
*
@ -571,6 +572,8 @@ public class CodeSource implements java.io.Serializable {
// could all be present in the stream at the same time
cfs = new Hashtable<>(3);
certList = new ArrayList<>(size > 20 ? 20 : size);
} else if (size < 0) {
throw new IOException("size cannot be negative");
}
for (int i = 0; i < size; i++) {
@ -592,13 +595,7 @@ public class CodeSource implements java.io.Serializable {
cfs.put(certType, cf);
}
// parse the certificate
byte[] encoded = null;
try {
encoded = new byte[ois.readInt()];
} catch (OutOfMemoryError oome) {
throw new IOException("Certificate too big");
}
ois.readFully(encoded);
byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
try {
certList.add(cf.generateCertificate(bais));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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,16 @@
package java.security;
import sun.security.util.IOUtils;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Hashtable;
import java.lang.reflect.*;
import java.security.cert.*;
import java.util.List;
/**
* The UnresolvedPermission class is used to hold Permissions that
@ -550,6 +554,7 @@ implements java.io.Serializable
{
CertificateFactory cf;
Hashtable<String, CertificateFactory> cfs = null;
List<Certificate> certList = null;
ois.defaultReadObject();
@ -562,7 +567,9 @@ implements java.io.Serializable
// we know of 3 different cert types: X.509, PGP, SDSI, which
// could all be present in the stream at the same time
cfs = new Hashtable<>(3);
this.certs = new java.security.cert.Certificate[size];
certList = new ArrayList<>(size > 20 ? 20 : size);
} else if (size < 0) {
throw new IOException("size cannot be negative");
}
for (int i=0; i<size; i++) {
@ -584,20 +591,18 @@ implements java.io.Serializable
cfs.put(certType, cf);
}
// parse the certificate
byte[] encoded=null;
try {
encoded = new byte[ois.readInt()];
} catch (OutOfMemoryError oome) {
throw new IOException("Certificate too big");
}
ois.readFully(encoded);
byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
try {
this.certs[i] = cf.generateCertificate(bais);
certList.add(cf.generateCertificate(bais));
} catch (CertificateException ce) {
throw new IOException(ce.getMessage());
}
bais.close();
}
if (certList != null) {
this.certs = certList.toArray(
new java.security.cert.Certificate[size]);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2017, 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
@ -34,6 +34,7 @@ import java.util.HashMap;
import java.util.Map;
import javax.security.auth.x500.X500Principal;
import sun.security.util.IOUtils;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.InvalidityDateExtension;
@ -230,17 +231,17 @@ public class CertificateRevokedException extends CertificateException {
int size = ois.readInt();
if (size == 0) {
extensions = Collections.emptyMap();
} else if (size < 0) {
throw new IOException("size cannot be negative");
} else {
extensions = new HashMap<>(size);
extensions = new HashMap<>(size > 20 ? 20 : size);
}
// Read in the extensions and put the mappings in the extensions map
for (int i = 0; i < size; i++) {
String oid = (String) ois.readObject();
boolean critical = ois.readBoolean();
int length = ois.readInt();
byte[] extVal = new byte[length];
ois.readFully(extVal);
byte[] extVal = IOUtils.readNBytes(ois, ois.readInt());
Extension ext = sun.security.x509.Extension.newExtension
(new ObjectIdentifier(oid), critical, extVal);
extensions.put(oid, ext);

View file

@ -38,6 +38,7 @@ import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import jdk.internal.misc.SharedSecrets;
/**
* Resizable-array implementation of the {@link Deque} interface. Array
@ -1194,6 +1195,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
// Read in size and allocate array
int size = s.readInt();
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size + 1);
elements = new Object[size + 1];
this.tail = size;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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 java.util;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import jdk.internal.misc.SharedSecrets;
/**
* Resizable-array implementation of the {@code List} interface. Implements
@ -814,6 +815,7 @@ public class ArrayList<E> extends AbstractList<E>
if (size > 0) {
// like clone(), allocate array based upon size not capacity
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
Object[] elements = new Object[size];
// Read in all elements in the proper order.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -34,6 +34,7 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import jdk.internal.misc.SharedSecrets;
/**
* Hash table based implementation of the {@code Map} interface. This
@ -1448,6 +1449,10 @@ public class HashMap<K,V> extends AbstractMap<K,V>
float ft = (float)cap * lf;
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);
// Check Map.Entry[].class since it's the nearest public type to
// what we're actually creating.
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, cap);
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
table = tab;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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 java.util;
import java.io.InvalidObjectException;
import jdk.internal.misc.SharedSecrets;
/**
* This class implements the {@code Set} interface, backed by a hash table
@ -322,6 +323,13 @@ public class HashSet<E>
capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
HashMap.MAXIMUM_CAPACITY);
// Constructing the backing map will lazily create an array when the first element is
// added, so check it before construction. Call HashMap.tableSizeFor to compute the
// actual allocation size. Check Map.Entry[].class since it's the nearest public type to
// what is actually created.
SharedSecrets.getJavaObjectInputStreamAccess()
.checkArray(s, Map.Entry[].class, HashMap.tableSizeFor(capacity));
// Create backing HashMap
map = (((HashSet<?>)this) instanceof LinkedHashSet ?
new LinkedHashMap<>(capacity, loadFactor) :

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2017, 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.io.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
import jdk.internal.misc.SharedSecrets;
/**
* This class implements a hash table, which maps keys to values. Any
@ -1291,6 +1292,10 @@ public class Hashtable<K,V>
if (length > elements && (length & 1) == 0)
length--;
length = Math.min(length, origlength);
// Check Map.Entry[].class since it's the nearest public type to
// what we're actually creating.
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, length);
table = new Entry<?,?>[length];
threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
count = 0;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, 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.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import jdk.internal.misc.SharedSecrets;
/**
* This class implements the {@code Map} interface with a hash table, using
@ -1304,7 +1305,9 @@ public class IdentityHashMap<K,V>
if (size < 0)
throw new java.io.StreamCorruptedException
("Illegal mappings count: " + size);
init(capacity(size));
int cap = capacity(size);
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, cap);
init(cap);
// Read the keys and values, and put the mappings in the table
for (int i=0; i<size; i++) {

View file

@ -35,6 +35,7 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.vm.annotation.Stable;
/**
@ -885,6 +886,7 @@ final class CollSer implements Serializable {
throw new InvalidObjectException("negative length " + len);
}
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(ois, Object[].class, len);
Object[] a = new Object[len];
for (int i = 0; i < len; i++) {
a[i] = ois.readObject();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2017, 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 java.util;
import java.util.function.Consumer;
import jdk.internal.misc.SharedSecrets;
/**
* An unbounded priority {@linkplain Queue queue} based on a priority heap.
@ -795,6 +796,7 @@ public class PriorityQueue<E> extends AbstractQueue<E>
// Read in (and discard) array length
s.readInt();
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
queue = new Object[size];
// Read in all elements.

View file

@ -42,6 +42,7 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.util.xml.PropertiesDefaultHandler;
/**
@ -1441,6 +1442,16 @@ class Properties extends Hashtable<Object,Object> {
throw new StreamCorruptedException("Illegal # of Elements: " + elements);
}
// Constructing the backing map will lazily create an array when the first element is
// added, so check it before construction. Note that CHM's constructor takes a size
// that is the number of elements to be stored -- not the table size -- so it must be
// inflated by the default load factor of 0.75, then inflated to the next power of two.
// (CHM uses the same power-of-two computation as HashMap, and HashMap.tableSizeFor is
// accessible here.) Check Map.Entry[].class since it's the nearest public type to
// what is actually created.
SharedSecrets.getJavaObjectInputStreamAccess()
.checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75)));
// create CHM of appropriate capacity
map = new ConcurrentHashMap<>(elements);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -41,6 +41,7 @@ package java.util;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import sun.util.calendar.CalendarSystem;
import sun.util.calendar.CalendarUtils;
import sun.util.calendar.BaseCalendar;
@ -1278,6 +1279,9 @@ public class SimpleTimeZone extends TimeZone {
*/
private int serialVersionOnStream = currentSerialVersion;
// Maximum number of rules.
private static final int MAX_RULE_NUM = 6;
private synchronized void invalidateCache() {
cacheYear = startYear - 1;
cacheStart = cacheEnd = 0;
@ -1569,7 +1573,7 @@ public class SimpleTimeZone extends TimeZone {
*/
private byte[] packRules()
{
byte[] rules = new byte[6];
byte[] rules = new byte[MAX_RULE_NUM];
rules[0] = (byte)startDay;
rules[1] = (byte)startDayOfWeek;
rules[2] = (byte)endDay;
@ -1594,7 +1598,7 @@ public class SimpleTimeZone extends TimeZone {
endDayOfWeek = rules[3];
// As of serial version 2, include time modes
if (rules.length >= 6) {
if (rules.length >= MAX_RULE_NUM) {
startTimeMode = rules[4];
endTimeMode = rules[5];
}
@ -1691,9 +1695,13 @@ public class SimpleTimeZone extends TimeZone {
// store the actual rules (which have not be made compatible with 1.1)
// in the optional area. Read them in here and parse them.
int length = stream.readInt();
byte[] rules = new byte[length];
stream.readFully(rules);
unpackRules(rules);
if (length <= MAX_RULE_NUM) {
byte[] rules = new byte[length];
stream.readFully(rules);
unpackRules(rules);
} else {
throw new InvalidObjectException("Too many rules: " + length);
}
}
if (serialVersionOnStream >= 2) {

View file

@ -51,6 +51,7 @@ import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import jdk.internal.misc.SharedSecrets;
/**
* A thread-safe variant of {@link java.util.ArrayList} in which all mutative
@ -933,6 +934,7 @@ public class CopyOnWriteArrayList<E>
// Read in array length and allocate array
int len = s.readInt();
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len);
Object[] elements = new Object[len];
// Read in all elements in the proper order.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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,17 +25,14 @@
package jdk.internal.misc;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
/**
* The interface to specify methods for accessing {@code ObjectInputStream}
* @author sjiang
* Interface to specify methods for accessing {@code ObjectInputStream}.
*/
@FunctionalInterface
public interface JavaObjectInputStreamAccess {
/**
* Sets a descriptor validating.
* @param ois stream to have the descriptors validated
* @param validator validator used to validate a descriptor.
*/
public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator);
void checkArray(ObjectInputStream ois, Class<?> arrayType, int arrayLength)
throws InvalidClassException;
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2016, 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.misc;
import java.io.ObjectStreamClass;
/**
* A callback used by {@code ObjectInputStream} to do descriptor validation.
*
* @author sjiang
*/
public interface ObjectStreamClassValidator {
/**
* This method will be called by ObjectInputStream to
* check a descriptor just before creating an object described by this descriptor.
* The object will not be created if this method throws a {@code RuntimeException}.
* @param descriptor descriptor to be checked.
*/
public void validateDescriptor(ObjectStreamClass descriptor);
}

View file

@ -115,8 +115,8 @@ public class FtpClient extends sun.net.ftp.FtpClient {
new PrivilegedAction<Object>() {
public Object run() {
vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue();
vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue();
vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 300_000).intValue();
vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 300_000).intValue();
encs[0] = System.getProperty("file.encoding", "ISO8859_1");
return null;
}

View file

@ -843,18 +843,36 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
this(u, null, handler);
}
public HttpURLConnection(URL u, String host, int port) {
this(u, new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(host, port)));
private static String checkHost(String h) throws IOException {
if (h != null) {
if (h.indexOf('\n') > -1) {
throw new MalformedURLException("Illegal character in host");
}
}
return h;
}
public HttpURLConnection(URL u, String host, int port) throws IOException {
this(u, new Proxy(Proxy.Type.HTTP,
InetSocketAddress.createUnresolved(checkHost(host), port)));
}
/** this constructor is used by other protocol handlers such as ftp
that want to use http to fetch urls on their behalf.*/
public HttpURLConnection(URL u, Proxy p) {
public HttpURLConnection(URL u, Proxy p) throws IOException {
this(u, p, new Handler());
}
protected HttpURLConnection(URL u, Proxy p, Handler handler) {
super(u);
private static URL checkURL(URL u) throws IOException {
if (u != null) {
if (u.toExternalForm().indexOf('\n') > -1) {
throw new MalformedURLException("Illegal character in URL");
}
}
return u;
}
protected HttpURLConnection(URL u, Proxy p, Handler handler)
throws IOException {
super(checkURL(u));
requests = new MessageHeader();
responses = new MessageHeader();
userHeaders = new MessageHeader();

View file

@ -38,6 +38,7 @@ package sun.net.www.protocol.https;
import java.net.URL;
import java.net.Proxy;
import java.net.ProtocolException;
import java.net.MalformedURLException;
import java.io.*;
import java.net.Authenticator;
import javax.net.ssl.*;
@ -80,10 +81,18 @@ public class HttpsURLConnectionImpl
this(u, null, handler);
}
static URL checkURL(URL u) throws IOException {
if (u != null) {
if (u.toExternalForm().indexOf('\n') > -1) {
throw new MalformedURLException("Illegal character in URL");
}
}
return u;
}
// For both copies of the file, uncomment one line and comment the other
HttpsURLConnectionImpl(URL u, Proxy p, Handler handler) throws IOException {
// HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
super(u);
super(checkURL(u));
delegate = new DelegateHttpsURLConnection(url, p, handler, this);
}

View file

@ -46,6 +46,7 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
@ -147,6 +148,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
"keystore.PKCS12.keyProtectionAlgorithm"
};
private static final int MAX_ITERATION_COUNT = 5000000;
private static final int PBE_ITERATION_COUNT = 50000; // default
private static final int MAC_ITERATION_COUNT = 100000; // default
private static final int SALT_LEN = 20;
// friendlyName, localKeyId, trustedKeyUsage
private static final String[] CORE_ATTRIBUTES = {
"1.2.840.113549.1.9.20",
@ -192,8 +198,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
private static ObjectIdentifier[] AnyUsage;
private int counter = 0;
private static final int iterationCount = 1024;
private static final int SALT_LEN = 20;
// private key count
// Note: This is a workaround to allow null localKeyID attribute
@ -327,6 +331,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
byte[] encryptedKey;
AlgorithmParameters algParams;
ObjectIdentifier algOid;
try {
// get the encrypted private key
EncryptedPrivateKeyInfo encrInfo =
@ -347,7 +352,24 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
throw uke;
}
try {
try {
PBEParameterSpec pbeSpec;
int ic = 0;
if (algParams != null) {
try {
pbeSpec =
algParams.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException("Invalid PBE algorithm parameters");
}
ic = pbeSpec.getIterationCount();
if (ic > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
}
byte[] keyInfo;
while (true) {
try {
@ -387,9 +409,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
key = kfac.generatePrivate(kspec);
if (debug != null) {
debug.println("Retrieved a protected private key (" +
key.getClass().getName() + ") at alias '" + alias +
"'");
debug.println("Retrieved a protected private key at alias" +
" '" + alias + "' (" +
new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
}
// decode secret key
@ -410,9 +433,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
}
if (debug != null) {
debug.println("Retrieved a protected secret key (" +
key.getClass().getName() + ") at alias '" + alias +
"'");
debug.println("Retrieved a protected secret key at alias " +
"'" + alias + "' (" +
new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
}
}
} catch (Exception e) {
@ -590,9 +614,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
(key.getFormat().equals("PKCS8"))) {
if (debug != null) {
debug.println("Setting a protected private key (" +
key.getClass().getName() + ") at alias '" + alias +
"'");
debug.println(
"Setting a protected private key at alias '" +
alias + "'");
}
// Encrypt the private key
@ -638,9 +662,8 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
if (debug != null) {
debug.println("Setting a protected secret key (" +
key.getClass().getName() + ") at alias '" + alias +
"'");
debug.println("Setting a protected secret key at alias '" +
alias + "'");
}
secretKeyCount++;
entry = keyEntry;
@ -761,19 +784,19 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
/*
* Generate PBE Algorithm Parameters
*/
private AlgorithmParameters getAlgorithmParameters(String algorithm)
private AlgorithmParameters getPBEAlgorithmParameters(String algorithm)
throws IOException
{
AlgorithmParameters algParams = null;
// create PBE parameters from salt and iteration count
PBEParameterSpec paramSpec =
new PBEParameterSpec(getSalt(), iterationCount);
new PBEParameterSpec(getSalt(), PBE_ITERATION_COUNT);
try {
algParams = AlgorithmParameters.getInstance(algorithm);
algParams.init(paramSpec);
} catch (Exception e) {
throw new IOException("getAlgorithmParameters failed: " +
throw new IOException("getPBEAlgorithmParameters failed: " +
e.getMessage(), e);
}
return algParams;
@ -859,7 +882,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
algParams = AlgorithmParameters.getInstance(algorithm);
algParams.init(algParamSpec);
} else {
algParams = getAlgorithmParameters(algorithm);
algParams = getPBEAlgorithmParameters(algorithm);
}
} else {
// Check default key protection algorithm for PKCS12 keystores
@ -879,7 +902,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (algorithm == null || algorithm.isEmpty()) {
algorithm = "PBEWithSHA1AndDESede";
}
algParams = getAlgorithmParameters(algorithm);
algParams = getPBEAlgorithmParameters(algorithm);
}
ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm);
@ -1194,7 +1217,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) {
debug.println("Storing " + (privateKeyCount + secretKeyCount) +
" protected key(s) in a PKCS#7 data content-type");
" protected key(s) in a PKCS#7 data");
}
byte[] safeContentData = createSafeContent();
@ -1207,7 +1230,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) {
debug.println("Storing " + certificateCount +
" certificate(s) in a PKCS#7 encryptedData content-type");
" certificate(s) in a PKCS#7 encryptedData");
}
byte[] encrData = createEncryptedData(password);
@ -1478,7 +1501,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// generate MAC (MAC key is generated within JCE)
Mac m = Mac.getInstance("HmacPBESHA1");
PBEParameterSpec params =
new PBEParameterSpec(salt, iterationCount);
new PBEParameterSpec(salt, MAC_ITERATION_COUNT);
SecretKey key = getPBEKey(passwd);
m.init(key, params);
m.update(data);
@ -1486,7 +1509,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// encode as MacData
MacData macData = new MacData(algName, macResult, salt,
iterationCount);
MAC_ITERATION_COUNT);
DerOutputStream bytes = new DerOutputStream();
bytes.write(macData.getEncoded());
mData = bytes.toByteArray();
@ -1878,7 +1901,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// create AlgorithmParameters
AlgorithmParameters algParams =
getAlgorithmParameters("PBEWithSHA1AndRC2_40");
getPBEAlgorithmParameters("PBEWithSHA1AndRC2_40");
DerOutputStream bytes = new DerOutputStream();
AlgorithmId algId =
new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams);
@ -1998,7 +2021,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (contentType.equals(ContentInfo.DATA_OID)) {
if (debug != null) {
debug.println("Loading PKCS#7 data content-type");
debug.println("Loading PKCS#7 data");
}
safeContentsData = safeContents.getData();
@ -2007,15 +2030,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) {
debug.println("Warning: skipping PKCS#7 encryptedData" +
" content-type - no password was supplied");
" - no password was supplied");
}
continue;
}
if (debug != null) {
debug.println("Loading PKCS#7 encryptedData content-type");
}
DerInputStream edi =
safeContents.getContent().toDerInputStream();
int edVersion = edi.getInteger();
@ -2036,6 +2055,30 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
ObjectIdentifier algOid = in.getOID();
AlgorithmParameters algParams = parseAlgParameters(algOid, in);
PBEParameterSpec pbeSpec;
int ic = 0;
if (algParams != null) {
try {
pbeSpec =
algParams.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
throw new IOException(
"Invalid PBE algorithm parameters");
}
ic = pbeSpec.getIterationCount();
if (ic > MAX_ITERATION_COUNT) {
throw new IOException("PBE iteration count too large");
}
}
if (debug != null) {
debug.println("Loading PKCS#7 encryptedData " +
"(" + new AlgorithmId(algOid).getName() +
" iterations: " + ic + ")");
}
while (true) {
try {
// Use JCE
@ -2066,8 +2109,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// The MacData is optional.
if (password != null && s.available() > 0) {
MacData macData = new MacData(s);
try {
MacData macData = new MacData(s);
int ic = macData.getIterations();
try {
if (ic > MAX_ITERATION_COUNT) {
throw new InvalidAlgorithmParameterException(
"MAC iteration count too large: " + ic);
}
String algName =
macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
@ -2077,8 +2127,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
// generate MAC (MAC key is created within JCE)
Mac m = Mac.getInstance("HmacPBE" + algName);
PBEParameterSpec params =
new PBEParameterSpec(macData.getSalt(),
macData.getIterations());
new PBEParameterSpec(macData.getSalt(), ic);
SecretKey key = getPBEKey(password);
m.init(key, params);
m.update(authSafeData);
@ -2086,16 +2135,16 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
if (debug != null) {
debug.println("Checking keystore integrity " +
"(MAC algorithm: " + m.getAlgorithm() + ")");
"(" + m.getAlgorithm() + " iterations: " + ic + ")");
}
if (!MessageDigest.isEqual(macData.getDigest(), macResult)) {
throw new UnrecoverableKeyException("Failed PKCS12" +
" integrity checking");
}
} catch (Exception e) {
} catch (Exception e) {
throw new IOException("Integrity check failed: " + e, e);
}
}
}
/*

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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,8 @@ import java.security.spec.InvalidParameterSpecException;
import java.security.spec.DSAParameterSpec;
import sun.security.jca.JCAUtil;
import static sun.security.util.SecurityProviderConstants.DEF_DSA_KEY_SIZE;
import static sun.security.util.SecurityProviderConstants.getDefDSASubprimeSize;
/**
* This class generates DSA key parameters and public/private key
@ -45,15 +47,14 @@ import sun.security.jca.JCAUtil;
* @author Andreas Sterbenz
*
*/
public class DSAKeyPairGenerator extends KeyPairGenerator
implements java.security.interfaces.DSAKeyPairGenerator {
class DSAKeyPairGenerator extends KeyPairGenerator {
/* Length for prime P and subPrime Q in bits */
private int plen;
private int qlen;
/* whether to force new parameters to be generated for each KeyPair */
private boolean forceNewParameters;
boolean forceNewParameters;
/* preset algorithm parameters. */
private DSAParameterSpec params;
@ -61,9 +62,9 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
/* The source of random bits to use */
private SecureRandom random;
public DSAKeyPairGenerator() {
DSAKeyPairGenerator(int defaultKeySize) {
super("DSA");
initialize(1024, null);
initialize(defaultKeySize, null);
}
private static void checkStrength(int sizeP, int sizeQ) {
@ -84,61 +85,7 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
}
public void initialize(int modlen, SecureRandom random) {
// generate new parameters when no precomputed ones available.
initialize(modlen, true, random);
this.forceNewParameters = false;
}
/**
* Initializes the DSA key pair generator. If <code>genParams</code>
* is false, a set of pre-computed parameters is used.
*/
@Override
public void initialize(int modlen, boolean genParams, SecureRandom random)
throws InvalidParameterException {
int subPrimeLen = -1;
if (modlen <= 1024) {
subPrimeLen = 160;
} else if (modlen == 2048) {
subPrimeLen = 224;
} else if (modlen == 3072) {
subPrimeLen = 256;
}
checkStrength(modlen, subPrimeLen);
if (genParams) {
params = null;
} else {
params = ParameterCache.getCachedDSAParameterSpec(modlen,
subPrimeLen);
if (params == null) {
throw new InvalidParameterException
("No precomputed parameters for requested modulus size "
+ "available");
}
}
this.plen = modlen;
this.qlen = subPrimeLen;
this.random = random;
this.forceNewParameters = genParams;
}
/**
* Initializes the DSA object using a DSA parameter object.
*
* @param params a fully initialized DSA parameter object.
*/
@Override
public void initialize(DSAParams params, SecureRandom random)
throws InvalidParameterException {
if (params == null) {
throw new InvalidParameterException("Params must not be null");
}
DSAParameterSpec spec = new DSAParameterSpec
(params.getP(), params.getQ(), params.getG());
initialize0(spec, random);
init(modlen, random, false);
}
/**
@ -157,10 +104,21 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
throw new InvalidAlgorithmParameterException
("Inappropriate parameter");
}
initialize0((DSAParameterSpec)params, random);
init((DSAParameterSpec)params, random, false);
}
private void initialize0(DSAParameterSpec params, SecureRandom random) {
void init(int modlen, SecureRandom random, boolean forceNew) {
int subPrimeLen = getDefDSASubprimeSize(modlen);
checkStrength(modlen, subPrimeLen);
this.plen = modlen;
this.qlen = subPrimeLen;
this.params = null;
this.random = random;
this.forceNewParameters = forceNew;
}
void init(DSAParameterSpec params, SecureRandom random,
boolean forceNew) {
int sizeP = params.getP().bitLength();
int sizeQ = params.getQ().bitLength();
checkStrength(sizeP, sizeQ);
@ -168,7 +126,7 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
this.qlen = sizeQ;
this.params = params;
this.random = random;
this.forceNewParameters = false;
this.forceNewParameters = forceNew;
}
/**
@ -197,7 +155,7 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
return generateKeyPair(spec.getP(), spec.getQ(), spec.getG(), random);
}
public KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g,
private KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g,
SecureRandom random) {
BigInteger x = generateX(random, q);
@ -252,4 +210,55 @@ public class DSAKeyPairGenerator extends KeyPairGenerator
return y;
}
public static final class Current extends DSAKeyPairGenerator {
public Current() {
super(DEF_DSA_KEY_SIZE);
}
}
public static final class Legacy extends DSAKeyPairGenerator
implements java.security.interfaces.DSAKeyPairGenerator {
public Legacy() {
super(1024);
}
/**
* Initializes the DSA key pair generator. If <code>genParams</code>
* is false, a set of pre-computed parameters is used.
*/
@Override
public void initialize(int modlen, boolean genParams,
SecureRandom random) throws InvalidParameterException {
if (genParams) {
super.init(modlen, random, true);
} else {
DSAParameterSpec cachedParams =
ParameterCache.getCachedDSAParameterSpec(modlen,
getDefDSASubprimeSize(modlen));
if (cachedParams == null) {
throw new InvalidParameterException
("No precomputed parameters for requested modulus" +
" size available");
}
super.init(cachedParams, random, false);
}
}
/**
* Initializes the DSA object using a DSA parameter object.
*
* @param params a fully initialized DSA parameter object.
*/
@Override
public void initialize(DSAParams params, SecureRandom random)
throws InvalidParameterException {
if (params == null) {
throw new InvalidParameterException("Params must not be null");
}
DSAParameterSpec spec = new DSAParameterSpec
(params.getP(), params.getQ(), params.getG());
super.init(spec, random, false);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -34,15 +34,18 @@ import java.security.NoSuchProviderException;
import java.security.InvalidParameterException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.ProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.DSAParameterSpec;
import java.security.spec.DSAGenParameterSpec;
import static sun.security.util.SecurityProviderConstants.DEF_DSA_KEY_SIZE;
import static sun.security.util.SecurityProviderConstants.getDefDSASubprimeSize;
/**
* This class generates parameters for the DSA algorithm. It uses a default
* prime modulus size of 1024 bits, which can be overwritten during
* initialization.
* This class generates parameters for the DSA algorithm.
*
* @author Jan Luehe
*
@ -56,10 +59,6 @@ import java.security.spec.DSAGenParameterSpec;
public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
// the default parameters
private static final DSAGenParameterSpec DEFAULTS =
new DSAGenParameterSpec(1024, 160, 160);
// the length of prime P, subPrime Q, and seed in bits
private int valueL = -1;
private int valueN = -1;
@ -80,18 +79,14 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
*/
@Override
protected void engineInit(int strength, SecureRandom random) {
if ((strength >= 512) && (strength <= 1024) && (strength % 64 == 0)) {
this.valueN = 160;
} else if (strength == 2048) {
this.valueN = 224;
} else if (strength == 3072) {
this.valueN = 256;
} else {
if ((strength != 2048) && (strength != 3072) &&
((strength < 512) || (strength > 1024) || (strength % 64 != 0))) {
throw new InvalidParameterException(
"Unexpected strength (size of prime): " + strength + ". " +
"Prime size should be 512 - 1024, or 2048, 3072");
"Unexpected strength (size of prime): " + strength +
". Prime size should be 512-1024, 2048, or 3072");
}
this.valueL = strength;
this.valueN = getDefDSASubprimeSize(strength);
this.seedLen = valueN;
this.random = random;
}
@ -110,7 +105,6 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
@Override
protected void engineInit(AlgorithmParameterSpec genParamSpec,
SecureRandom random) throws InvalidAlgorithmParameterException {
if (!(genParamSpec instanceof DSAGenParameterSpec)) {
throw new InvalidAlgorithmParameterException("Invalid parameter");
}
@ -136,11 +130,7 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
this.random = new SecureRandom();
}
if (valueL == -1) {
try {
engineInit(DEFAULTS, this.random);
} catch (InvalidAlgorithmParameterException iape) {
// should never happen
}
engineInit(DEF_DSA_KEY_SIZE, this.random);
}
BigInteger[] pAndQ = generatePandQ(this.random, valueL,
valueN, seedLen);
@ -206,13 +196,17 @@ public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi {
int b = (valueL - 1) % outLen;
byte[] seedBytes = new byte[seedLen/8];
BigInteger twoSl = BigInteger.TWO.pow(seedLen);
int primeCertainty = 80; // for 1024-bit prime P
if (valueL == 2048) {
int primeCertainty = -1;
if (valueL <= 1024) {
primeCertainty = 80;
} else if (valueL == 2048) {
primeCertainty = 112;
} else if (valueL == 3072) {
primeCertainty = 128;
}
if (primeCertainty < 0) {
throw new ProviderException("Invalid valueL: " + valueL);
}
BigInteger resultP, resultQ, seed = null;
int counter;
while (true) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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.io.*;
import java.net.*;
import java.util.Map;
import java.security.*;
import sun.security.action.GetPropertyAction;
/**
* Defines the entries of the SUN provider.
@ -74,6 +75,10 @@ import java.security.*;
final class SunEntries {
private static final boolean useLegacyDSA =
Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty
("jdk.security.legacyDSAKeyPairGenerator"));
private SunEntries() {
// empty
}
@ -174,8 +179,9 @@ final class SunEntries {
/*
* Key Pair Generator engines
*/
map.put("KeyPairGenerator.DSA",
"sun.security.provider.DSAKeyPairGenerator");
String dsaKPGImplClass = "sun.security.provider.DSAKeyPairGenerator$";
dsaKPGImplClass += (useLegacyDSA? "Legacy" : "Current");
map.put("KeyPairGenerator.DSA", dsaKPGImplClass);
map.put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
map.put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
map.put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2017, 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.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import sun.security.jca.JCAUtil;
import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE;
/**
* RSA keypair generation. Standard algorithm, minimum key length 512 bit.
@ -55,7 +56,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
public RSAKeyPairGenerator() {
// initialize to default in case the app does not call initialize()
initialize(2048, null);
initialize(DEF_RSA_KEY_SIZE, null);
}
// initialize the generator. See JCA doc

View file

@ -26,6 +26,8 @@
package sun.security.tools.keytool;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.CodeSigner;
import java.security.CryptoPrimitive;
import java.security.KeyStore;
@ -72,6 +74,7 @@ import sun.security.pkcs10.PKCS10Attribute;
import sun.security.provider.X509Factory;
import sun.security.provider.certpath.ssl.SSLServerCertStore;
import sun.security.util.Password;
import sun.security.util.SecurityProviderConstants;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@ -168,7 +171,12 @@ public final class Main {
private List<String> ids = new ArrayList<>(); // used in GENCRL
private List<String> v3ext = new ArrayList<>();
// Warnings on weak algorithms
// In-place importkeystore is special.
// A backup is needed, and no need to prompt for deststorepass.
private boolean inplaceImport = false;
private String inplaceBackupName = null;
// Warnings on weak algorithms etc
private List<String> weakWarnings = new ArrayList<>();
private static final DisabledAlgorithmConstraints DISABLED_CHECK =
@ -846,37 +854,52 @@ public final class Main {
("New.password.must.be.at.least.6.characters"));
}
// Set this before inplaceImport check so we can compare name.
if (ksfname == null) {
ksfname = System.getProperty("user.home") + File.separator
+ ".keystore";
}
KeyStore srcKeyStore = null;
if (command == IMPORTKEYSTORE) {
inplaceImport = inplaceImportCheck();
if (inplaceImport) {
// We load srckeystore first so we have srcstorePass that
// can be assigned to storePass
srcKeyStore = loadSourceKeyStore();
if (storePass == null) {
storePass = srcstorePass;
}
}
}
// Check if keystore exists.
// If no keystore has been specified at the command line, try to use
// the default, which is located in $HOME/.keystore.
// If the command is "genkey", "identitydb", "import", or "printcert",
// it is OK not to have a keystore.
if (isKeyStoreRelated(command)) {
if (ksfname == null) {
ksfname = System.getProperty("user.home") + File.separator
+ ".keystore";
}
if (!nullStream) {
try {
ksfile = new File(ksfname);
// Check if keystore file is empty
if (ksfile.exists() && ksfile.length() == 0) {
throw new Exception(rb.getString
("Keystore.file.exists.but.is.empty.") + ksfname);
}
ksStream = new FileInputStream(ksfile);
} catch (FileNotFoundException e) {
if (command != GENKEYPAIR &&
// DO NOT open the existing keystore if this is an in-place import.
// The keystore should be created as brand new.
if (isKeyStoreRelated(command) && !nullStream && !inplaceImport) {
try {
ksfile = new File(ksfname);
// Check if keystore file is empty
if (ksfile.exists() && ksfile.length() == 0) {
throw new Exception(rb.getString
("Keystore.file.exists.but.is.empty.") + ksfname);
}
ksStream = new FileInputStream(ksfile);
} catch (FileNotFoundException e) {
if (command != GENKEYPAIR &&
command != GENSECKEY &&
command != IDENTITYDB &&
command != IMPORTCERT &&
command != IMPORTPASS &&
command != IMPORTKEYSTORE &&
command != PRINTCRL) {
throw new Exception(rb.getString
("Keystore.file.does.not.exist.") + ksfname);
}
throw new Exception(rb.getString
("Keystore.file.does.not.exist.") + ksfname);
}
}
}
@ -900,7 +923,7 @@ public final class Main {
// Create new keystore
// Probe for keystore type when filename is available
if (ksfile != null && ksStream != null && providerName == null &&
hasStoretypeOption == false) {
hasStoretypeOption == false && !inplaceImport) {
keyStore = KeyStore.getInstance(ksfile, storePass);
} else {
if (providerName == null) {
@ -930,7 +953,11 @@ public final class Main {
* Null stream keystores are loaded later.
*/
if (!nullStream) {
keyStore.load(ksStream, storePass);
if (inplaceImport) {
keyStore.load(null, storePass);
} else {
keyStore.load(ksStream, storePass);
}
if (ksStream != null) {
ksStream.close();
}
@ -1167,7 +1194,11 @@ public final class Main {
}
}
} else if (command == IMPORTKEYSTORE) {
doImportKeyStore();
// When not in-place import, srcKeyStore is not loaded yet.
if (srcKeyStore == null) {
srcKeyStore = loadSourceKeyStore();
}
doImportKeyStore(srcKeyStore);
kssave = true;
} else if (command == KEYCLONE) {
keyPassNew = newPass;
@ -1298,6 +1329,51 @@ public final class Main {
}
}
}
if (isKeyStoreRelated(command)
&& !token && !nullStream && ksfname != null) {
// JKS storetype warning on the final result keystore
File f = new File(ksfname);
char[] pass = (storePassNew!=null) ? storePassNew : storePass;
if (f.exists()) {
// Probe for real type. A JKS can be loaded as PKCS12 because
// DualFormat support, vice versa.
keyStore = KeyStore.getInstance(f, pass);
String realType = keyStore.getType();
if (realType.equalsIgnoreCase("JKS")
|| realType.equalsIgnoreCase("JCEKS")) {
boolean allCerts = true;
for (String a : Collections.list(keyStore.aliases())) {
if (!keyStore.entryInstanceOf(
a, TrustedCertificateEntry.class)) {
allCerts = false;
break;
}
}
// Don't warn for "cacerts" style keystore.
if (!allCerts) {
weakWarnings.add(String.format(
rb.getString("jks.storetype.warning"),
realType, ksfname));
}
}
if (inplaceImport) {
String realSourceStoreType = KeyStore.getInstance(
new File(inplaceBackupName), srcstorePass).getType();
String format =
realType.equalsIgnoreCase(realSourceStoreType) ?
rb.getString("backup.keystore.warning") :
rb.getString("migrate.keystore.warning");
weakWarnings.add(
String.format(format,
srcksfname,
realSourceStoreType,
inplaceBackupName,
realType));
}
}
}
}
/**
@ -1742,9 +1818,12 @@ public final class Main {
{
if (keysize == -1) {
if ("EC".equalsIgnoreCase(keyAlgName)) {
keysize = 256;
} else {
keysize = 2048; // RSA and DSA
keysize = SecurityProviderConstants.DEF_EC_KEY_SIZE;
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
keysize = SecurityProviderConstants.DEF_RSA_KEY_SIZE;
} else if ("DSA".equalsIgnoreCase(keyAlgName)) {
// hardcode for now as DEF_DSA_KEY_SIZE is still 1024
keysize = 2048; // SecurityProviderConstants.DEF_DSA_KEY_SIZE;
}
}
@ -1989,12 +2068,40 @@ public final class Main {
}
}
boolean inplaceImportCheck() throws Exception {
if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
return false;
}
if (srcksfname != null) {
File srcksfile = new File(srcksfname);
if (srcksfile.exists() && srcksfile.length() == 0) {
throw new Exception(rb.getString
("Source.keystore.file.exists.but.is.empty.") +
srcksfname);
}
if (srcksfile.getCanonicalFile()
.equals(new File(ksfname).getCanonicalFile())) {
return true;
} else {
// Informational, especially if destkeystore is not
// provided, which default to ~/.keystore.
System.err.println(String.format(rb.getString(
"importing.keystore.status"), srcksfname, ksfname));
return false;
}
} else {
throw new Exception(rb.getString
("Please.specify.srckeystore"));
}
}
/**
* Load the srckeystore from a stream, used in -importkeystore
* @return the src KeyStore
*/
KeyStore loadSourceKeyStore() throws Exception {
boolean isPkcs11 = false;
InputStream is = null;
File srcksfile = null;
@ -2007,20 +2114,9 @@ public final class Main {
System.err.println();
tinyHelp();
}
isPkcs11 = true;
} else {
if (srcksfname != null) {
srcksfile = new File(srcksfname);
if (srcksfile.exists() && srcksfile.length() == 0) {
throw new Exception(rb.getString
("Source.keystore.file.exists.but.is.empty.") +
srcksfname);
}
is = new FileInputStream(srcksfile);
} else {
throw new Exception(rb.getString
("Please.specify.srckeystore"));
}
srcksfile = new File(srcksfname);
is = new FileInputStream(srcksfile);
}
KeyStore store;
@ -2087,17 +2183,32 @@ public final class Main {
* keep alias unchanged if no name conflict, otherwise, prompt.
* keep keypass unchanged for keys
*/
private void doImportKeyStore() throws Exception {
private void doImportKeyStore(KeyStore srcKS) throws Exception {
if (alias != null) {
doImportKeyStoreSingle(loadSourceKeyStore(), alias);
doImportKeyStoreSingle(srcKS, alias);
} else {
if (dest != null || srckeyPass != null) {
throw new Exception(rb.getString(
"if.alias.not.specified.destalias.and.srckeypass.must.not.be.specified"));
}
doImportKeyStoreAll(loadSourceKeyStore());
doImportKeyStoreAll(srcKS);
}
if (inplaceImport) {
// Backup to file.old or file.old2...
// The keystore is not rewritten yet now.
for (int n = 1; /* forever */; n++) {
inplaceBackupName = srcksfname + ".old" + (n == 1 ? "" : n);
File bkFile = new File(inplaceBackupName);
if (!bkFile.exists()) {
Files.copy(Paths.get(srcksfname), bkFile.toPath());
break;
}
}
}
/*
* Information display rule of -importkeystore
* 1. inside single, shows failure

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, 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
@ -471,6 +471,10 @@ public class Resources extends java.util.ListResourceBundle {
{"verified.by.s.in.s.weak", "Verified by %s in %s with a %s"},
{"whose.sigalg.risk", "%s uses the %s signature algorithm which is considered a security risk."},
{"whose.key.risk", "%s uses a %s which is considered a security risk."},
{"jks.storetype.warning", "The %1$s keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\"."},
{"migrate.keystore.warning", "Migrated \"%1$s\" to %4$s. The %2$s keystore is backed up as \"%3$s\"."},
{"backup.keystore.warning", "The original keystore \"%1$s\" is backed up as \"%3$s\"..."},
{"importing.keystore.status", "Importing keystore %1$s to %2$s..."},
};

View file

@ -37,7 +37,7 @@ import java.util.Arrays;
public class IOUtils {
/**
* Read up to <code>length</code> of bytes from <code>in</code>
* Read up to {@code length} of bytes from {@code in}
* until EOF is detected.
* @param is input stream, must not be null
* @param length number of bytes to read
@ -78,4 +78,22 @@ public class IOUtils {
}
return output;
}
/**
* Read {@code length} of bytes from {@code in}. An exception is
* thrown if there are not enough bytes in the stream.
*
* @param is input stream, must not be null
* @param length number of bytes to read, must not be negative
* @return bytes read
* @throws IOException if any IO error or a premature EOF is detected, or
* if {@code length} is negative since this length is usually also
* read from {@code is}.
*/
public static byte[] readNBytes(InputStream is, int length) throws IOException {
if (length < 0) {
throw new IOException("length cannot be negative: " + length);
}
return readFully(is, length, true);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -111,7 +111,11 @@ class ObjectIdentifier implements Serializable
is.defaultReadObject();
if (encoding == null) { // from an old version
init((int[])components, componentLen);
int[] comp = (int[])components;
if (componentLen > comp.length) {
componentLen = comp.length;
}
init(comp, componentLen);
}
}

View file

@ -0,0 +1,131 @@
/*
* Copyright (c) 2017, 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 sun.security.util;
import java.util.regex.PatternSyntaxException;
import java.security.InvalidParameterException;
import sun.security.action.GetPropertyAction;
/**
* Various constants such as version number, default key length, used by
* the JDK security/crypto providers.
*/
public final class SecurityProviderConstants {
private static final Debug debug =
Debug.getInstance("jca", "ProviderConfig");
// Cannot create one of these
private SecurityProviderConstants () {
}
public static final int getDefDSASubprimeSize(int primeSize) {
if (primeSize <= 1024) {
return 160;
} else if (primeSize == 2048) {
return 224;
} else if (primeSize == 3072) {
return 256;
} else {
throw new InvalidParameterException("Invalid DSA Prime Size: " +
primeSize);
}
}
public static final int DEF_DSA_KEY_SIZE;
public static final int DEF_RSA_KEY_SIZE;
public static final int DEF_DH_KEY_SIZE;
public static final int DEF_EC_KEY_SIZE;
private static final String KEY_LENGTH_PROP =
"jdk.security.defaultKeySize";
static {
String keyLengthStr = GetPropertyAction.privilegedGetProperty
(KEY_LENGTH_PROP);
int dsaKeySize = 1024;
int rsaKeySize = 2048;
int dhKeySize = 2048;
int ecKeySize = 256;
if (keyLengthStr != null) {
try {
String[] pairs = keyLengthStr.split(",");
for (String p : pairs) {
String[] algoAndValue = p.split(":");
if (algoAndValue.length != 2) {
// invalid pair, skip to next pair
if (debug != null) {
debug.println("Ignoring invalid pair in " +
KEY_LENGTH_PROP + " property: " + p);
}
continue;
}
String algoName = algoAndValue[0].trim().toUpperCase();
int value = -1;
try {
value = Integer.parseInt(algoAndValue[1].trim());
} catch (NumberFormatException nfe) {
// invalid value, skip to next pair
if (debug != null) {
debug.println("Ignoring invalid value in " +
KEY_LENGTH_PROP + " property: " + p);
}
continue;
}
if (algoName.equals("DSA")) {
dsaKeySize = value;
} else if (algoName.equals("RSA")) {
rsaKeySize = value;
} else if (algoName.equals("DH")) {
dhKeySize = value;
} else if (algoName.equals("EC")) {
ecKeySize = value;
} else {
if (debug != null) {
debug.println("Ignoring unsupported algo in " +
KEY_LENGTH_PROP + " property: " + p);
}
continue;
}
if (debug != null) {
debug.println("Overriding default " + algoName +
" keysize with value from " +
KEY_LENGTH_PROP + " property: " + value);
}
}
} catch (PatternSyntaxException pse) {
// if property syntax is not followed correctly
if (debug != null) {
debug.println("Unexpected exception while parsing " +
KEY_LENGTH_PROP + " property: " + pse);
}
}
}
DEF_DSA_KEY_SIZE = dsaKeySize;
DEF_RSA_KEY_SIZE = rsaKeySize;
DEF_DH_KEY_SIZE = dhKeySize;
DEF_EC_KEY_SIZE = ecKeySize;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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.util.*;
import javax.security.auth.x500.X500Principal;
import sun.net.util.IPAddressUtil;
import sun.security.util.*;
import sun.security.pkcs.PKCS9Attribute;
@ -440,6 +441,7 @@ implements CertAttrSet<String>, Cloneable {
X500Principal subjectPrincipal = cert.getSubjectX500Principal();
X500Name subject = X500Name.asX500Name(subjectPrincipal);
// Check subject as an X500Name
if (subject.isEmpty() == false) {
if (verify(subject) == false) {
return false;
@ -465,12 +467,51 @@ implements CertAttrSet<String>, Cloneable {
"certificate: " + ce.getMessage());
}
// If there are no subjectAlternativeNames, perform the special-case
// check where if the subjectName contains any EMAILADDRESS
// attributes, they must be checked against RFC822 constraints.
// If that passes, we're fine.
if (altNames == null) {
return verifyRFC822SpecialCase(subject);
altNames = new GeneralNames();
// RFC 5280 4.2.1.10:
// When constraints are imposed on the rfc822Name name form,
// but the certificate does not include a subject alternative name,
// the rfc822Name constraint MUST be applied to the attribute of
// type emailAddress in the subject distinguished name.
for (AVA ava : subject.allAvas()) {
ObjectIdentifier attrOID = ava.getObjectIdentifier();
if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
String attrValue = ava.getValueString();
if (attrValue != null) {
try {
altNames.add(new GeneralName(
new RFC822Name(attrValue)));
} catch (IOException ioe) {
continue;
}
}
}
}
}
// If there is no IPAddressName or DNSName in subjectAlternativeNames,
// see if the last CN inside subjectName can be used instead.
DerValue derValue = subject.findMostSpecificAttribute
(X500Name.commonName_oid);
String cn = derValue == null ? null : derValue.getAsString();
if (cn != null) {
try {
if (IPAddressUtil.isIPv4LiteralAddress(cn) ||
IPAddressUtil.isIPv6LiteralAddress(cn)) {
if (!hasNameType(altNames, GeneralNameInterface.NAME_IP)) {
altNames.add(new GeneralName(new IPAddressName(cn)));
}
} else {
if (!hasNameType(altNames, GeneralNameInterface.NAME_DNS)) {
altNames.add(new GeneralName(new DNSName(cn)));
}
}
} catch (IOException ioe) {
// OK, cn is neither IP nor DNS
}
}
// verify each subjectAltName
@ -485,6 +526,15 @@ implements CertAttrSet<String>, Cloneable {
return true;
}
private static boolean hasNameType(GeneralNames names, int type) {
for (GeneralName name : names.names()) {
if (name.getType() == type) {
return true;
}
}
return false;
}
/**
* check whether a name conforms to these NameConstraints.
* This involves verifying that the name is consistent with the
@ -566,37 +616,6 @@ implements CertAttrSet<String>, Cloneable {
return true;
}
/**
* Perform the RFC 822 special case check. We have a certificate
* that does not contain any subject alternative names. Check that
* any EMAILADDRESS attributes in its subject name conform to these
* NameConstraints.
*
* @param subject the certificate's subject name
* @return true if certificate verifies successfully
* @throws IOException on error
*/
public boolean verifyRFC822SpecialCase(X500Name subject) throws IOException {
for (AVA ava : subject.allAvas()) {
ObjectIdentifier attrOID = ava.getObjectIdentifier();
if (attrOID.equals(PKCS9Attribute.EMAIL_ADDRESS_OID)) {
String attrValue = ava.getValueString();
if (attrValue != null) {
RFC822Name emailName;
try {
emailName = new RFC822Name(attrValue);
} catch (IOException ioe) {
continue;
}
if (!verify(emailName)) {
return(false);
}
}
}
}
return true;
}
/**
* Clone all objects that may be modified during certificate validation.
*/