--- a/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -165,18 +165,16 @@
// partition keyblock into individual secrets
int ofs = 0;
- if (macLength != 0) {
- byte[] tmp = new byte[macLength];
+ byte[] tmp = new byte[macLength];
- // mac keys
- System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
- ofs += macLength;
- clientMacKey = new SecretKeySpec(tmp, "Mac");
+ // mac keys
+ System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
+ ofs += macLength;
+ clientMacKey = new SecretKeySpec(tmp, "Mac");
- System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
- ofs += macLength;
- serverMacKey = new SecretKeySpec(tmp, "Mac");
- }
+ System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
+ ofs += macLength;
+ serverMacKey = new SecretKeySpec(tmp, "Mac");
if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites
return new TlsKeyMaterialSpec(clientMacKey, serverMacKey);
@@ -200,7 +198,7 @@
// IV keys if needed.
if (ivLength != 0) {
- byte[] tmp = new byte[ivLength];
+ tmp = new byte[ivLength];
System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
ofs += ivLength;
@@ -222,8 +220,8 @@
// TLS 1.0
byte[] seed = concat(clientRandom, serverRandom);
- byte[] tmp = doTLS10PRF(clientKeyBytes,
- LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
+ tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
+ expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
@@ -241,7 +239,7 @@
}
} else {
// SSLv3
- byte[] tmp = new byte[expandedKeyLength];
+ tmp = new byte[expandedKeyLength];
md5.update(clientKeyBytes);
md5.update(clientRandom);
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -212,6 +212,12 @@
* generated.
*/
public int getIvLength() {
+ // TLS v1.1 or later uses an explicit IV to protect against
+ // the CBC attacks.
+ if (majorVersion >= 0x03 && minorVersion >= 0x02) {
+ return 0;
+ }
+
return ivLength;
}
--- a/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -58,8 +58,9 @@
* <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
* null, null, null, null)</code>.
*
- * @param clientMacKey the client MAC key (or null)
- * @param serverMacKey the server MAC key (or null)
+ * @param clientMacKey the client MAC key
+ * @param serverMacKey the server MAC key
+ * @throws NullPointerException if clientMacKey or serverMacKey is null
*/
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey) {
this(clientMacKey, serverMacKey, null, null, null, null);
@@ -72,10 +73,11 @@
* <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
* clientCipherKey, serverCipherKey, null, null)</code>.
*
- * @param clientMacKey the client MAC key (or null)
- * @param serverMacKey the server MAC key (or null)
+ * @param clientMacKey the client MAC key
+ * @param serverMacKey the server MAC key
* @param clientCipherKey the client cipher key (or null)
* @param serverCipherKey the server cipher key (or null)
+ * @throws NullPointerException if clientMacKey or serverMacKey is null
*/
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, SecretKey serverCipherKey) {
@@ -88,17 +90,21 @@
* keys, client and server cipher keys, and client and server
* initialization vectors.
*
- * @param clientMacKey the client MAC key (or null)
- * @param serverMacKey the server MAC key (or null)
+ * @param clientMacKey the client MAC key
+ * @param serverMacKey the server MAC key
* @param clientCipherKey the client cipher key (or null)
* @param clientIv the client initialization vector (or null)
* @param serverCipherKey the server cipher key (or null)
* @param serverIv the server initialization vector (or null)
+ *
+ * @throws NullPointerException if clientMacKey or serverMacKey is null
*/
public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
SecretKey clientCipherKey, IvParameterSpec clientIv,
SecretKey serverCipherKey, IvParameterSpec serverIv) {
-
+ if ((clientMacKey == null) || (serverMacKey == null)) {
+ throw new NullPointerException("MAC keys must not be null");
+ }
this.clientMacKey = clientMacKey;
this.serverMacKey = serverMacKey;
this.clientCipherKey = clientCipherKey;
@@ -137,7 +143,7 @@
/**
* Returns the client MAC key.
*
- * @return the client MAC key (or null).
+ * @return the client MAC key.
*/
public SecretKey getClientMacKey() {
return clientMacKey;
@@ -146,7 +152,7 @@
/**
* Return the server MAC key.
*
- * @return the server MAC key (or null).
+ * @return the server MAC key.
*/
public SecretKey getServerMacKey() {
return serverMacKey;
--- a/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2007, 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
@@ -168,22 +168,10 @@
// Note that the MAC keys do not inherit all attributes from the
// template, but they do inherit the sensitive/extractable/token
// flags, which is all P11Key cares about.
- SecretKey clientMacKey, serverMacKey;
-
- // The MAC size may be zero for GCM mode.
- //
- // PKCS11 does not support GCM mode as the author made the comment,
- // so the macBits is unlikely to be zero. It's only a place holder.
- if (macBits != 0) {
- clientMacKey = P11Key.secretKey
+ SecretKey clientMacKey = P11Key.secretKey
(session, out.hClientMacSecret, "MAC", macBits, attributes);
- serverMacKey = P11Key.secretKey
+ SecretKey serverMacKey = P11Key.secretKey
(session, out.hServerMacSecret, "MAC", macBits, attributes);
- } else {
- clientMacKey = null;
- serverMacKey = null;
- }
-
SecretKey clientCipherKey, serverCipherKey;
if (keyBits != 0) {
clientCipherKey = P11Key.secretKey(session, out.hClientKey,
--- a/jdk/src/share/classes/sun/security/ssl/Authenticator.java Tue Mar 12 10:35:44 2013 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2012, 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.ssl;
-
-import java.util.Arrays;
-
-/**
- * This class represents an SSL/TLS message authentication token,
- * which encapsulates a sequence number and ensures that attempts to
- * delete or reorder messages can be detected.
- *
- * Each SSL/TLS connection state contains a sequence number, which
- * is maintained separately for read and write states. The sequence
- * number MUST be set to zero whenever a connection state is made the
- * active state. Sequence numbers are of type uint64 and may not
- * exceed 2^64-1. Sequence numbers do not wrap. If a SSL/TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead. A sequence number is incremented after each
- * record: specifically, the first record transmitted under a
- * particular connection state MUST use sequence number 0.
- */
-class Authenticator {
-
- // byte array containing the additional authentication information for
- // each record
- private final byte[] block;
-
- // the block size of SSL v3.0:
- // sequence number + record type + + record length
- private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
-
- // the block size of TLS v1.0 and later:
- // sequence number + record type + protocol version + record length
- private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
-
- /**
- * Default construct, no message authentication token is initialized.
- *
- * Note that this construct can only be called for null MAC
- */
- Authenticator() {
- block = new byte[0];
- }
-
- /**
- * Constructs the message authentication token for the specified
- * SSL/TLS protocol.
- */
- Authenticator(ProtocolVersion protocolVersion) {
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- block = new byte[BLOCK_SIZE_TLS];
- block[9] = protocolVersion.major;
- block[10] = protocolVersion.minor;
- } else {
- block = new byte[BLOCK_SIZE_SSL];
- }
- }
-
- /**
- * Checks whether the sequence number is close to wrap.
- *
- * Sequence numbers are of type uint64 and may not exceed 2^64-1.
- * Sequence numbers do not wrap. When the sequence number is near
- * to wrap, we need to close the connection immediately.
- *
- * @return true if the sequence number is close to wrap
- */
- final boolean seqNumOverflow() {
- /*
- * Conservatively, we don't allow more records to be generated
- * when there are only 2^8 sequence numbers left.
- */
- return (block.length != 0 &&
- block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
- block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
- block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
- block[6] == (byte)0xFF);
- }
-
- /**
- * Checks whether the sequence number close to renew.
- *
- * Sequence numbers are of type uint64 and may not exceed 2^64-1.
- * Sequence numbers do not wrap. If a TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead.
- *
- * @return true if the sequence number is huge enough to renew
- */
- final boolean seqNumIsHuge() {
- /*
- * Conservatively, we should ask for renegotiation when there are
- * only 2^48 sequence numbers left.
- */
- return (block.length != 0 &&
- block[0] == (byte)0xFF && block[1] == (byte)0xFF);
- }
-
- /**
- * Gets the current sequence number.
- *
- * @return the byte array of the current sequence number
- */
- final byte[] sequenceNumber() {
- return Arrays.copyOf(block, 8);
- }
-
- /**
- * Acquires the current message authentication information with the
- * specified record type and fragment length, and then increases the
- * sequence number.
- *
- * @param type the record type
- * @param length the fragment of the record
- * @return the byte array of the current message authentication information
- */
- final byte[] acquireAuthenticationBytes(byte type, int length) {
- byte[] copy = block.clone();
-
- if (block.length != 0) {
- copy[8] = type;
- copy[copy.length - 2] = (byte)(length >> 8);
- copy[copy.length - 1] = (byte)(length);
-
- /*
- * Increase the sequence number in the block array
- * it is a 64-bit number stored in big-endian format
- */
- int k = 7;
- while ((k >= 0) && (++block[k] == 0)) {
- k--;
- }
- }
-
- return copy;
- }
-
-}
--- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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,18 +29,15 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Hashtable;
-import java.util.Arrays;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.GCMParameterSpec;
import java.nio.*;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
import sun.misc.HexDumpEncoder;
@@ -105,40 +102,19 @@
private final Cipher cipher;
/**
+ * Cipher blocksize, 0 for stream ciphers
+ */
+ private int blockSize;
+
+ /**
* secure random
*/
private SecureRandom random;
/**
- * fixed IV, the implicit nonce of AEAD cipher suite, only apply to
- * AEAD cipher suites
- */
- private final byte[] fixedIv;
-
- /**
- * the key, reserved only for AEAD cipher initialization
- */
- private final Key key;
-
- /**
- * the operation mode, reserved for AEAD cipher initialization
+ * Is the cipher of CBC mode?
*/
- private final int mode;
-
- /**
- * the authentication tag size, only apply to AEAD cipher suites
- */
- private final int tagSize;
-
- /**
- * the record IV length, only apply to AEAD cipher suites
- */
- private final int recordIvSize;
-
- /**
- * cipher type
- */
- private final CipherType cipherType;
+ private final boolean isCBCMode;
/**
* Fixed masks of various block size, as the initial decryption IVs
@@ -156,13 +132,7 @@
private CipherBox() {
this.protocolVersion = ProtocolVersion.DEFAULT;
this.cipher = null;
- this.cipherType = STREAM_CIPHER;
- this.fixedIv = new byte[0];
- this.key = null;
- this.mode = Cipher.ENCRYPT_MODE; // choose at random
- this.random = null;
- this.tagSize = 0;
- this.recordIvSize = 0;
+ this.isCBCMode = false;
}
/**
@@ -177,13 +147,13 @@
try {
this.protocolVersion = protocolVersion;
this.cipher = JsseJce.getCipher(bulkCipher.transformation);
- this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+ int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
if (random == null) {
random = JsseJce.getSecureRandom();
}
this.random = random;
- this.cipherType = bulkCipher.cipherType;
+ this.isCBCMode = bulkCipher.isCBCMode;
/*
* RFC 4346 recommends two algorithms used to generated the
@@ -201,40 +171,14 @@
iv = getFixedMask(bulkCipher.ivSize);
}
- if (cipherType == AEAD_CIPHER) {
- // AEAD must completely initialize the cipher for each packet,
- // and so we save initialization parameters for packet
- // processing time.
-
- // Set the tag size for AEAD cipher
- tagSize = bulkCipher.tagSize;
-
- // Reserve the key for AEAD cipher initialization
- this.key = key;
-
- fixedIv = iv.getIV();
- if (fixedIv == null ||
- fixedIv.length != bulkCipher.fixedIvSize) {
- throw new RuntimeException("Improper fixed IV for AEAD");
- }
+ cipher.init(mode, key, iv, random);
- // Set the record IV length for AEAD cipher
- recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize;
-
- // DON'T initialize the cipher for AEAD!
- } else {
- // CBC only requires one initialization during its lifetime
- // (future packets/IVs set the proper CBC state), so we can
- // initialize now.
-
- // Zeroize the variables that only apply to AEAD cipher
- this.tagSize = 0;
- this.fixedIv = new byte[0];
- this.recordIvSize = 0;
- this.key = null;
-
- // Initialize the cipher
- cipher.init(mode, key, iv, random);
+ // Do not call getBlockSize until after init()
+ // otherwise we would disrupt JCE delayed provider selection
+ blockSize = cipher.getBlockSize();
+ // some providers implement getBlockSize() incorrectly
+ if (blockSize == 1) {
+ blockSize = 0;
}
} catch (NoSuchAlgorithmException e) {
throw e;
@@ -291,11 +235,26 @@
}
try {
- int blockSize = cipher.getBlockSize();
- if (cipherType == BLOCK_CIPHER) {
+ if (blockSize != 0) {
+ // TLSv1.1 needs a IV block
+ if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+ // generate a random number
+ byte[] prefix = new byte[blockSize];
+ random.nextBytes(prefix);
+
+ // move forward the plaintext
+ System.arraycopy(buf, offset,
+ buf, offset + prefix.length, len);
+
+ // prefix the plaintext
+ System.arraycopy(prefix, 0,
+ buf, offset, prefix.length);
+
+ len += prefix.length;
+ }
+
len = addPadding(buf, offset, len, blockSize);
}
-
if (debug != null && Debug.isOn("plaintext")) {
try {
HexDumpEncoder hd = new HexDumpEncoder();
@@ -308,28 +267,14 @@
System.out);
} catch (IOException e) { }
}
-
-
- if (cipherType == AEAD_CIPHER) {
- try {
- return cipher.doFinal(buf, offset, len, buf, offset);
- } catch (IllegalBlockSizeException | BadPaddingException ibe) {
- // unlikely to happen
- throw new RuntimeException(
- "Cipher error in AEAD mode in JCE provider " +
- cipher.getProvider().getName(), ibe);
- }
- } else {
- int newLen = cipher.update(buf, offset, len, buf, offset);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
- return newLen;
+ int newLen = cipher.update(buf, offset, len, buf, offset);
+ if (newLen != len) {
+ // catch BouncyCastle buffering error
+ throw new RuntimeException("Cipher buffering error " +
+ "in JCE provider " + cipher.getProvider().getName());
}
+ return newLen;
} catch (ShortBufferException e) {
- // unlikely to happen, we should have enough buffer space here
throw new ArrayIndexOutOfBoundsException(e.toString());
}
}
@@ -343,7 +288,7 @@
* set to last position padded/encrypted. The limit may have changed
* because of the added padding bytes.
*/
- int encrypt(ByteBuffer bb, int outLimit) {
+ int encrypt(ByteBuffer bb) {
int len = bb.remaining();
@@ -352,71 +297,66 @@
return len;
}
- int pos = bb.position();
+ try {
+ int pos = bb.position();
- int blockSize = cipher.getBlockSize();
- if (cipherType == BLOCK_CIPHER) {
- // addPadding adjusts pos/limit
- len = addPadding(bb, blockSize);
- bb.position(pos);
- }
+ if (blockSize != 0) {
+ // TLSv1.1 needs a IV block
+ if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+ // generate a random number
+ byte[] prefix = new byte[blockSize];
+ random.nextBytes(prefix);
- if (debug != null && Debug.isOn("plaintext")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println(
- "Padded plaintext before ENCRYPTION: len = "
- + len);
- hd.encodeBuffer(bb.duplicate(), System.out);
-
- } catch (IOException e) { }
- }
+ // move forward the plaintext
+ byte[] buf = null;
+ int limit = bb.limit();
+ if (bb.hasArray()) {
+ int arrayOffset = bb.arrayOffset();
+ buf = bb.array();
+ System.arraycopy(buf, arrayOffset + pos,
+ buf, arrayOffset + pos + prefix.length,
+ limit - pos);
+ bb.limit(limit + prefix.length);
+ } else {
+ buf = new byte[limit - pos];
+ bb.get(buf, 0, limit - pos);
+ bb.position(pos + prefix.length);
+ bb.limit(limit + prefix.length);
+ bb.put(buf);
+ }
+ bb.position(pos);
- /*
- * Encrypt "in-place". This does not add its own padding.
- */
- ByteBuffer dup = bb.duplicate();
- if (cipherType == AEAD_CIPHER) {
- try {
- int outputSize = cipher.getOutputSize(dup.remaining());
- if (outputSize > bb.remaining()) {
- // need to expand the limit of the output buffer for
- // the authentication tag.
- //
- // DON'T worry about the buffer's capacity, we have
- // reserved space for the authentication tag.
- if (outLimit < pos + outputSize) {
- // unlikely to happen
- throw new ShortBufferException(
- "need more space in output buffer");
- }
- bb.limit(pos + outputSize);
+ // prefix the plaintext
+ bb.put(prefix);
+ bb.position(pos);
}
- int newLen = cipher.doFinal(dup, bb);
- if (newLen != outputSize) {
- throw new RuntimeException(
- "Cipher buffering error in JCE provider " +
- cipher.getProvider().getName());
- }
- return newLen;
- } catch (IllegalBlockSizeException |
- BadPaddingException | ShortBufferException ibse) {
- // unlikely to happen
- throw new RuntimeException(
- "Cipher error in AEAD mode in JCE provider " +
- cipher.getProvider().getName(), ibse);
+
+ // addPadding adjusts pos/limit
+ len = addPadding(bb, blockSize);
+ bb.position(pos);
}
- } else {
- int newLen;
- try {
- newLen = cipher.update(dup, bb);
- } catch (ShortBufferException sbe) {
- // unlikely to happen
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
+ if (debug != null && Debug.isOn("plaintext")) {
+ try {
+ HexDumpEncoder hd = new HexDumpEncoder();
+
+ System.out.println(
+ "Padded plaintext before ENCRYPTION: len = "
+ + len);
+ hd.encodeBuffer(bb, System.out);
+
+ } catch (IOException e) { }
+ /*
+ * reset back to beginning
+ */
+ bb.position(pos);
}
+ /*
+ * Encrypt "in-place". This does not add its own padding.
+ */
+ ByteBuffer dup = bb.duplicate();
+ int newLen = cipher.update(dup, bb);
+
if (bb.position() != dup.position()) {
throw new RuntimeException("bytebuffer padding error");
}
@@ -427,6 +367,10 @@
"in JCE provider " + cipher.getProvider().getName());
}
return newLen;
+ } catch (ShortBufferException e) {
+ RuntimeException exc = new RuntimeException(e.toString());
+ exc.initCause(e);
+ throw exc;
}
}
@@ -454,23 +398,11 @@
}
try {
- int newLen;
- if (cipherType == AEAD_CIPHER) {
- try {
- newLen = cipher.doFinal(buf, offset, len, buf, offset);
- } catch (IllegalBlockSizeException ibse) {
- // unlikely to happen
- throw new RuntimeException(
- "Cipher error in AEAD mode in JCE provider " +
- cipher.getProvider().getName(), ibse);
- }
- } else {
- newLen = cipher.update(buf, offset, len, buf, offset);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
+ int newLen = cipher.update(buf, offset, len, buf, offset);
+ if (newLen != len) {
+ // catch BouncyCastle buffering error
+ throw new RuntimeException("Cipher buffering error " +
+ "in JCE provider " + cipher.getProvider().getName());
}
if (debug != null && Debug.isOn("plaintext")) {
try {
@@ -484,9 +416,7 @@
System.out);
} catch (IOException e) { }
}
-
- if (cipherType == BLOCK_CIPHER) {
- int blockSize = cipher.getBlockSize();
+ if (blockSize != 0) {
newLen = removePadding(buf, offset, newLen,
blockSize, protocolVersion);
@@ -494,11 +424,16 @@
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
+
+ // discards the first cipher block, the IV component.
+ System.arraycopy(buf, offset + blockSize,
+ buf, offset, newLen - blockSize);
+
+ newLen -= blockSize;
}
}
return newLen;
} catch (ShortBufferException e) {
- // unlikely to happen, we should have enough buffer space here
throw new ArrayIndexOutOfBoundsException(e.toString());
}
}
@@ -528,29 +463,15 @@
*/
int pos = bb.position();
ByteBuffer dup = bb.duplicate();
- int newLen;
- if (cipherType == AEAD_CIPHER) {
- try {
- newLen = cipher.doFinal(dup, bb);
- } catch (IllegalBlockSizeException ibse) {
- // unlikely to happen
- throw new RuntimeException(
- "Cipher error in AEAD mode \"" + ibse.getMessage() +
- " \"in JCE provider " + cipher.getProvider().getName());
- }
- } else {
- newLen = cipher.update(dup, bb);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
+ int newLen = cipher.update(dup, bb);
+ if (newLen != len) {
+ // catch BouncyCastle buffering error
+ throw new RuntimeException("Cipher buffering error " +
+ "in JCE provider " + cipher.getProvider().getName());
}
- // reset the limit to the end of the decryted data
- bb.limit(pos + newLen);
-
if (debug != null && Debug.isOn("plaintext")) {
+ bb.position(pos);
try {
HexDumpEncoder hd = new HexDumpEncoder();
@@ -558,33 +479,50 @@
"Padded plaintext after DECRYPTION: len = "
+ newLen);
- hd.encodeBuffer(
- (ByteBuffer)bb.duplicate().position(pos), System.out);
+ hd.encodeBuffer(bb, System.out);
} catch (IOException e) { }
}
/*
* Remove the block padding.
*/
- if (cipherType == BLOCK_CIPHER) {
- int blockSize = cipher.getBlockSize();
+ if (blockSize != 0) {
bb.position(pos);
newLen = removePadding(bb, blockSize, protocolVersion);
- // check the explicit IV of TLS v1.1 or later
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
+ // discards the first cipher block, the IV component.
+ byte[] buf = null;
+ int limit = bb.limit();
+ if (bb.hasArray()) {
+ int arrayOffset = bb.arrayOffset();
+ buf = bb.array();
+ System.arraycopy(buf, arrayOffset + pos + blockSize,
+ buf, arrayOffset + pos, limit - pos - blockSize);
+ bb.limit(limit - blockSize);
+ } else {
+ buf = new byte[limit - pos - blockSize];
+ bb.position(pos + blockSize);
+ bb.get(buf);
+ bb.position(pos);
+ bb.put(buf);
+ bb.limit(limit - blockSize);
+ }
+
// reset the position to the end of the decrypted data
- bb.position(bb.limit());
+ limit = bb.limit();
+ bb.position(limit);
}
}
return newLen;
} catch (ShortBufferException e) {
- // unlikely to happen, we should have enough buffer space here
- throw new ArrayIndexOutOfBoundsException(e.toString());
+ RuntimeException exc = new RuntimeException(e.toString());
+ exc.initCause(e);
+ throw exc;
}
}
@@ -757,8 +695,8 @@
// ignore return value.
cipher.doFinal();
}
- } catch (Exception e) {
- // swallow all types of exceptions.
+ } catch (GeneralSecurityException e) {
+ // swallow for now.
}
}
@@ -768,234 +706,6 @@
* @return true if the cipher use CBC mode, false otherwise.
*/
boolean isCBCMode() {
- return cipherType == BLOCK_CIPHER;
- }
-
- /*
- * Does the cipher use AEAD mode?
- *
- * @return true if the cipher use AEAD mode, false otherwise.
- */
- boolean isAEADMode() {
- return cipherType == AEAD_CIPHER;
- }
-
- /*
- * Is the cipher null?
- *
- * @return true if the cipher is null, false otherwise.
- */
- boolean isNullCipher() {
- return cipher == null;
- }
-
- /*
- * Gets the explicit nonce/IV size of the cipher.
- *
- * The returned value is the SecurityParameters.record_iv_length in
- * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the
- * size of explicit nonce for AEAD mode.
- *
- * @return the explicit nonce size of the cipher.
- */
- int getExplicitNonceSize() {
- switch (cipherType) {
- case BLOCK_CIPHER:
- // For block ciphers, the explicit IV length is of length
- // SecurityParameters.record_iv_length, which is equal to
- // the SecurityParameters.block_size.
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- return cipher.getBlockSize();
- }
- break;
- case AEAD_CIPHER:
- return recordIvSize;
- // It is also the length of sequence number, which is
- // used as the nonce_explicit for AEAD cipher suites.
- }
-
- return 0;
- }
-
- /*
- * Applies the explicit nonce/IV to this cipher. This method is used to
- * decrypt an SSL/TLS input record.
- *
- * The returned value is the SecurityParameters.record_iv_length in
- * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the
- * size of explicit nonce for AEAD mode.
- *
- * @param authenticator the authenticator to get the additional
- * authentication data
- * @param contentType the content type of the input record
- * @param bb the byte buffer to get the explicit nonce from
- *
- * @return the explicit nonce size of the cipher.
- */
- int applyExplicitNonce(Authenticator authenticator, byte contentType,
- ByteBuffer bb) throws BadPaddingException {
- switch (cipherType) {
- case BLOCK_CIPHER:
- // For block ciphers, the explicit IV length is of length
- // SecurityParameters.record_iv_length, which is equal to
- // the SecurityParameters.block_size.
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- return cipher.getBlockSize();
- }
- break;
- case AEAD_CIPHER:
- if (bb.remaining() < (recordIvSize + tagSize)) {
- throw new BadPaddingException(
- "invalid AEAD cipher fragment");
- }
-
- // initialize the AEAD cipher for the unique IV
- byte[] iv = Arrays.copyOf(fixedIv,
- fixedIv.length + recordIvSize);
- bb.get(iv, fixedIv.length, recordIvSize);
- bb.position(bb.position() - recordIvSize);
- GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
- try {
- cipher.init(mode, key, spec, random);
- } catch (InvalidKeyException |
- InvalidAlgorithmParameterException ikae) {
- // unlikely to happen
- throw new RuntimeException(
- "invalid key or spec in GCM mode", ikae);
- }
-
- // update the additional authentication data
- byte[] aad = authenticator.acquireAuthenticationBytes(
- contentType, bb.remaining() - recordIvSize - tagSize);
- cipher.updateAAD(aad);
-
- return recordIvSize;
- // It is also the length of sequence number, which is
- // used as the nonce_explicit for AEAD cipher suites.
- }
-
- return 0;
- }
-
- /*
- * Applies the explicit nonce/IV to this cipher. This method is used to
- * decrypt an SSL/TLS input record.
- *
- * The returned value is the SecurityParameters.record_iv_length in
- * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the
- * size of explicit nonce for AEAD mode.
- *
- * @param authenticator the authenticator to get the additional
- * authentication data
- * @param contentType the content type of the input record
- * @param buf the byte array to get the explicit nonce from
- * @param offset the offset of the byte buffer
- * @param cipheredLength the ciphered fragment length of the output
- * record, it is the TLSCiphertext.length in RFC 4346/5246.
- *
- * @return the explicit nonce size of the cipher.
- */
- int applyExplicitNonce(Authenticator authenticator,
- byte contentType, byte[] buf, int offset,
- int cipheredLength) throws BadPaddingException {
-
- ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength);
-
- return applyExplicitNonce(authenticator, contentType, bb);
- }
-
- /*
- * Creates the explicit nonce/IV to this cipher. This method is used to
- * encrypt an SSL/TLS output record.
- *
- * The size of the returned array is the SecurityParameters.record_iv_length
- * in RFC 4346/5246. It is the size of explicit IV for CBC mode, and the
- * size of explicit nonce for AEAD mode.
- *
- * @param authenticator the authenticator to get the additional
- * authentication data
- * @param contentType the content type of the input record
- * @param fragmentLength the fragment length of the output record, it is
- * the TLSCompressed.length in RFC 4346/5246.
- *
- * @return the explicit nonce of the cipher.
- */
- byte[] createExplicitNonce(Authenticator authenticator,
- byte contentType, int fragmentLength) {
-
- byte[] nonce = new byte[0];
- switch (cipherType) {
- case BLOCK_CIPHER:
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- // For block ciphers, the explicit IV length is of length
- // SecurityParameters.record_iv_length, which is equal to
- // the SecurityParameters.block_size.
- //
- // Generate a random number as the explicit IV parameter.
- nonce = new byte[cipher.getBlockSize()];
- random.nextBytes(nonce);
- }
- break;
- case AEAD_CIPHER:
- // To be unique and aware of overflow-wrap, sequence number
- // is used as the nonce_explicit of AEAD cipher suites.
- nonce = authenticator.sequenceNumber();
-
- // initialize the AEAD cipher for the unique IV
- byte[] iv = Arrays.copyOf(fixedIv,
- fixedIv.length + nonce.length);
- System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
- GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
- try {
- cipher.init(mode, key, spec, random);
- } catch (InvalidKeyException |
- InvalidAlgorithmParameterException ikae) {
- // unlikely to happen
- throw new RuntimeException(
- "invalid key or spec in GCM mode", ikae);
- }
-
- // update the additional authentication data
- byte[] aad = authenticator.acquireAuthenticationBytes(
- contentType, fragmentLength);
- cipher.updateAAD(aad);
- break;
- }
-
- return nonce;
- }
-
- /*
- * Is this cipher available?
- *
- * This method can only be called by CipherSuite.BulkCipher.isAvailable()
- * to test the availability of a cipher suites. Please DON'T use it in
- * other places, otherwise, the behavior may be unexpected because we may
- * initialize AEAD cipher improperly in the method.
- */
- Boolean isAvailable() {
- // We won't know whether a cipher for a particular key size is
- // available until the cipher is successfully initialized.
- //
- // We do not initialize AEAD cipher in the constructor. Need to
- // initialize the cipher to ensure that the AEAD mode for a
- // particular key size is supported.
- if (cipherType == AEAD_CIPHER) {
- try {
- Authenticator authenticator =
- new Authenticator(protocolVersion);
- byte[] nonce = authenticator.sequenceNumber();
- byte[] iv = Arrays.copyOf(fixedIv,
- fixedIv.length + nonce.length);
- System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
- GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
-
- cipher.init(mode, key, spec, random);
- } catch (Exception e) {
- return Boolean.FALSE;
- }
- } // Otherwise, we have initialized the cipher in the constructor.
-
- return Boolean.TRUE;
+ return isCBCMode;
}
}
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Tue Mar 12 15:31:49 2013 -0700
@@ -33,14 +33,12 @@
import java.security.SecureRandom;
import java.security.KeyManagementException;
-import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
import static sun.security.ssl.JsseJce.*;
/**
@@ -137,9 +135,7 @@
this.keyExchange = keyExchange;
this.cipher = cipher;
this.exportable = cipher.exportable;
- if (cipher.cipherType == CipherType.AEAD_CIPHER) {
- macAlg = M_NULL;
- } else if (name.endsWith("_MD5")) {
+ if (name.endsWith("_MD5")) {
macAlg = M_MD5;
} else if (name.endsWith("_SHA")) {
macAlg = M_SHA;
@@ -389,12 +385,6 @@
}
}
- static enum CipherType {
- STREAM_CIPHER, // null or stream cipher
- BLOCK_CIPHER, // block cipher in CBC mode
- AEAD_CIPHER // AEAD cipher
- }
-
/**
* An SSL/TLS bulk cipher algorithm. One instance per combination of
* cipher and key length.
@@ -427,26 +417,14 @@
// for non-exportable ciphers, this is the same as keySize
final int expandedKeySize;
- // size of the IV
+ // size of the IV (also block size)
final int ivSize;
- // size of fixed IV
- //
- // record_iv_length = ivSize - fixedIvSize
- final int fixedIvSize;
-
// exportable under 512/40 bit rules
final boolean exportable;
// Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
- final CipherType cipherType;
-
- // size of the authentication tag, only applicable to cipher suites in
- // Galois Counter Mode (GCM)
- //
- // As far as we know, all supported GCM cipher suites use 128-bits
- // authentication tags.
- final int tagSize = 16;
+ final boolean isCBCMode;
// The secure random used to detect the cipher availability.
private final static SecureRandom secureRandom;
@@ -459,34 +437,32 @@
}
}
- BulkCipher(String transformation, CipherType cipherType, int keySize,
- int expandedKeySize, int ivSize,
- int fixedIvSize, boolean allowed) {
-
+ BulkCipher(String transformation, int keySize,
+ int expandedKeySize, int ivSize, boolean allowed) {
this.transformation = transformation;
String[] splits = transformation.split("/");
this.algorithm = splits[0];
- this.cipherType = cipherType;
+ this.isCBCMode =
+ splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
this.description = this.algorithm + "/" + (keySize << 3);
this.keySize = keySize;
this.ivSize = ivSize;
- this.fixedIvSize = fixedIvSize;
this.allowed = allowed;
this.expandedKeySize = expandedKeySize;
this.exportable = true;
}
- BulkCipher(String transformation, CipherType cipherType, int keySize,
- int ivSize, int fixedIvSize, boolean allowed) {
+ BulkCipher(String transformation, int keySize,
+ int ivSize, boolean allowed) {
this.transformation = transformation;
String[] splits = transformation.split("/");
this.algorithm = splits[0];
- this.cipherType = cipherType;
+ this.isCBCMode =
+ splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
this.description = this.algorithm + "/" + (keySize << 3);
this.keySize = keySize;
this.ivSize = ivSize;
- this.fixedIvSize = fixedIvSize;
this.allowed = allowed;
this.expandedKeySize = keySize;
@@ -510,20 +486,16 @@
* Test if this bulk cipher is available. For use by CipherSuite.
*
* Currently all supported ciphers except AES are always available
- * via the JSSE internal implementations. We also assume AES/128 of
- * CBC mode is always available since it is shipped with the SunJCE
- * provider. However, AES/256 is unavailable when the default JCE
- * policy jurisdiction files are installed because of key length
- * restrictions, and AEAD is unavailable when the underlying providers
- * do not support AEAD/GCM mode.
+ * via the JSSE internal implementations. We also assume AES/128
+ * is always available since it is shipped with the SunJCE provider.
+ * However, AES/256 is unavailable when the default JCE policy
+ * jurisdiction files are installed because of key length restrictions.
*/
boolean isAvailable() {
if (allowed == false) {
return false;
}
-
- if ((this == B_AES_256) ||
- (this.cipherType == CipherType.AEAD_CIPHER)) {
+ if (this == B_AES_256) {
return isAvailable(this);
}
@@ -541,50 +513,19 @@
private static synchronized boolean isAvailable(BulkCipher cipher) {
Boolean b = availableCache.get(cipher);
if (b == null) {
- int keySizeInBits = cipher.keySize * 8;
- if (keySizeInBits > 128) { // need the JCE unlimited
- // strength jurisdiction policy
- try {
- if (Cipher.getMaxAllowedKeyLength(
- cipher.transformation) < keySizeInBits) {
- b = Boolean.FALSE;
- }
- } catch (Exception e) {
- b = Boolean.FALSE;
- }
+ try {
+ SecretKey key = new SecretKeySpec
+ (new byte[cipher.expandedKeySize], cipher.algorithm);
+ IvParameterSpec iv =
+ new IvParameterSpec(new byte[cipher.ivSize]);
+ cipher.newCipher(ProtocolVersion.DEFAULT,
+ key, iv, secureRandom, true);
+ b = Boolean.TRUE;
+ } catch (NoSuchAlgorithmException e) {
+ b = Boolean.FALSE;
}
-
- if (b == null) {
- b = Boolean.FALSE; // may be reset to TRUE if
- // the cipher is available
- CipherBox temporary = null;
- try {
- SecretKey key = new SecretKeySpec(
- new byte[cipher.expandedKeySize],
- cipher.algorithm);
- IvParameterSpec iv;
- if (cipher.cipherType == CipherType.AEAD_CIPHER) {
- iv = new IvParameterSpec(
- new byte[cipher.fixedIvSize]);
- } else {
- iv = new IvParameterSpec(new byte[cipher.ivSize]);
- }
- temporary = cipher.newCipher(
- ProtocolVersion.DEFAULT,
- key, iv, secureRandom, true);
- b = temporary.isAvailable();
- } catch (NoSuchAlgorithmException e) {
- // not available
- } finally {
- if (temporary != null) {
- temporary.dispose();
- }
- }
- }
-
availableCache.put(cipher, b);
}
-
return b.booleanValue();
}
@@ -632,31 +573,27 @@
// export strength ciphers
final static BulkCipher B_NULL =
- new BulkCipher("NULL", STREAM_CIPHER, 0, 0, 0, 0, true);
+ new BulkCipher("NULL", 0, 0, 0, true);
final static BulkCipher B_RC4_40 =
- new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true);
+ new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
final static BulkCipher B_RC2_40 =
- new BulkCipher("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false);
+ new BulkCipher("RC2", 5, 16, 8, false);
final static BulkCipher B_DES_40 =
- new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 5, 8, 8, 0, true);
+ new BulkCipher(CIPHER_DES, 5, 8, 8, true);
// domestic strength ciphers
final static BulkCipher B_RC4_128 =
- new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 16, 0, 0, true);
+ new BulkCipher(CIPHER_RC4, 16, 0, true);
final static BulkCipher B_DES =
- new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 8, 8, 0, true);
+ new BulkCipher(CIPHER_DES, 8, 8, true);
final static BulkCipher B_3DES =
- new BulkCipher(CIPHER_3DES, BLOCK_CIPHER, 24, 8, 0, true);
+ new BulkCipher(CIPHER_3DES, 24, 8, true);
final static BulkCipher B_IDEA =
- new BulkCipher("IDEA", BLOCK_CIPHER, 16, 8, 0, false);
+ new BulkCipher("IDEA", 16, 8, false);
final static BulkCipher B_AES_128 =
- new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 16, 16, 0, true);
+ new BulkCipher(CIPHER_AES, 16, 16, true);
final static BulkCipher B_AES_256 =
- new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 32, 16, 0, true);
- final static BulkCipher B_AES_128_GCM =
- new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 16, 12, 4, true);
- final static BulkCipher B_AES_256_GCM =
- new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 32, 12, 4, true);
+ new BulkCipher(CIPHER_AES, 32, 16, true);
// MACs
final static MacAlg M_NULL = new MacAlg("NULL", 0);
@@ -956,12 +893,11 @@
* Definition of the CipherSuites that are enabled by default.
* They are listed in preference order, most preferred first, using
* the following criteria:
- * 1. Prefer Suite B compliant cipher suites, see RFC6460.
- * 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
- * AES_128(GCM), AES_256, AES_128, RC-4, 3DES-EDE.
- * 3. Prefer the stronger MAC algorithm, in the order of SHA384,
+ * 1. Prefer the stronger buld cipher, in the order of AES_256,
+ * AES_128, RC-4, 3DES-EDE.
+ * 2. Prefer the stronger MAC algorithm, in the order of SHA384,
* SHA256, SHA, MD5.
- * 4. Prefer the better performance of key exchange and digital
+ * 3. Prefer the better performance of key exchange and digital
* signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
* RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
*/
@@ -974,16 +910,6 @@
// ID Key Exchange Cipher A obs suprt PRF
// ====== ============ ========= = === ===== ========
-
-
- // Placeholder for cipher suites in GCM mode.
- //
- // For better compatibility and interoperability, we decrease the
- // priority of cipher suites in GCM mode for a while as GCM
- // technologies mature in the industry. Eventually we'll move
- // the GCM suites here.
-
- // AES_256(CBC)
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
@@ -1014,7 +940,6 @@
add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
0x0038, --p, K_DHE_DSS, B_AES_256, T);
- // AES_128(CBC)
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
@@ -1045,7 +970,6 @@
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
0x0032, --p, K_DHE_DSS, B_AES_128, T);
- // RC-4
add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
@@ -1057,51 +981,6 @@
add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
- // Cipher suites in GCM mode, see RFC 5288/5289.
- //
- // We may increase the priority of cipher suites in GCM mode when
- // GCM technologies become mature in the industry.
-
- // Suite B compliant cipher suites, see RFC 6460.
- //
- // Note that, at present this provider is not Suite B compliant. The
- // preference order of the GCM cipher suites does not follow the spec
- // of RFC 6460.
- add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
- 0xc02c, --p, K_ECDHE_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
- 0xc02b, --p, K_ECDHE_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
-
- // AES_256(GCM)
- add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
- 0xc030, --p, K_ECDHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_RSA_WITH_AES_256_GCM_SHA384",
- 0x009d, --p, K_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
- 0xc02e, --p, K_ECDH_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
- 0xc032, --p, K_ECDH_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
- 0x009f, --p, K_DHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
- add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
- 0x00a3, --p, K_DHE_DSS, B_AES_256_GCM, T, max, tls12, P_SHA384);
-
- // AES_128(GCM)
- add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- 0xc02f, --p, K_ECDHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
- add("TLS_RSA_WITH_AES_128_GCM_SHA256",
- 0x009c, --p, K_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
- add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- 0xc02d, --p, K_ECDH_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
- add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
- 0xc031, --p, K_ECDH_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
- add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
- 0x009e, --p, K_DHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
- add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
- 0x00a2, --p, K_DHE_DSS, B_AES_128_GCM, T, max, tls12, P_SHA256);
- // End of cipher suites in GCM mode.
-
- // 3DES_EDE
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -1145,22 +1024,17 @@
*/
p = DEFAULT_SUITES_PRIORITY;
- add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",
- 0x00a7, --p, K_DH_ANON, B_AES_256_GCM, N, max, tls12, P_SHA384);
- add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",
- 0x00a6, --p, K_DH_ANON, B_AES_128_GCM, N, max, tls12, P_SHA256);
-
add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
- 0xC019, --p, K_ECDH_ANON, B_AES_256, N);
+ 0xC019, --p, K_ECDH_ANON, B_AES_256, T);
add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
0x003a, --p, K_DH_ANON, B_AES_256, N);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256);
add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
- 0xC018, --p, K_ECDH_ANON, B_AES_128, N);
+ 0xC018, --p, K_ECDH_ANON, B_AES_128, T);
add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
0x0034, --p, K_DH_ANON, B_AES_128, N);
@@ -1170,7 +1044,7 @@
0x0018, --p, K_DH_ANON, B_RC4_128, N);
add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
- 0xC017, --p, K_ECDH_ANON, B_3DES, N);
+ 0xC017, --p, K_ECDH_ANON, B_3DES, T);
add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
0x001b, --p, K_DH_ANON, B_3DES, N);
@@ -1325,10 +1199,18 @@
add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
// Unsupported cipher suites from RFC 5288
+ add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c);
+ add("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d);
+ add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e);
+ add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f);
add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0);
add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1);
+ add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2);
+ add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3);
add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4);
add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5);
+ add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6);
+ add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7);
// Unsupported cipher suites from RFC 5487
add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8);
@@ -1387,6 +1269,16 @@
add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021);
add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
+ // Unsupported cipher suites from RFC 5289
+ add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b);
+ add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c);
+ add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d);
+ add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e);
+ add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f);
+ add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030);
+ add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031);
+ add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032);
+
// Unsupported cipher suites from RFC 5489
add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033);
add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
--- a/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2007, 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
@@ -178,6 +178,71 @@
}
/*
+ * Verifies and removes the MAC value. Returns true if
+ * the MAC checks out OK.
+ *
+ * On entry:
+ * position = beginning of app/MAC data
+ * limit = end of MAC data.
+ *
+ * On return:
+ * position = beginning of app data
+ * limit = end of app data
+ */
+ boolean checkMAC(MAC signer, ByteBuffer bb) {
+ if (internalData) {
+ return checkMAC(signer);
+ }
+
+ int len = signer.MAClen();
+ if (len == 0) { // no mac
+ return true;
+ }
+
+ /*
+ * Grab the original limit
+ */
+ int lim = bb.limit();
+
+ /*
+ * Delineate the area to apply a MAC on.
+ */
+ int macData = lim - len;
+ bb.limit(macData);
+
+ byte[] mac = signer.compute(contentType(), bb);
+
+ if (len != mac.length) {
+ throw new RuntimeException("Internal MAC error");
+ }
+
+ /*
+ * Delineate the MAC values, position was already set
+ * by doing the compute above.
+ *
+ * We could zero the MAC area, but not much useful information
+ * there anyway.
+ */
+ bb.position(macData);
+ bb.limit(lim);
+
+ try {
+ for (int i = 0; i < len; i++) {
+ if (bb.get() != mac[i]) { // No BB.equals(byte []); !
+ return false;
+ }
+ }
+ return true;
+ } finally {
+ /*
+ * Position to the data.
+ */
+ bb.rewind();
+ bb.limit(macData);
+ }
+ }
+
+ /*
* Pass the data down if it's internally cached, otherwise
* do it here.
*
@@ -186,85 +251,16 @@
* If external data(app), return a new ByteBuffer with data to
* process.
*/
- ByteBuffer decrypt(Authenticator authenticator,
- CipherBox box, ByteBuffer bb) throws BadPaddingException {
+ ByteBuffer decrypt(CipherBox box, ByteBuffer bb)
+ throws BadPaddingException {
if (internalData) {
- decrypt(authenticator, box); // MAC is checked during decryption
+ decrypt(box);
return tmpBB;
}
- BadPaddingException bpe = null;
- if (!box.isNullCipher()) {
- try {
- // apply explicit nonce for AEAD/CBC cipher suites if needed
- int nonceSize =
- box.applyExplicitNonce(authenticator, contentType(), bb);
-
- // decrypt the content
- if (box.isAEADMode()) {
- // DON'T encrypt the nonce_explicit for AEAD mode
- bb.position(bb.position() + nonceSize);
- } // The explicit IV for CBC mode can be decrypted.
-
- box.decrypt(bb);
- bb.position(nonceSize); // We don't actually remove the nonce.
- } catch (BadPaddingException e) {
- // RFC 2246 states that decryption_failed should be used
- // for this purpose. However, that allows certain attacks,
- // so we just send bad record MAC. We also need to make
- // sure to always check the MAC to avoid a timing attack
- // for the same issue. See paper by Vaudenay et al and the
- // update in RFC 4346/5246.
- //
- // Failover to message authentication code checking.
- bpe = new BadPaddingException("invalid padding");
- }
- }
-
- // Requires message authentication code for null, stream and block
- // cipher suites.
- if (authenticator instanceof MAC) {
- MAC signer = (MAC)authenticator;
- int macLen = signer.MAClen();
- if (macLen != 0) {
- if (bb.remaining() < macLen) {
- // negative data length, something is wrong
- throw new BadPaddingException("bad record");
- }
-
- int position = bb.position();
- int limit = bb.limit();
- int macOffset = limit - macLen;
-
- bb.limit(macOffset);
- byte[] hash = signer.compute(contentType(), bb);
- if (hash == null || macLen != hash.length) {
- // something is wrong with MAC implementation
- throw new RuntimeException("Internal MAC error");
- }
-
- bb.position(macOffset);
- bb.limit(limit);
-
- try {
- for (byte b : hash) { // No BB.equals(byte []); !
- if (bb.get() != b) {
- throw new BadPaddingException("bad record MAC");
- }
- }
- } finally {
- // reset to the data
- bb.position(position);
- bb.limit(macOffset);
- }
- }
- }
-
- // Is it a failover?
- if (bpe != null) {
- throw bpe;
- }
+ box.decrypt(bb);
+ bb.rewind();
return bb.slice();
}
@@ -342,8 +338,8 @@
if (debug != null && Debug.isOn("packet")) {
try {
HexDumpEncoder hd = new HexDumpEncoder();
+ srcBB.limit(srcPos + len);
ByteBuffer bb = srcBB.duplicate(); // Use copy of BB
- bb.limit(srcPos + len);
System.out.println("[Raw read (bb)]: length = " + len);
hd.encodeBuffer(bb, System.out);
--- a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java Tue Mar 12 15:31:49 2013 -0700
@@ -29,6 +29,7 @@
import java.io.*;
import java.nio.*;
+
/**
* A OutputRecord class extension which uses external ByteBuffers
* or the internal ByteArrayOutputStream for data manipulations.
@@ -100,6 +101,51 @@
return finishedMsg;
}
+
+ /**
+ * Calculate the MAC value, storing the result either in
+ * the internal buffer, or at the end of the destination
+ * ByteBuffer.
+ * <P>
+ * We assume that the higher levels have assured us enough
+ * room, otherwise we'll indirectly throw a
+ * BufferOverFlowException runtime exception.
+ *
+ * position should equal limit, and points to the next
+ * free spot.
+ */
+ private void addMAC(MAC signer, ByteBuffer bb)
+ throws IOException {
+
+ if (signer.MAClen() != 0) {
+ byte[] hash = signer.compute(contentType(), bb);
+
+ /*
+ * position was advanced to limit in compute above.
+ *
+ * Mark next area as writable (above layers should have
+ * established that we have plenty of room), then write
+ * out the hash.
+ */
+ bb.limit(bb.limit() + hash.length);
+ bb.put(hash);
+ }
+ }
+
+ /*
+ * Encrypt a ByteBuffer.
+ *
+ * We assume that the higher levels have assured us enough
+ * room for the encryption (plus padding), otherwise we'll
+ * indirectly throw a BufferOverFlowException runtime exception.
+ *
+ * position and limit will be the same, and points to the
+ * next free spot.
+ */
+ void encrypt(CipherBox box, ByteBuffer bb) {
+ box.encrypt(bb);
+ }
+
/*
* Override the actual write below. We do things this way to be
* consistent with InputRecord. InputRecord may try to write out
@@ -114,8 +160,7 @@
* Copy data out of buffer, it's ready to go.
*/
ByteBuffer netBB = (ByteBuffer)
- ByteBuffer.allocate(len).put(buf, off, len).flip();
-
+ ByteBuffer.allocate(len).put(buf, 0, len).flip();
writer.putOutboundData(netBB);
}
@@ -123,19 +168,17 @@
* Main method for writing non-application data.
* We MAC/encrypt, then send down for processing.
*/
- void write(Authenticator authenticator, CipherBox writeCipher)
- throws IOException {
-
+ void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
/*
* Sanity check.
*/
switch (contentType()) {
- case ct_change_cipher_spec:
- case ct_alert:
- case ct_handshake:
- break;
- default:
- throw new RuntimeException("unexpected byte buffers");
+ case ct_change_cipher_spec:
+ case ct_alert:
+ case ct_handshake:
+ break;
+ default:
+ throw new RuntimeException("unexpected byte buffers");
}
/*
@@ -150,10 +193,10 @@
*/
if (!isEmpty()) {
// compress(); // eventually
- encrypt(authenticator, writeCipher);
-
- // send down for processing
- write((OutputStream)null, false, (ByteArrayOutputStream)null);
+ addMAC(writeMAC);
+ encrypt(writeCipher);
+ write((OutputStream)null, false, // send down for processing
+ (ByteArrayOutputStream)null);
}
return;
}
@@ -161,8 +204,8 @@
/**
* Main wrap/write driver.
*/
- void write(EngineArgs ea, Authenticator authenticator,
- CipherBox writeCipher) throws IOException {
+ void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
+ throws IOException {
/*
* sanity check to make sure someone didn't inadvertantly
* send us an impossible combination we don't know how
@@ -174,7 +217,7 @@
* Have we set the MAC's yet? If not, we're not ready
* to process application data yet.
*/
- if (authenticator == MAC.NULL) {
+ if (writeMAC == MAC.NULL) {
return;
}
@@ -212,7 +255,7 @@
*/
int length;
if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
- write(ea, authenticator, writeCipher, 0x01);
+ write(ea, writeMAC, writeCipher, 0x01);
ea.resetLim(); // reset application data buffer limit
length = Math.min(ea.getAppRemaining(),
maxDataSizeMinusOneByteRecord);
@@ -222,14 +265,14 @@
// Don't bother to really write empty records.
if (length > 0) {
- write(ea, authenticator, writeCipher, length);
+ write(ea, writeMAC, writeCipher, length);
}
return;
}
- void write(EngineArgs ea, Authenticator authenticator,
- CipherBox writeCipher, int length) throws IOException {
+ void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher,
+ int length) throws IOException {
/*
* Copy out existing buffer values.
*/
@@ -243,76 +286,39 @@
* Don't need to worry about SSLv2 rewrites, if we're here,
* that's long since done.
*/
- int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize();
+ int dstData = dstPos + headerSize;
dstBB.position(dstData);
- /*
- * transfer application data into the network data buffer
- */
ea.gather(length);
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
/*
* "flip" but skip over header again, add MAC & encrypt
+ * addMAC will expand the limit to reflect the new
+ * data.
*/
- if (authenticator instanceof MAC) {
- MAC signer = (MAC)authenticator;
- if (signer.MAClen() != 0) {
- byte[] hash = signer.compute(contentType(), dstBB);
-
- /*
- * position was advanced to limit in compute above.
- *
- * Mark next area as writable (above layers should have
- * established that we have plenty of room), then write
- * out the hash.
- */
- dstBB.limit(dstBB.limit() + hash.length);
- dstBB.put(hash);
-
- // reset the position and limit
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
- }
- }
+ dstBB.limit(dstBB.position());
+ dstBB.position(dstData);
+ addMAC(writeMAC, dstBB);
- if (!writeCipher.isNullCipher()) {
- /*
- * Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1
- * or later.
- */
- if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
- (writeCipher.isCBCMode() || writeCipher.isAEADMode())) {
- byte[] nonce = writeCipher.createExplicitNonce(
- authenticator, contentType(), dstBB.remaining());
- dstBB.position(dstPos + headerSize);
- dstBB.put(nonce);
- if (!writeCipher.isAEADMode()) {
- // The explicit IV in TLS 1.1 and later can be encrypted.
- dstBB.position(dstPos + headerSize);
- } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
- }
+ /*
+ * Encrypt may pad, so again the limit may have changed.
+ */
+ dstBB.limit(dstBB.position());
+ dstBB.position(dstData);
+ encrypt(writeCipher, dstBB);
- /*
- * Encrypt may pad, so again the limit may have changed.
- */
- writeCipher.encrypt(dstBB, dstLim);
-
- if ((debug != null) && (Debug.isOn("record") ||
- (Debug.isOn("handshake") &&
- (contentType() == ct_change_cipher_spec)))) {
+ if (debug != null
+ && (Debug.isOn("record") || Debug.isOn("handshake"))) {
+ if ((debug != null && Debug.isOn("record"))
+ || contentType() == ct_change_cipher_spec)
System.out.println(Thread.currentThread().getName()
// v3.0/v3.1 ...
+ ", WRITE: " + protocolVersion
+ " " + InputRecord.contentName(contentType())
+ ", length = " + length);
- }
- } else {
- dstBB.position(dstBB.limit());
}
- int packetLength = dstBB.limit() - dstPos - headerSize;
+ int packetLength = dstBB.limit() - dstData;
/*
* Finish out the record header.
@@ -327,5 +333,7 @@
* Position was already set by encrypt() above.
*/
dstBB.limit(dstLim);
+
+ return;
}
}
--- a/jdk/src/share/classes/sun/security/ssl/EngineWriter.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/EngineWriter.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2007, 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
@@ -99,8 +99,7 @@
* other writeRecord.
*/
synchronized void writeRecord(EngineOutputRecord outputRecord,
- Authenticator authenticator,
- CipherBox writeCipher) throws IOException {
+ MAC writeMAC, CipherBox writeCipher) throws IOException {
/*
* Only output if we're still open.
@@ -109,7 +108,7 @@
throw new IOException("writer side was already closed.");
}
- outputRecord.write(authenticator, writeCipher);
+ outputRecord.write(writeMAC, writeCipher);
/*
* Did our handshakers notify that we just sent the
@@ -152,8 +151,7 @@
* Return any determined status.
*/
synchronized HandshakeStatus writeRecord(
- EngineOutputRecord outputRecord, EngineArgs ea,
- Authenticator authenticator,
+ EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC,
CipherBox writeCipher) throws IOException {
/*
@@ -183,7 +181,7 @@
throw new IOException("The write side was already closed");
}
- outputRecord.write(ea, authenticator, writeCipher);
+ outputRecord.write(ea, writeMAC, writeCipher);
if (debug != null && Debug.isOn("packet")) {
dumpPacket(ea, false);
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Tue Mar 12 15:31:49 2013 -0700
@@ -49,7 +49,6 @@
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.CipherSuite.CipherType.*;
/**
* Handshaker ... processes handshake records from an SSL V3.0
@@ -715,47 +714,33 @@
/**
* Create a new read MAC and return it to caller.
*/
- Authenticator newReadAuthenticator()
- throws NoSuchAlgorithmException, InvalidKeyException {
-
- Authenticator authenticator = null;
- if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
- authenticator = new Authenticator(protocolVersion);
+ MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException {
+ MacAlg macAlg = cipherSuite.macAlg;
+ MAC mac;
+ if (isClient) {
+ mac = macAlg.newMac(protocolVersion, svrMacSecret);
+ svrMacSecret = null;
} else {
- MacAlg macAlg = cipherSuite.macAlg;
- if (isClient) {
- authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
- svrMacSecret = null;
- } else {
- authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
- clntMacSecret = null;
- }
+ mac = macAlg.newMac(protocolVersion, clntMacSecret);
+ clntMacSecret = null;
}
-
- return authenticator;
+ return mac;
}
/**
* Create a new write MAC and return it to caller.
*/
- Authenticator newWriteAuthenticator()
- throws NoSuchAlgorithmException, InvalidKeyException {
-
- Authenticator authenticator = null;
- if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
- authenticator = new Authenticator(protocolVersion);
+ MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException {
+ MacAlg macAlg = cipherSuite.macAlg;
+ MAC mac;
+ if (isClient) {
+ mac = macAlg.newMac(protocolVersion, clntMacSecret);
+ clntMacSecret = null;
} else {
- MacAlg macAlg = cipherSuite.macAlg;
- if (isClient) {
- authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
- clntMacSecret = null;
- } else {
- authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
- svrMacSecret = null;
- }
+ mac = macAlg.newMac(protocolVersion, svrMacSecret);
+ svrMacSecret = null;
}
-
- return authenticator;
+ return mac;
}
/*
@@ -1204,23 +1189,11 @@
int prfHashLength = prf.getPRFHashLength();
int prfBlockSize = prf.getPRFBlockSize();
- // TLS v1.1 or later uses an explicit IV in CBC cipher suites to
- // protect against the CBC attacks. AEAD/GCM cipher suites in TLS
- // v1.2 or later use a fixed IV as the implicit part of the partially
- // implicit nonce technique described in RFC 5116.
- int ivSize = cipher.ivSize;
- if (cipher.cipherType == AEAD_CIPHER) {
- ivSize = cipher.fixedIvSize;
- } else if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
- cipher.cipherType == BLOCK_CIPHER) {
- ivSize = 0;
- }
-
TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
masterKey, protocolVersion.major, protocolVersion.minor,
clnt_random.random_bytes, svr_random.random_bytes,
cipher.algorithm, cipher.keySize, expandedKeySize,
- ivSize, hashSize,
+ cipher.ivSize, hashSize,
prfHashAlg, prfHashLength, prfBlockSize);
try {
@@ -1228,15 +1201,14 @@
kg.init(spec);
TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
- // Return null if cipher keys are not supposed to be generated.
clntWriteKey = keySpec.getClientCipherKey();
svrWriteKey = keySpec.getServerCipherKey();
// Return null if IVs are not supposed to be generated.
+ // e.g. TLS 1.1+.
clntWriteIV = keySpec.getClientIv();
svrWriteIV = keySpec.getServerIv();
- // Return null if MAC keys are not supposed to be generated.
clntMacSecret = keySpec.getClientMacKey();
svrMacSecret = keySpec.getServerMacKey();
} catch (GeneralSecurityException e) {
@@ -1261,14 +1233,10 @@
printHex(dump, masterKey.getEncoded());
// Outputs:
- if (clntMacSecret != null) {
- System.out.println("Client MAC write Secret:");
- printHex(dump, clntMacSecret.getEncoded());
- System.out.println("Server MAC write Secret:");
- printHex(dump, svrMacSecret.getEncoded());
- } else {
- System.out.println("... no MAC keys used for this cipher");
- }
+ System.out.println("Client MAC write Secret:");
+ printHex(dump, clntMacSecret.getEncoded());
+ System.out.println("Server MAC write Secret:");
+ printHex(dump, svrMacSecret.getEncoded());
if (clntWriteKey != null) {
System.out.println("Client write key:");
--- a/jdk/src/share/classes/sun/security/ssl/InputRecord.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/InputRecord.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2008, 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
@@ -77,17 +77,6 @@
/*
* Construct the record to hold the maximum sized input record.
* Data will be filled in separately.
- *
- * The structure of the byte buffer looks like:
- *
- * |--------+---------+---------------------------------|
- * | header | IV | content, MAC/TAG, padding, etc. |
- * | headerPlusIVSize |
- *
- * header: the header of an SSL records
- * IV: the optional IV/nonce field, it is only required for block
- * (TLS 1.1 or later) and AEAD cipher suites.
- *
*/
InputRecord() {
super(new byte[maxRecordSize]);
@@ -144,83 +133,44 @@
return handshakeHash;
}
- void decrypt(Authenticator authenticator,
- CipherBox box) throws BadPaddingException {
-
- BadPaddingException bpe = null;
- if (!box.isNullCipher()) {
- try {
- int cipheredLength = count - headerSize;
-
- // apply explicit nonce for AEAD/CBC cipher suites if needed
- int nonceSize = box.applyExplicitNonce(authenticator,
- contentType(), buf, headerSize, cipheredLength);
- pos = headerSize + nonceSize;
- lastHashed = pos; // don't digest the explicit nonce
+ /*
+ * Verify and remove the MAC ... used for all records.
+ */
+ boolean checkMAC(MAC signer) {
+ int len = signer.MAClen();
+ if (len == 0) { // no mac
+ return true;
+ }
- // decrypt the content
- int offset = headerSize;
- if (box.isAEADMode()) {
- // DON'T encrypt the nonce_explicit for AEAD mode
- offset += nonceSize;
- } // The explicit IV for CBC mode can be decrypted.
-
- count = offset + box.decrypt(buf, offset, count - offset);
+ int offset = count - len;
- // Note that we don't remove the nonce from the buffer.
- } catch (BadPaddingException e) {
- // RFC 2246 states that decryption_failed should be used
- // for this purpose. However, that allows certain attacks,
- // so we just send bad record MAC. We also need to make
- // sure to always check the MAC to avoid a timing attack
- // for the same issue. See paper by Vaudenay et al and the
- // update in RFC 4346/5246.
- //
- // Failover to message authenticatoin code checking.
- bpe = new BadPaddingException("invalid padding");
- }
+ if (offset < headerSize) {
+ // data length would be negative, something is wrong
+ return false;
}
- // Requires message authentication code for null, stream and block
- // cipher suites.
- if (authenticator instanceof MAC) {
- MAC signer = (MAC)authenticator;
- int macLen = signer.MAClen();
- if (macLen != 0) {
- int macOffset = count - macLen;
- int contentLen = macOffset - pos;
- if (contentLen < 0) {
- // negative data length, something is wrong
- throw new BadPaddingException("bad record");
- }
+ byte[] mac = signer.compute(contentType(), buf,
+ headerSize, offset - headerSize);
- count -= macLen; // Set the count before any MAC checking
- // exception occurs, so that the following
- // process can read the actual decrypted
- // content (minus the MAC) in the fragment
- // if necessary.
- byte[] hash = signer.compute(contentType(),
- buf, pos, contentLen);
- if (hash == null || macLen != hash.length) {
- // something is wrong with MAC implementation
- throw new RuntimeException("Internal MAC error");
- }
+ if (len != mac.length) {
+ throw new RuntimeException("Internal MAC error");
+ }
- int offset = macOffset;
- for (byte b : hash) {
- if (buf[offset++] != b) {
- throw new BadPaddingException("bad record MAC");
- }
- }
+ for (int i = 0; i < len; i++) {
+ if (buf[offset + i] != mac[i]) {
+ return false;
}
}
+ count -= len;
+ return true;
+ }
- // Is it a failover?
- if (bpe != null) {
- throw bpe;
- }
+ void decrypt(CipherBox box) throws BadPaddingException {
+ int len = count - headerSize;
+ count = headerSize + box.decrypt(buf, headerSize, len);
}
+
/*
* Well ... hello_request messages are _never_ hashed since we can't
* know when they'd appear in the sequence.
--- a/jdk/src/share/classes/sun/security/ssl/JsseJce.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/JsseJce.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, 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
@@ -155,11 +155,6 @@
*/
final static String CIPHER_AES = "AES/CBC/NoPadding";
/**
- * JCE transformation string for AES in GCM mode
- * without padding.
- */
- final static String CIPHER_AES_GCM = "AES/GCM/NoPadding";
- /**
* JCA identifier string for DSA, i.e. a DSA with SHA-1.
*/
final static String SIGNATURE_DSA = "DSA";
--- a/jdk/src/share/classes/sun/security/ssl/MAC.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/MAC.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -39,15 +39,19 @@
/**
* This class computes the "Message Authentication Code" (MAC) for each
- * SSL stream and block cipher message. This is essentially a shared-secret
- * signature, used to provide integrity protection for SSL messages. The
- * MAC is actually one of several keyed hashes, as associated with the cipher
- * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.)
+ * SSL message. This is essentially a shared-secret signature, used to
+ * provide integrity protection for SSL messages. The MAC is actually
+ * one of several keyed hashes, as associated with the cipher suite and
+ * protocol version. (SSL v3.0 uses one construct, TLS uses another.)
+ *
+ * <P>NOTE: MAC computation is the only place in the SSL protocol that the
+ * sequence number is used. It's also reset to zero with each change of
+ * a cipher spec, so this is the only place this state is needed.
*
* @author David Brownell
* @author Andreas Sterbenz
*/
-final class MAC extends Authenticator {
+final class MAC {
final static MAC NULL = new MAC();
@@ -60,9 +64,26 @@
// JCE Mac object
private final Mac mac;
+ // byte array containing the additional information we MAC in each record
+ // (see below)
+ private final byte[] block;
+
+ // sequence number + record type + + record length
+ private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
+
+ // sequence number + record type + protocol version + record length
+ private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
+
+ // offset of record type in block
+ private static final int BLOCK_OFFSET_TYPE = 8;
+
+ // offset of protocol version number in block (TLS only)
+ private static final int BLOCK_OFFSET_VERSION = 8 + 1;
+
private MAC() {
macSize = 0;
mac = null;
+ block = null;
}
/**
@@ -70,8 +91,6 @@
*/
MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
throws NoSuchAlgorithmException, InvalidKeyException {
- super(protocolVersion);
-
this.macSize = macAlg.size;
String algorithm;
@@ -91,6 +110,14 @@
mac = JsseJce.getMac(algorithm);
mac.init(key);
+
+ if (tls) {
+ block = new byte[BLOCK_SIZE_TLS];
+ block[BLOCK_OFFSET_VERSION] = protocolVersion.major;
+ block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
+ } else {
+ block = new byte[BLOCK_SIZE_SSL];
+ }
}
/**
@@ -109,15 +136,7 @@
* @param len the size of the compressed record
*/
final byte[] compute(byte type, byte buf[], int offset, int len) {
- if (macSize == 0) {
- return nullMAC;
- }
-
- byte[] additional = acquireAuthenticationBytes(type, len);
- mac.update(additional);
- mac.update(buf, offset, len);
-
- return mac.doFinal();
+ return compute(type, null, buf, offset, len);
}
/**
@@ -132,13 +151,78 @@
* demarcate the data to be MAC'd.
*/
final byte[] compute(byte type, ByteBuffer bb) {
+ return compute(type, bb, null, 0, bb.remaining());
+ }
+
+ /**
+ * Check whether the sequence number is close to wrap
+ *
+ * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+ * Sequence numbers do not wrap. When the sequence number is near
+ * to wrap, we need to close the connection immediately.
+ */
+ final boolean seqNumOverflow() {
+ /*
+ * Conservatively, we don't allow more records to be generated
+ * when there are only 2^8 sequence numbers left.
+ */
+ return (block != null && mac != null &&
+ block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
+ block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
+ block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
+ block[6] == (byte)0xFF);
+ }
+
+ /*
+ * Check whether to renew the sequence number
+ *
+ * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+ * Sequence numbers do not wrap. If a TLS
+ * implementation would need to wrap a sequence number, it must
+ * renegotiate instead.
+ */
+ final boolean seqNumIsHuge() {
+ /*
+ * Conservatively, we should ask for renegotiation when there are
+ * only 2^48 sequence numbers left.
+ */
+ return (block != null && mac != null &&
+ block[0] == (byte)0xFF && block[1] == (byte)0xFF);
+ }
+
+ // increment the sequence number in the block array
+ // it is a 64-bit number stored in big-endian format
+ private void incrementSequenceNumber() {
+ int k = 7;
+ while ((k >= 0) && (++block[k] == 0)) {
+ k--;
+ }
+ }
+
+ /*
+ * Compute based on either buffer type, either bb.position/limit
+ * or buf/offset/len.
+ */
+ private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
+ int offset, int len) {
+
if (macSize == 0) {
return nullMAC;
}
- byte[] additional = acquireAuthenticationBytes(type, bb.remaining());
- mac.update(additional);
- mac.update(bb);
+ block[BLOCK_OFFSET_TYPE] = type;
+ block[block.length - 2] = (byte)(len >> 8);
+ block[block.length - 1] = (byte)(len );
+
+ mac.update(block);
+ incrementSequenceNumber();
+
+ // content
+ if (bb != null) {
+ mac.update(bb);
+ } else {
+ mac.update(buf, offset, len);
+ }
return mac.doFinal();
}
--- a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Tue Mar 12 15:31:49 2013 -0700
@@ -54,7 +54,6 @@
private int lastHashed;
private boolean firstMessage;
final private byte contentType;
- private int headerOffset;
// current protocol version, sent as record version
ProtocolVersion protocolVersion;
@@ -71,23 +70,6 @@
* Default constructor makes a record supporting the maximum
* SSL record size. It allocates the header bytes directly.
*
- * The structure of the byte buffer looks like:
- *
- * |---------+--------+-------+---------------------------------|
- * | unused | header | IV | content, MAC/TAG, padding, etc. |
- * | headerPlusMaxIVSize |
- *
- * unused: unused part of the buffer of size
- *
- * headerPlusMaxIVSize - header size - IV size
- *
- * When this object is created, we don't know the protocol
- * version number, IV length, etc., so reserve space in front
- * to avoid extra data movement (copies).
- * header: the header of an SSL record
- * IV: the optional IV/nonce field, it is only required for block
- * (TLS 1.1 or later) and AEAD cipher suites.
- *
* @param type the content type for the record
*/
OutputRecord(byte type, int size) {
@@ -95,10 +77,9 @@
this.protocolVersion = ProtocolVersion.DEFAULT;
this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
firstMessage = true;
- count = headerPlusMaxIVSize;
+ count = headerSize;
contentType = type;
lastHashed = count;
- headerOffset = headerPlusMaxIVSize - headerSize;
}
OutputRecord(byte type) {
@@ -138,9 +119,8 @@
@Override
public synchronized void reset() {
super.reset();
- count = headerPlusMaxIVSize;
+ count = headerSize;
lastHashed = count;
- headerOffset = headerPlusMaxIVSize - headerSize;
}
/*
@@ -193,84 +173,58 @@
* of sending empty records over the network.
*/
boolean isEmpty() {
- return count == headerPlusMaxIVSize;
+ return count == headerSize;
}
/*
- * Return true if the record is of an alert of the given description.
- *
- * Per SSL/TLS specifications, alert messages convey the severity of the
- * message (warning or fatal) and a description of the alert. An alert
- * is defined with a two bytes struct, {byte level, byte description},
- * following after the header bytes.
+ * Return true if the record is of a given alert.
*/
boolean isAlert(byte description) {
- if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) {
- return buf[headerPlusMaxIVSize + 1] == description;
+ // An alert is defined with a two bytes struct,
+ // {byte level, byte description}, following after the header bytes.
+ if (count > (headerSize + 1) && contentType == ct_alert) {
+ return buf[headerSize + 1] == description;
}
return false;
}
/*
- * Encrypt ... length may grow due to block cipher padding, or
- * message authentication code or tag.
+ * Compute the MAC and append it to this record. In case we
+ * are automatically flushing a handshake stream, make sure we
+ * have hashed the message first.
*/
- void encrypt(Authenticator authenticator, CipherBox box)
- throws IOException {
-
- // In case we are automatically flushing a handshake stream, make
- // sure we have hashed the message first.
+ void addMAC(MAC signer) throws IOException {
//
// when we support compression, hashing can't go here
// since it'll need to be done on the uncompressed data,
// and the MAC applies to the compressed data.
+ //
if (contentType == ct_handshake) {
doHashes();
}
-
- // Requires message authentication code for stream and block
- // cipher suites.
- if (authenticator instanceof MAC) {
- MAC signer = (MAC)authenticator;
- if (signer.MAClen() != 0) {
- byte[] hash = signer.compute(contentType, buf,
- headerPlusMaxIVSize, count - headerPlusMaxIVSize);
- write(hash);
- }
- }
-
- if (!box.isNullCipher()) {
- // Requires explicit IV/nonce for CBC/AEAD cipher suites for
- // TLS 1.1 or later.
- if ((protocolVersion.v >= ProtocolVersion.TLS11.v) &&
- (box.isCBCMode() || box.isAEADMode())) {
- byte[] nonce = box.createExplicitNonce(authenticator,
- contentType, count - headerPlusMaxIVSize);
- int offset = headerPlusMaxIVSize - nonce.length;
- System.arraycopy(nonce, 0, buf, offset, nonce.length);
- headerOffset = offset - headerSize;
- } else {
- headerOffset = headerPlusMaxIVSize - headerSize;
- }
-
- // encrypt the content
- int offset = headerPlusMaxIVSize;
- if (!box.isAEADMode()) {
- // The explicit IV can be encrypted.
- offset = headerOffset + headerSize;
- } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
-
- count = offset + box.encrypt(buf, offset, count - offset);
+ if (signer.MAClen() != 0) {
+ byte[] hash = signer.compute(contentType, buf,
+ headerSize, count - headerSize);
+ write(hash);
}
}
/*
+ * Encrypt ... length may grow due to block cipher padding
+ */
+ void encrypt(CipherBox box) {
+ int len = count - headerSize;
+ count = headerSize + box.encrypt(buf, headerSize, len);
+ }
+
+
+ /*
* Tell how full the buffer is ... for filling it with application or
* handshake data.
*/
final int availableDataBytes() {
- int dataSize = count - headerPlusMaxIVSize;
+ int dataSize = count - headerSize;
return maxDataSize - dataSize;
}
@@ -316,11 +270,11 @@
* Don't emit content-free records. (Even change cipher spec
* messages have a byte of data!)
*/
- if (count == headerPlusMaxIVSize) {
+ if (count == headerSize) {
return;
}
- int length = count - headerOffset - headerSize;
+ int length = count - headerSize;
// "should" really never write more than about 14 Kb...
if (length < 0) {
throw new SSLException("output record size too small: "
@@ -345,9 +299,7 @@
*/
if (firstMessage && useV2Hello()) {
byte[] v3Msg = new byte[length - 4];
- System.arraycopy(buf, headerPlusMaxIVSize + 4,
- v3Msg, 0, v3Msg.length);
- headerOffset = 0; // reset the header offset
+ System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length);
V3toV2ClientHello(v3Msg);
handshakeHash.reset();
lastHashed = 2;
@@ -362,11 +314,11 @@
/*
* Fill out the header, write it and the message.
*/
- buf[headerOffset + 0] = contentType;
- buf[headerOffset + 1] = protocolVersion.major;
- buf[headerOffset + 2] = protocolVersion.minor;
- buf[headerOffset + 3] = (byte)(length >> 8);
- buf[headerOffset + 4] = (byte)(length);
+ buf[0] = contentType;
+ buf[1] = protocolVersion.major;
+ buf[2] = protocolVersion.minor;
+ buf[3] = (byte)(length >> 8);
+ buf[4] = (byte)(length);
}
firstMessage = false;
@@ -386,8 +338,7 @@
* when holdRecord is true, the implementation in this class
* will be used.
*/
- writeBuffer(heldRecordBuffer,
- buf, headerOffset, count - headerOffset, debugOffset);
+ writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset);
} else {
// It's time to send, do we have buffered data?
// May or may not have a heldRecordBuffer.
@@ -395,18 +346,15 @@
int heldLen = heldRecordBuffer.size();
// Ensure the capacity of this buffer.
- int newCount = count + heldLen - headerOffset;
- ensureCapacity(newCount);
+ ensureCapacity(count + heldLen);
// Slide everything in the buffer to the right.
- System.arraycopy(buf, headerOffset,
- buf, heldLen, count - headerOffset);
+ System.arraycopy(buf, 0, buf, heldLen, count);
// Prepend the held record to the buffer.
System.arraycopy(
heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
- count = newCount;
- headerOffset = 0;
+ count += heldLen;
// Clear the held buffer.
heldRecordBuffer.reset();
@@ -414,8 +362,7 @@
// The held buffer has been dumped, set the debug dump offset.
debugOffset = heldLen;
}
- writeBuffer(s, buf, headerOffset,
- count - headerOffset, debugOffset);
+ writeBuffer(s, buf, 0, count, debugOffset);
}
reset();
@@ -435,11 +382,12 @@
if (debug != null && Debug.isOn("packet")) {
try {
HexDumpEncoder hd = new HexDumpEncoder();
+ ByteBuffer bb = ByteBuffer.wrap(
+ buf, off + debugOffset, len - debugOffset);
System.out.println("[Raw write]: length = " +
- (len - debugOffset));
- hd.encodeBuffer(new ByteArrayInputStream(buf,
- off + debugOffset, len - debugOffset), System.out);
+ bb.remaining());
+ hd.encodeBuffer(bb, System.out);
} catch (IOException e) { }
}
}
@@ -452,13 +400,8 @@
return firstMessage
&& (helloVersion == ProtocolVersion.SSL20Hello)
&& (contentType == ct_handshake)
- && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello)
- // 5: recode header size
- && (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0);
- // V3 session ID is empty
- // 4: handshake header size
- // 2: client_version in ClientHello
- // 32: random in ClientHello
+ && (buf[5] == HandshakeMessage.ht_client_hello)
+ && (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty
}
/*
--- a/jdk/src/share/classes/sun/security/ssl/Record.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/Record.java Tue Mar 12 15:31:49 2013 -0700
@@ -52,29 +52,20 @@
static final int trailerSize = 20; // SHA1 hash size
static final int maxDataSize = 16384; // 2^14 bytes of data
static final int maxPadding = 256; // block cipher padding
- static final int maxIVLength = 256; // IV length
-
- /*
- * The size of the header plus the max IV length
- */
- static final int headerPlusMaxIVSize =
- headerSize // header
- + maxIVLength; // iv
+ static final int maxIVLength = 256; // block length
/*
* SSL has a maximum record size. It's header, (compressed) data,
- * padding, and a trailer for the message authentication information (MAC
- * for block and stream ciphers, and message authentication tag for AEAD
- * ciphers).
- *
+ * padding, and a trailer for the MAC.
* Some compression algorithms have rare cases where they expand the data.
* As we don't support compression at this time, leave that out.
*/
static final int maxRecordSize =
- headerPlusMaxIVSize // header + iv
- + maxDataSize // data
- + maxPadding // padding
- + trailerSize; // MAC or AEAD tag
+ headerSize // header
+ + maxIVLength // iv
+ + maxDataSize // data
+ + maxPadding // padding
+ + trailerSize; // MAC
static final boolean enableCBCProtection =
Debug.getBooleanProperty("jsse.enableCBCProtection", true);
@@ -86,7 +77,8 @@
static final int maxDataSizeMinusOneByteRecord =
maxDataSize // max data size
- ( // max one byte record size
- headerPlusMaxIVSize // header + iv
+ headerSize // header
+ + maxIVLength // iv
+ 1 // one byte data
+ maxPadding // padding
+ trailerSize // MAC
@@ -112,10 +104,11 @@
* Allocate a smaller array.
*/
static final int maxAlertRecordSize =
- headerPlusMaxIVSize // header + iv
- + 2 // alert
- + maxPadding // padding
- + trailerSize; // MAC
+ headerSize // header
+ + maxIVLength // iv
+ + 2 // alert
+ + maxPadding // padding
+ + trailerSize; // MAC
/*
* The overflow values of integers of 8, 16 and 24 bits.
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Tue Mar 12 15:31:49 2013 -0700
@@ -280,7 +280,7 @@
/*
* Crypto state that's reinitialized when the session changes.
*/
- private Authenticator readAuthenticator, writeAuthenticator;
+ private MAC readMAC, writeMAC;
private CipherBox readCipher, writeCipher;
// NOTE: compression state would be saved here
@@ -377,9 +377,9 @@
* Note: compression support would go here too
*/
readCipher = CipherBox.NULL;
- readAuthenticator = MAC.NULL;
+ readMAC = MAC.NULL;
writeCipher = CipherBox.NULL;
- writeAuthenticator = MAC.NULL;
+ writeMAC = MAC.NULL;
// default security parameters for secure renegotiation
secureRenegotiation = false;
@@ -586,7 +586,7 @@
try {
readCipher = handshaker.newReadCipher();
- readAuthenticator = handshaker.newReadAuthenticator();
+ readMAC = handshaker.newReadMAC();
} catch (GeneralSecurityException e) {
// "can't happen"
throw new SSLException("Algorithm missing: ", e);
@@ -622,7 +622,7 @@
try {
writeCipher = handshaker.newWriteCipher();
- writeAuthenticator = handshaker.newWriteAuthenticator();
+ writeMAC = handshaker.newWriteMAC();
} catch (GeneralSecurityException e) {
// "can't happen"
throw new SSLException("Algorithm missing: ", e);
@@ -958,15 +958,34 @@
* throw a fatal alert if the integrity check fails.
*/
try {
- decryptedBB = inputRecord.decrypt(
- readAuthenticator, readCipher, readBB);
+ decryptedBB = inputRecord.decrypt(readCipher, readBB);
} catch (BadPaddingException e) {
+ // RFC 2246 states that decryption_failed should be used
+ // for this purpose. However, that allows certain attacks,
+ // so we just send bad record MAC. We also need to make
+ // sure to always check the MAC to avoid a timing attack
+ // for the same issue. See paper by Vaudenay et al.
+ //
+ // rewind the BB if necessary.
+ readBB.rewind();
+
+ inputRecord.checkMAC(readMAC, readBB);
+
// use the same alert types as for MAC failure below
byte alertType = (inputRecord.contentType() ==
Record.ct_handshake) ?
Alerts.alert_handshake_failure :
Alerts.alert_bad_record_mac;
- fatal(alertType, e.getMessage(), e);
+ fatal(alertType, "Invalid padding", e);
+ }
+
+ if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
+ if (inputRecord.contentType() == Record.ct_handshake) {
+ fatal(Alerts.alert_handshake_failure,
+ "bad handshake record MAC");
+ } else {
+ fatal(Alerts.alert_bad_record_mac, "bad record MAC");
+ }
}
// if (!inputRecord.decompress(c))
@@ -1118,7 +1137,7 @@
hsStatus = getHSStatus(hsStatus);
if (connectionState < cs_ERROR && !isInboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
- if (checkSequenceNumber(readAuthenticator,
+ if (checkSequenceNumber(readMAC,
inputRecord.contentType())) {
hsStatus = getHSStatus(null);
}
@@ -1271,7 +1290,7 @@
// eventually compress as well.
HandshakeStatus hsStatus =
- writer.writeRecord(eor, ea, writeAuthenticator, writeCipher);
+ writer.writeRecord(eor, ea, writeMAC, writeCipher);
/*
* We only need to check the sequence number state for
@@ -1288,7 +1307,7 @@
hsStatus = getHSStatus(hsStatus);
if (connectionState < cs_ERROR && !isOutboundDone() &&
(hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
- if (checkSequenceNumber(writeAuthenticator, eor.contentType())) {
+ if (checkSequenceNumber(writeMAC, eor.contentType())) {
hsStatus = getHSStatus(null);
}
}
@@ -1327,7 +1346,7 @@
*/
void writeRecord(EngineOutputRecord eor) throws IOException {
// eventually compress as well.
- writer.writeRecord(eor, writeAuthenticator, writeCipher);
+ writer.writeRecord(eor, writeMAC, writeCipher);
/*
* Check the sequence number state
@@ -1341,7 +1360,7 @@
* of the last record cannot be wrapped.
*/
if ((connectionState < cs_ERROR) && !isOutboundDone()) {
- checkSequenceNumber(writeAuthenticator, eor.contentType());
+ checkSequenceNumber(writeMAC, eor.contentType());
}
}
@@ -1359,14 +1378,14 @@
*
* Return true if the handshake status may be changed.
*/
- private boolean checkSequenceNumber(Authenticator authenticator, byte type)
+ private boolean checkSequenceNumber(MAC mac, byte type)
throws IOException {
/*
* Don't bother to check the sequence number for error or
* closed connections, or NULL MAC
*/
- if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
+ if (connectionState >= cs_ERROR || mac == MAC.NULL) {
return false;
}
@@ -1374,7 +1393,7 @@
* Conservatively, close the connection immediately when the
* sequence number is close to overflow
*/
- if (authenticator.seqNumOverflow()) {
+ if (mac.seqNumOverflow()) {
/*
* TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert
@@ -1397,7 +1416,7 @@
* Don't bother to kickstart the renegotiation when the local is
* asking for it.
*/
- if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
+ if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) {
System.out.println(Thread.currentThread().getName() +
", request renegotiation " +
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Tue Mar 12 15:31:49 2013 -0700
@@ -292,7 +292,7 @@
/*
* Crypto state that's reinitialized when the session changes.
*/
- private Authenticator readAuthenticator, writeAuthenticator;
+ private MAC readMAC, writeMAC;
private CipherBox readCipher, writeCipher;
// NOTE: compression state would be saved here
@@ -586,9 +586,9 @@
* Note: compression support would go here too
*/
readCipher = CipherBox.NULL;
- readAuthenticator = MAC.NULL;
+ readMAC = MAC.NULL;
writeCipher = CipherBox.NULL;
- writeAuthenticator = MAC.NULL;
+ writeMAC = MAC.NULL;
// initial security parameters for secure renegotiation
secureRenegotiation = false;
@@ -829,7 +829,8 @@
boolean holdRecord) throws IOException {
// r.compress(c);
- r.encrypt(writeAuthenticator, writeCipher);
+ r.addMAC(writeMAC);
+ r.encrypt(writeCipher);
if (holdRecord) {
// If we were requested to delay the record due to possibility
@@ -860,7 +861,7 @@
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR) {
- checkSequenceNumber(writeAuthenticator, r.contentType());
+ checkSequenceNumber(writeMAC, r.contentType());
}
// turn off the flag of the first application record
@@ -985,14 +986,29 @@
* throw a fatal alert if the integrity check fails.
*/
try {
- r.decrypt(readAuthenticator, readCipher);
+ r.decrypt(readCipher);
} catch (BadPaddingException e) {
+ // RFC 2246 states that decryption_failed should be used
+ // for this purpose. However, that allows certain attacks,
+ // so we just send bad record MAC. We also need to make
+ // sure to always check the MAC to avoid a timing attack
+ // for the same issue. See paper by Vaudenay et al.
+ r.checkMAC(readMAC);
// use the same alert types as for MAC failure below
byte alertType = (r.contentType() == Record.ct_handshake)
? Alerts.alert_handshake_failure
: Alerts.alert_bad_record_mac;
- fatal(alertType, e.getMessage(), e);
+ fatal(alertType, "Invalid padding", e);
}
+ if (!r.checkMAC(readMAC)) {
+ if (r.contentType() == Record.ct_handshake) {
+ fatal(Alerts.alert_handshake_failure,
+ "bad handshake record MAC");
+ } else {
+ fatal(Alerts.alert_bad_record_mac, "bad record MAC");
+ }
+ }
+
// if (!r.decompress(c))
// fatal(Alerts.alert_decompression_failure,
@@ -1143,7 +1159,7 @@
* of the last record cannot be wrapped.
*/
if (connectionState < cs_ERROR) {
- checkSequenceNumber(readAuthenticator, r.contentType());
+ checkSequenceNumber(readMAC, r.contentType());
}
return;
@@ -1166,14 +1182,14 @@
* implementation would need to wrap a sequence number, it must
* renegotiate instead."
*/
- private void checkSequenceNumber(Authenticator authenticator, byte type)
+ private void checkSequenceNumber(MAC mac, byte type)
throws IOException {
/*
* Don't bother to check the sequence number for error or
* closed connections, or NULL MAC.
*/
- if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
+ if (connectionState >= cs_ERROR || mac == MAC.NULL) {
return;
}
@@ -1181,7 +1197,7 @@
* Conservatively, close the connection immediately when the
* sequence number is close to overflow
*/
- if (authenticator.seqNumOverflow()) {
+ if (mac.seqNumOverflow()) {
/*
* TLS protocols do not define a error alert for sequence
* number overflow. We use handshake_failure error alert
@@ -1203,7 +1219,7 @@
* Don't bother to kickstart the renegotiation when the local is
* asking for it.
*/
- if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
+ if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
if (debug != null && Debug.isOn("ssl")) {
System.out.println(Thread.currentThread().getName() +
", request renegotiation " +
@@ -2065,7 +2081,7 @@
try {
readCipher = handshaker.newReadCipher();
- readAuthenticator = handshaker.newReadAuthenticator();
+ readMAC = handshaker.newReadMAC();
} catch (GeneralSecurityException e) {
// "can't happen"
throw new SSLException("Algorithm missing: ", e);
@@ -2096,7 +2112,7 @@
try {
writeCipher = handshaker.newWriteCipher();
- writeAuthenticator = handshaker.newWriteAuthenticator();
+ writeMAC = handshaker.newWriteMAC();
} catch (GeneralSecurityException e) {
// "can't happen"
throw new SSLException("Algorithm missing: ", e);
--- a/jdk/test/sun/security/ec/TestEC.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/ec/TestEC.java Tue Mar 12 15:31:49 2013 -0700
@@ -21,11 +21,6 @@
* questions.
*/
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
/**
* @test
* @bug 6840752
@@ -35,7 +30,7 @@
* @library ../pkcs11/sslecc
* @library ../../../java/security/testlibrary
* @compile -XDignore.symbol.file TestEC.java
- * @run main/othervm TestEC
+ * @run main TestEC
*/
import java.security.NoSuchProviderException;
--- a/jdk/test/sun/security/pkcs11/fips/CipherTest.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/pkcs11/fips/CipherTest.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, 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
@@ -147,25 +147,6 @@
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
- CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
-
- CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
- CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
// cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, 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
@@ -147,25 +147,6 @@
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
- CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
-
- CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
- CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
// cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Tue Mar 12 15:31:49 2013 -0700
@@ -21,16 +21,14 @@
* questions.
*/
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
/*
* @test
* @bug 7031830
* @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine
* @run main/othervm SSLEngineBadBufferArrayAccess
+ *
+ * SunJSSE does not support dynamic system properties, no way to re-use
+ * system properties in samevm/agentvm mode.
*/
/**
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java Tue Mar 12 10:35:44 2013 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,445 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
-/*
- * @test
- * @bug 7030966
- * @summary Support AEAD CipherSuites
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_128_GCM_SHA256
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_128_GCM_SHA256
- */
-
-/*
- * Need additional key materials to run the following cases.
- *
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- *
- * Need unlimited JCE Unlimited Strength Jurisdiction Policy to run the
- * following cases.
- *
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_256_GCM_SHA384
- */
-
-import java.net.*;
-import java.util.*;
-import java.io.*;
-import javax.net.ssl.*;
-import java.security.Security;
-import java.security.KeyStore;
-import java.security.KeyFactory;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.security.spec.*;
-import java.security.interfaces.*;
-import sun.misc.BASE64Decoder;
-
-
-public class ShortRSAKeyGCM {
-
- /*
- * =============================================================
- * Set the various variables needed for the tests, then
- * specify what tests to run on each side.
- */
-
- /*
- * Should we run the client or server in a separate thread?
- * Both sides can throw exceptions, but do you have a preference
- * as to which side should be the main thread.
- */
- static boolean separateServerThread = true;
-
- /*
- * Where do we find the keystores?
- */
- // Certificates and key used in the test.
- static String trustedCertStr =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
- "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
- "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
- "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
- "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" +
- "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" +
- "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" +
- "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" +
- "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" +
- "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
- "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
- "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" +
- "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" +
- "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" +
- "-----END CERTIFICATE-----";
-
- static String targetCertStr =
- "-----BEGIN CERTIFICATE-----\n" +
- "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
- "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
- "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
- "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
- "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" +
- "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" +
- "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" +
- "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" +
- "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" +
- "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" +
- "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" +
- "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" +
- "-----END CERTIFICATE-----";
-
- // Private key in the format of PKCS#8, key size is 512 bits.
- static String targetPrivateKey =
- "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" +
- "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" +
- "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" +
- "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" +
- "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" +
- "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" +
- "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" +
- "3fnqsTgaUs4=";
-
- static char passphrase[] = "passphrase".toCharArray();
-
- /*
- * Is the server ready to serve?
- */
- volatile static boolean serverReady = false;
-
- /*
- * Turn on SSL debugging?
- */
- static boolean debug = false;
-
- /*
- * Define the server side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doServerSide() throws Exception {
- SSLContext context = generateSSLContext(null, targetCertStr,
- targetPrivateKey);
- SSLServerSocketFactory sslssf = context.getServerSocketFactory();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket)sslssf.createServerSocket(serverPort);
- serverPort = sslServerSocket.getLocalPort();
-
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
-
- SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
- sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslIS.read();
- sslOS.write('A');
- sslOS.flush();
-
- sslSocket.close();
- }
-
- /*
- * Define the client side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doClientSide() throws Exception {
-
- /*
- * Wait for server to get started.
- */
- while (!serverReady) {
- Thread.sleep(50);
- }
-
- SSLContext context = generateSSLContext(trustedCertStr, null, null);
- SSLSocketFactory sslsf = context.getSocketFactory();
-
- SSLSocket sslSocket =
- (SSLSocket)sslsf.createSocket("localhost", serverPort);
-
- // enable TLSv1.2 only
- sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
-
- // enable a block cipher
- sslSocket.setEnabledCipherSuites(new String[] {cipherSuite});
-
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslOS.write('B');
- sslOS.flush();
- sslIS.read();
-
- sslSocket.close();
- }
-
- /*
- * =============================================================
- * The remainder is just support stuff
- */
- private static String tmAlgorithm; // trust manager
- private static String cipherSuite; // cipher suite
-
- private static void parseArguments(String[] args) {
- tmAlgorithm = args[0];
- cipherSuite = args[1];
- }
-
- private static SSLContext generateSSLContext(String trustedCertStr,
- String keyCertStr, String keySpecStr) throws Exception {
-
- // generate certificate from cert string
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
-
- // create a key store
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(null, null);
-
- // import the trused cert
- Certificate trusedCert = null;
- ByteArrayInputStream is = null;
- if (trustedCertStr != null) {
- is = new ByteArrayInputStream(trustedCertStr.getBytes());
- trusedCert = cf.generateCertificate(is);
- is.close();
-
- ks.setCertificateEntry("RSA Export Signer", trusedCert);
- }
-
- if (keyCertStr != null) {
- // generate the private key.
- PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
- new BASE64Decoder().decodeBuffer(keySpecStr));
- KeyFactory kf = KeyFactory.getInstance("RSA");
- RSAPrivateKey priKey =
- (RSAPrivateKey)kf.generatePrivate(priKeySpec);
-
- // generate certificate chain
- is = new ByteArrayInputStream(keyCertStr.getBytes());
- Certificate keyCert = cf.generateCertificate(is);
- is.close();
-
- Certificate[] chain = null;
- if (trusedCert != null) {
- chain = new Certificate[2];
- chain[0] = keyCert;
- chain[1] = trusedCert;
- } else {
- chain = new Certificate[1];
- chain[0] = keyCert;
- }
-
- // import the key entry.
- ks.setKeyEntry("Whatever", priKey, passphrase, chain);
- }
-
- // create SSL context
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
- tmf.init(ks);
-
- SSLContext ctx = SSLContext.getInstance("TLS");
- if (keyCertStr != null && !keyCertStr.isEmpty()) {
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
- kmf.init(ks, passphrase);
-
- ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
- ks = null;
- } else {
- ctx.init(null, tmf.getTrustManagers(), null);
- }
-
- return ctx;
- }
-
-
- // use any free port by default
- volatile int serverPort = 0;
-
- volatile Exception serverException = null;
- volatile Exception clientException = null;
-
- public static void main(String[] args) throws Exception {
- // reset the security property to make sure that the algorithms
- // and keys used in this test are not disabled.
- Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2");
-
- if (debug) {
- System.setProperty("javax.net.debug", "all");
- }
-
- /*
- * Get the customized arguments.
- */
- parseArguments(args);
-
- /*
- * Start the tests.
- */
- new ShortRSAKeyGCM();
- }
-
- Thread clientThread = null;
- Thread serverThread = null;
-
- /*
- * Primary constructor, used to drive remainder of the test.
- *
- * Fork off the other side, then do your work.
- */
- ShortRSAKeyGCM() throws Exception {
- try {
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
- } catch (Exception e) {
- // swallow for now. Show later
- }
-
- /*
- * Wait for other side to close down.
- */
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
-
- /*
- * When we get here, the test is pretty much over.
- * Which side threw the error?
- */
- Exception local;
- Exception remote;
- String whichRemote;
-
- if (separateServerThread) {
- remote = serverException;
- local = clientException;
- whichRemote = "server";
- } else {
- remote = clientException;
- local = serverException;
- whichRemote = "client";
- }
-
- /*
- * If both failed, return the curthread's exception, but also
- * print the remote side Exception
- */
- if ((local != null) && (remote != null)) {
- System.out.println(whichRemote + " also threw:");
- remote.printStackTrace();
- System.out.println();
- throw local;
- }
-
- if (remote != null) {
- throw remote;
- }
-
- if (local != null) {
- throw local;
- }
- }
-
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- /*
- * Our server thread just died.
- *
- * Release the client, if not active already...
- */
- System.err.println("Server died..." + e);
- serverReady = true;
- serverException = e;
- }
- }
- };
- serverThread.start();
- } else {
- try {
- doServerSide();
- } catch (Exception e) {
- serverException = e;
- } finally {
- serverReady = true;
- }
- }
- }
-
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died..." + e);
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- try {
- doClientSide();
- } catch (Exception e) {
- clientException = e;
- }
- }
- }
-}
--- a/jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Tue Mar 12 15:31:49 2013 -0700
@@ -21,15 +21,13 @@
* questions.
*/
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
/*
* @test
* @bug 7174244
* @summary NPE in Krb5ProxyImpl.getServerKeys()
+ *
+ * SunJSSE does not support dynamic system properties, no way to re-use
+ * system properties in samevm/agentvm mode.
* @run main/othervm CipherSuitesInOrder
*/
@@ -74,22 +72,6 @@
"SSL_RSA_WITH_RC4_128_SHA",
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDH_RSA_WITH_RC4_128_SHA",
-
- "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
- "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
- "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
- "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
- "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
-
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -101,9 +83,6 @@
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
- "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
- "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
-
"TLS_DH_anon_WITH_AES_256_CBC_SHA256",
"TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
"TLS_DH_anon_WITH_AES_256_CBC_SHA",
--- a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, 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
@@ -148,25 +148,6 @@
CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),
CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),
- CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
-
- CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
- CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
- CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
- CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
-
// cipher suites obsoleted since TLS 1.2
CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- a/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java Tue Mar 12 15:31:49 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -21,15 +21,14 @@
* questions.
*/
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
/*
* @test
* @bug 7105780
* @summary Add SSLSocket client/SSLEngine server to templates directory.
+ *
+ * SunJSSE does not support dynamic system properties, no way to re-use
+ * system properties in samevm/agentvm mode.
+ *
* @run main/othervm SSLSocketSSLEngineTemplate
*/