--- a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java Tue Mar 12 10:35:44 2013 -0400
+++ b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java Tue Mar 12 15:31:49 2013 -0700
@@ -29,6 +29,7 @@
import java.io.*;
import java.nio.*;
+
/**
* A OutputRecord class extension which uses external ByteBuffers
* or the internal ByteArrayOutputStream for data manipulations.
@@ -100,6 +101,51 @@
return finishedMsg;
}
+
+ /**
+ * Calculate the MAC value, storing the result either in
+ * the internal buffer, or at the end of the destination
+ * ByteBuffer.
+ * <P>
+ * We assume that the higher levels have assured us enough
+ * room, otherwise we'll indirectly throw a
+ * BufferOverFlowException runtime exception.
+ *
+ * position should equal limit, and points to the next
+ * free spot.
+ */
+ private void addMAC(MAC signer, ByteBuffer bb)
+ throws IOException {
+
+ if (signer.MAClen() != 0) {
+ byte[] hash = signer.compute(contentType(), bb);
+
+ /*
+ * position was advanced to limit in compute above.
+ *
+ * Mark next area as writable (above layers should have
+ * established that we have plenty of room), then write
+ * out the hash.
+ */
+ bb.limit(bb.limit() + hash.length);
+ bb.put(hash);
+ }
+ }
+
+ /*
+ * Encrypt a ByteBuffer.
+ *
+ * We assume that the higher levels have assured us enough
+ * room for the encryption (plus padding), otherwise we'll
+ * indirectly throw a BufferOverFlowException runtime exception.
+ *
+ * position and limit will be the same, and points to the
+ * next free spot.
+ */
+ void encrypt(CipherBox box, ByteBuffer bb) {
+ box.encrypt(bb);
+ }
+
/*
* Override the actual write below. We do things this way to be
* consistent with InputRecord. InputRecord may try to write out
@@ -114,8 +160,7 @@
* Copy data out of buffer, it's ready to go.
*/
ByteBuffer netBB = (ByteBuffer)
- ByteBuffer.allocate(len).put(buf, off, len).flip();
-
+ ByteBuffer.allocate(len).put(buf, 0, len).flip();
writer.putOutboundData(netBB);
}
@@ -123,19 +168,17 @@
* Main method for writing non-application data.
* We MAC/encrypt, then send down for processing.
*/
- void write(Authenticator authenticator, CipherBox writeCipher)
- throws IOException {
-
+ void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
/*
* Sanity check.
*/
switch (contentType()) {
- case ct_change_cipher_spec:
- case ct_alert:
- case ct_handshake:
- break;
- default:
- throw new RuntimeException("unexpected byte buffers");
+ case ct_change_cipher_spec:
+ case ct_alert:
+ case ct_handshake:
+ break;
+ default:
+ throw new RuntimeException("unexpected byte buffers");
}
/*
@@ -150,10 +193,10 @@
*/
if (!isEmpty()) {
// compress(); // eventually
- encrypt(authenticator, writeCipher);
-
- // send down for processing
- write((OutputStream)null, false, (ByteArrayOutputStream)null);
+ addMAC(writeMAC);
+ encrypt(writeCipher);
+ write((OutputStream)null, false, // send down for processing
+ (ByteArrayOutputStream)null);
}
return;
}
@@ -161,8 +204,8 @@
/**
* Main wrap/write driver.
*/
- void write(EngineArgs ea, Authenticator authenticator,
- CipherBox writeCipher) throws IOException {
+ void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
+ throws IOException {
/*
* sanity check to make sure someone didn't inadvertantly
* send us an impossible combination we don't know how
@@ -174,7 +217,7 @@
* Have we set the MAC's yet? If not, we're not ready
* to process application data yet.
*/
- if (authenticator == MAC.NULL) {
+ if (writeMAC == MAC.NULL) {
return;
}
@@ -212,7 +255,7 @@
*/
int length;
if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
- write(ea, authenticator, writeCipher, 0x01);
+ write(ea, writeMAC, writeCipher, 0x01);
ea.resetLim(); // reset application data buffer limit
length = Math.min(ea.getAppRemaining(),
maxDataSizeMinusOneByteRecord);
@@ -222,14 +265,14 @@
// Don't bother to really write empty records.
if (length > 0) {
- write(ea, authenticator, writeCipher, length);
+ write(ea, writeMAC, writeCipher, length);
}
return;
}
- void write(EngineArgs ea, Authenticator authenticator,
- CipherBox writeCipher, int length) throws IOException {
+ void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher,
+ int length) throws IOException {
/*
* Copy out existing buffer values.
*/
@@ -243,76 +286,39 @@
* Don't need to worry about SSLv2 rewrites, if we're here,
* that's long since done.
*/
- int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize();
+ int dstData = dstPos + headerSize;
dstBB.position(dstData);
- /*
- * transfer application data into the network data buffer
- */
ea.gather(length);
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
/*
* "flip" but skip over header again, add MAC & encrypt
+ * addMAC will expand the limit to reflect the new
+ * data.
*/
- if (authenticator instanceof MAC) {
- MAC signer = (MAC)authenticator;
- if (signer.MAClen() != 0) {
- byte[] hash = signer.compute(contentType(), dstBB);
-
- /*
- * position was advanced to limit in compute above.
- *
- * Mark next area as writable (above layers should have
- * established that we have plenty of room), then write
- * out the hash.
- */
- dstBB.limit(dstBB.limit() + hash.length);
- dstBB.put(hash);
-
- // reset the position and limit
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
- }
- }
+ dstBB.limit(dstBB.position());
+ dstBB.position(dstData);
+ addMAC(writeMAC, dstBB);
- if (!writeCipher.isNullCipher()) {
- /*
- * Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1
- * or later.
- */
- if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
- (writeCipher.isCBCMode() || writeCipher.isAEADMode())) {
- byte[] nonce = writeCipher.createExplicitNonce(
- authenticator, contentType(), dstBB.remaining());
- dstBB.position(dstPos + headerSize);
- dstBB.put(nonce);
- if (!writeCipher.isAEADMode()) {
- // The explicit IV in TLS 1.1 and later can be encrypted.
- dstBB.position(dstPos + headerSize);
- } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
- }
+ /*
+ * Encrypt may pad, so again the limit may have changed.
+ */
+ dstBB.limit(dstBB.position());
+ dstBB.position(dstData);
+ encrypt(writeCipher, dstBB);
- /*
- * Encrypt may pad, so again the limit may have changed.
- */
- writeCipher.encrypt(dstBB, dstLim);
-
- if ((debug != null) && (Debug.isOn("record") ||
- (Debug.isOn("handshake") &&
- (contentType() == ct_change_cipher_spec)))) {
+ if (debug != null
+ && (Debug.isOn("record") || Debug.isOn("handshake"))) {
+ if ((debug != null && Debug.isOn("record"))
+ || contentType() == ct_change_cipher_spec)
System.out.println(Thread.currentThread().getName()
// v3.0/v3.1 ...
+ ", WRITE: " + protocolVersion
+ " " + InputRecord.contentName(contentType())
+ ", length = " + length);
- }
- } else {
- dstBB.position(dstBB.limit());
}
- int packetLength = dstBB.limit() - dstPos - headerSize;
+ int packetLength = dstBB.limit() - dstData;
/*
* Finish out the record header.
@@ -327,5 +333,7 @@
* Position was already set by encrypt() above.
*/
dstBB.limit(dstLim);
+
+ return;
}
}