# HG changeset patch # User wetmore # Date 1363127509 25200 # Node ID 36055e4b5305230c9355a2b9f914f1b8fe7a6749 # Parent b9fb0d9c58eca7a95064933f43d5badc0f6dde96 8009925: Back out AEAD CipherSuites temporarily Reviewed-by: valeriep diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java --- 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); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java --- 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; } diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java --- 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 @@ * new TlsKeymaterialSpec(clientMacKey, serverMacKey, * null, null, null, null). * - * @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 @@ * new TlsKeymaterialSpec(clientMacKey, serverMacKey, * clientCipherKey, serverCipherKey, null, null). * - * @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; diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java --- 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, diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/Authenticator.java --- 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; - } - -} diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/CipherBox.java --- 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; } } diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/CipherSuite.java --- 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); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java --- 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); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java --- 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. + *

+ * 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; } } diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/EngineWriter.java --- 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); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/Handshaker.java --- 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:"); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/InputRecord.java --- 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. diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/JsseJce.java --- 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"; diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/MAC.java --- 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.) + * + *

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(); } diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/OutputRecord.java --- 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 } /* diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/Record.java --- 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. diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java --- 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 " + diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java --- 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); diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ec/TestEC.java --- 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; diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/pkcs11/fips/CipherTest.java --- 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), diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/pkcs11/sslecc/CipherTest.java --- 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), diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java --- 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. */ /** diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java --- 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; - } - } - } -} diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java --- 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", diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ssl/sanity/interop/CipherTest.java --- 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), diff -r b9fb0d9c58ec -r 36055e4b5305 jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java --- 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 */