src/java.base/share/classes/sun/security/ssl/CipherBox.java
Print this page
*** 152,164 ****
/**
* NULL cipherbox. Identity operation, no encryption.
*/
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;
--- 152,164 ----
/**
* NULL cipherbox. Identity operation, no encryption.
*/
private CipherBox() {
! this.protocolVersion = ProtocolVersion.DEFAULT_TLS;
this.cipher = null;
! this.cipherType = NULL_CIPHER;
this.fixedIv = new byte[0];
this.key = null;
this.mode = Cipher.ENCRYPT_MODE; // choose at random
this.random = null;
this.tagSize = 0;
*** 195,205 ****
* value generated by Cipher.init() for encryption, and a fixed
* mask for decryption.
*/
if (iv == null && bulkCipher.ivSize != 0 &&
mode == Cipher.DECRYPT_MODE &&
! protocolVersion.v >= ProtocolVersion.TLS11.v) {
iv = getFixedMask(bulkCipher.ivSize);
}
if (cipherType == AEAD_CIPHER) {
// AEAD must completely initialize the cipher for each packet,
--- 195,205 ----
* value generated by Cipher.init() for encryption, and a fixed
* mask for decryption.
*/
if (iv == null && bulkCipher.ivSize != 0 &&
mode == Cipher.DECRYPT_MODE &&
! protocolVersion.useTLS11PlusSpec()) {
iv = getFixedMask(bulkCipher.ivSize);
}
if (cipherType == AEAD_CIPHER) {
// AEAD must completely initialize the cipher for each packet,
*** 489,499 ****
if (cipherType == BLOCK_CIPHER) {
int blockSize = cipher.getBlockSize();
newLen = removePadding(
buf, offset, newLen, tagLen, blockSize, protocolVersion);
! if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
}
}
--- 489,499 ----
if (cipherType == BLOCK_CIPHER) {
int blockSize = cipher.getBlockSize();
newLen = removePadding(
buf, offset, newLen, tagLen, blockSize, protocolVersion);
! if (protocolVersion.useTLS11PlusSpec()) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
}
}
*** 571,581 ****
int blockSize = cipher.getBlockSize();
bb.position(pos);
newLen = removePadding(bb, tagLen, 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");
}
// reset the position to the end of the decrypted data
--- 571,581 ----
int blockSize = cipher.getBlockSize();
bb.position(pos);
newLen = removePadding(bb, tagLen, blockSize, protocolVersion);
// check the explicit IV of TLS v1.1 or later
! if (protocolVersion.useTLS11PlusSpec()) {
if (newLen < blockSize) {
throw new BadPaddingException("invalid explicit IV");
}
// reset the position to the end of the decrypted data
*** 744,754 ****
}
// The padding data should be filled with the padding length value.
int[] results = checkPadding(buf, offset + newLen,
padLen + 1, (byte)(padLen & 0xFF));
! if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
if (results[0] != 0) { // padding data has invalid bytes
throw new BadPaddingException("Invalid TLS padding data");
}
} else { // SSLv3
// SSLv3 requires 0 <= length byte < block size
--- 744,754 ----
}
// The padding data should be filled with the padding length value.
int[] results = checkPadding(buf, offset + newLen,
padLen + 1, (byte)(padLen & 0xFF));
! if (protocolVersion.useTLS10PlusSpec()) {
if (results[0] != 0) { // padding data has invalid bytes
throw new BadPaddingException("Invalid TLS padding data");
}
} else { // SSLv3
// SSLv3 requires 0 <= length byte < block size
*** 790,800 ****
// The padding data should be filled with the padding length value.
int[] results = checkPadding(
bb.duplicate().position(offset + newLen),
(byte)(padLen & 0xFF));
! if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
if (results[0] != 0) { // padding data has invalid bytes
throw new BadPaddingException("Invalid TLS padding data");
}
} else { // SSLv3
// SSLv3 requires 0 <= length byte < block size
--- 790,800 ----
// The padding data should be filled with the padding length value.
int[] results = checkPadding(
bb.duplicate().position(offset + newLen),
(byte)(padLen & 0xFF));
! if (protocolVersion.useTLS10PlusSpec()) {
if (results[0] != 0) { // padding data has invalid bytes
throw new BadPaddingException("Invalid TLS padding data");
}
} else { // SSLv3
// SSLv3 requires 0 <= length byte < block size
*** 871,881 ****
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;
--- 871,881 ----
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.useTLS11PlusSpec()) {
return cipher.getBlockSize();
}
break;
case AEAD_CIPHER:
return recordIvSize;
*** 900,910 ****
* @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:
// sanity check length of the ciphertext
int tagLen = (authenticator instanceof MAC) ?
((MAC)authenticator).MAClen() : 0;
--- 900,910 ----
* @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, byte[] sequence) throws BadPaddingException {
switch (cipherType) {
case BLOCK_CIPHER:
// sanity check length of the ciphertext
int tagLen = (authenticator instanceof MAC) ?
((MAC)authenticator).MAClen() : 0;
*** 916,926 ****
}
// 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)) {
--- 916,926 ----
}
// For block ciphers, the explicit IV length is of length
// SecurityParameters.record_iv_length, which is equal to
// the SecurityParameters.block_size.
! if (protocolVersion.useTLS11PlusSpec()) {
return cipher.getBlockSize();
}
break;
case AEAD_CIPHER:
if (bb.remaining() < (recordIvSize + tagSize)) {
*** 943,953 ****
"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.
--- 943,954 ----
"invalid key or spec in GCM mode", ikae);
}
// update the additional authentication data
byte[] aad = authenticator.acquireAuthenticationBytes(
! contentType, bb.remaining() - recordIvSize - tagSize,
! sequence);
cipher.updateAAD(aad);
return recordIvSize;
// It is also the length of sequence number, which is
// used as the nonce_explicit for AEAD cipher suites.
*** 955,991 ****
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
--- 956,965 ----
*** 1003,1013 ****
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.
--- 977,987 ----
byte contentType, int fragmentLength) {
byte[] nonce = new byte[0];
switch (cipherType) {
case BLOCK_CIPHER:
! if (protocolVersion.useTLS11PlusSpec()) {
// 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.
*** 1032,1051 ****
// 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
--- 1006,1113 ----
// unlikely to happen
throw new RuntimeException(
"invalid key or spec in GCM mode", ikae);
}
! // Update the additional authentication data, using the
! // implicit sequence number of the authenticator.
byte[] aad = authenticator.acquireAuthenticationBytes(
! contentType, fragmentLength, null);
cipher.updateAAD(aad);
break;
}
return nonce;
}
+ // See also CipherSuite.calculatePacketSize().
+ int calculatePacketSize(int fragmentSize, int macLen, int headerSize) {
+ int packetSize = fragmentSize;
+ if (cipher != null) {
+ int blockSize = cipher.getBlockSize();
+ switch (cipherType) {
+ case BLOCK_CIPHER:
+ packetSize += macLen;
+ packetSize += 1; // 1 byte padding length field
+ packetSize += // use the minimal padding
+ (blockSize - (packetSize % blockSize)) % blockSize;
+ if (protocolVersion.useTLS11PlusSpec()) {
+ packetSize += blockSize; // explicit IV
+ }
+
+ break;
+ case AEAD_CIPHER:
+ packetSize += recordIvSize;
+ packetSize += tagSize;
+
+ break;
+ default: // NULL_CIPHER or STREAM_CIPHER
+ packetSize += macLen;
+ }
+ }
+
+ return packetSize + headerSize;
+ }
+
+ // See also CipherSuite.calculateFragSize().
+ int calculateFragmentSize(int packetLimit, int macLen, int headerSize) {
+ int fragLen = packetLimit - headerSize;
+ if (cipher != null) {
+ int blockSize = cipher.getBlockSize();
+ switch (cipherType) {
+ case BLOCK_CIPHER:
+ if (protocolVersion.useTLS11PlusSpec()) {
+ fragLen -= blockSize; // explicit IV
+ }
+ fragLen -= (fragLen % blockSize); // cannot hold a block
+ // No padding for a maximum fragment.
+ fragLen -= 1; // 1 byte padding length field: 0x00
+ fragLen -= macLen;
+
+ break;
+ case AEAD_CIPHER:
+ fragLen -= recordIvSize;
+ fragLen -= tagSize;
+
+ break;
+ default: // NULL_CIPHER or STREAM_CIPHER
+ fragLen -= macLen;
+ }
+ }
+
+ return fragLen;
+ }
+
+ // Estimate the maximum fragment size of a received packet.
+ int estimateFragmentSize(int packetSize, int macLen, int headerSize) {
+ int fragLen = packetSize - headerSize;
+ if (cipher != null) {
+ int blockSize = cipher.getBlockSize();
+ switch (cipherType) {
+ case BLOCK_CIPHER:
+ if (protocolVersion.useTLS11PlusSpec()) {
+ fragLen -= blockSize; // explicit IV
+ }
+ // No padding for a maximum fragment.
+ fragLen -= 1; // 1 byte padding length field: 0x00
+ fragLen -= macLen;
+
+ break;
+ case AEAD_CIPHER:
+ fragLen -= recordIvSize;
+ fragLen -= tagSize;
+
+ break;
+ default: // NULL_CIPHER or STREAM_CIPHER
+ fragLen -= macLen;
+ }
+ }
+
+ return fragLen;
+ }
+
+
/*
* 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
*** 1098,1108 ****
int blockSize = cipher.getBlockSize();
if ((fragmentLen % blockSize) == 0) {
int minimal = tagLen + 1;
minimal = (minimal >= blockSize) ? minimal : blockSize;
! if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
minimal += blockSize; // plus the size of the explicit IV
}
return (fragmentLen >= minimal);
}
--- 1160,1170 ----
int blockSize = cipher.getBlockSize();
if ((fragmentLen % blockSize) == 0) {
int minimal = tagLen + 1;
minimal = (minimal >= blockSize) ? minimal : blockSize;
! if (protocolVersion.useTLS11PlusSpec()) {
minimal += blockSize; // plus the size of the explicit IV
}
return (fragmentLen >= minimal);
}