1 /* 2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.*; 29 import java.nio.*; 30 import java.util.Arrays; 31 32 import javax.net.ssl.SSLException; 33 import sun.security.util.HexDumpEncoder; 34 35 36 /** 37 * {@code OutputRecord} takes care of the management of SSL/TLS/DTLS output 38 * records, including buffering, encryption, handshake messages marshal, etc. 39 * 40 * @author David Brownell 41 */ 42 abstract class OutputRecord extends ByteArrayOutputStream 43 implements Record, Closeable { 44 45 /* Class and subclass dynamic debugging support */ 46 static final Debug debug = Debug.getInstance("ssl"); 47 48 Authenticator writeAuthenticator; 49 CipherBox writeCipher; 50 51 HandshakeHash handshakeHash; 52 boolean firstMessage; 53 54 // current protocol version, sent as record version 55 ProtocolVersion protocolVersion; 56 57 // version for the ClientHello message. Only relevant if this is a 58 // client handshake record. If set to ProtocolVersion.SSL20Hello, 59 // the V3 client hello is converted to V2 format. 60 ProtocolVersion helloVersion; 61 62 // Is it the first application record to write? 63 boolean isFirstAppOutputRecord = true; 64 65 // packet size 66 int packetSize; 67 68 // fragment size 69 int fragmentSize; 70 71 // closed or not? 72 boolean isClosed; 73 74 /* 75 * Mappings from V3 cipher suite encodings to their pure V2 equivalents. 76 * This is taken from the SSL V3 specification, Appendix E. 77 */ 78 private static int[] V3toV2CipherMap1 = 79 {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07}; 80 private static int[] V3toV2CipherMap3 = 81 {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0}; 82 83 OutputRecord() { 84 this.writeCipher = CipherBox.NULL; 85 this.firstMessage = true; 86 this.fragmentSize = Record.maxDataSize; 87 88 // Please set packetSize and protocolVersion in the implementation. 89 } 90 91 void setVersion(ProtocolVersion protocolVersion) { 92 this.protocolVersion = protocolVersion; 93 } 94 95 /* 96 * Updates helloVersion of this record. 97 */ 98 synchronized void setHelloVersion(ProtocolVersion helloVersion) { 99 this.helloVersion = helloVersion; 100 } 101 102 /* 103 * For handshaking, we need to be able to hash every byte above the 104 * record marking layer. This is where we're guaranteed to see those 105 * bytes, so this is where we can hash them. 106 */ 107 void setHandshakeHash(HandshakeHash handshakeHash) { 108 this.handshakeHash = handshakeHash; 109 } 110 111 /* 112 * Return true iff the record is empty -- to avoid doing the work 113 * of sending empty records over the network. 114 */ 115 boolean isEmpty() { 116 return false; 117 } 118 119 boolean seqNumIsHuge() { 120 return (writeAuthenticator != null) && 121 writeAuthenticator.seqNumIsHuge(); 122 } 123 124 // SSLEngine and SSLSocket 125 abstract void encodeAlert(byte level, byte description) throws IOException; 126 127 // SSLEngine and SSLSocket 128 abstract void encodeHandshake(byte[] buffer, 129 int offset, int length) throws IOException; 130 131 // SSLEngine and SSLSocket 132 abstract void encodeChangeCipherSpec() throws IOException; 133 134 // apply to SSLEngine only 135 Ciphertext encode(ByteBuffer[] sources, int offset, int length, 136 ByteBuffer destination) throws IOException { 137 throw new UnsupportedOperationException(); 138 } 139 140 // apply to SSLEngine only 141 void encodeV2NoCipher() throws IOException { 142 throw new UnsupportedOperationException(); 143 } 144 145 // apply to SSLSocket only 146 void deliver(byte[] source, int offset, int length) throws IOException { 147 throw new UnsupportedOperationException(); 148 } 149 150 // apply to SSLSocket only 151 void setDeliverStream(OutputStream outputStream) { 152 throw new UnsupportedOperationException(); 153 } 154 155 // apply to SSLEngine only 156 Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException { 157 throw new UnsupportedOperationException(); 158 } 159 160 void changeWriteCiphers(Authenticator writeAuthenticator, 161 CipherBox writeCipher) throws IOException { 162 163 encodeChangeCipherSpec(); 164 165 /* 166 * Dispose of any intermediate state in the underlying cipher. 167 * For PKCS11 ciphers, this will release any attached sessions, 168 * and thus make finalization faster. 169 * 170 * Since MAC's doFinal() is called for every SSL/TLS packet, it's 171 * not necessary to do the same with MAC's. 172 */ 173 writeCipher.dispose(); 174 175 this.writeAuthenticator = writeAuthenticator; 176 this.writeCipher = writeCipher; 177 this.isFirstAppOutputRecord = true; 178 } 179 180 void changePacketSize(int packetSize) { 181 this.packetSize = packetSize; 182 } 183 184 void changeFragmentSize(int fragmentSize) { 185 this.fragmentSize = fragmentSize; 186 } 187 188 int getMaxPacketSize() { 189 return packetSize; 190 } 191 192 // apply to DTLS SSLEngine 193 void initHandshaker() { 194 // blank 195 } 196 197 @Override 198 public synchronized void close() throws IOException { 199 if (!isClosed) { 200 isClosed = true; 201 writeCipher.dispose(); 202 } 203 } 204 205 // 206 // shared helpers 207 // 208 209 // Encrypt a fragment and wrap up a record. 210 // 211 // To be consistent with the spec of SSLEngine.wrap() methods, the 212 // destination ByteBuffer's position is updated to reflect the amount 213 // of data produced. The limit remains the same. 214 static long encrypt(Authenticator authenticator, 215 CipherBox encCipher, byte contentType, ByteBuffer destination, 216 int headerOffset, int dstLim, int headerSize, 217 ProtocolVersion protocolVersion, boolean isDTLS) { 218 219 byte[] sequenceNumber = null; 220 int dstContent = destination.position(); 221 222 // Acquire the current sequence number before using. 223 if (isDTLS) { 224 sequenceNumber = authenticator.sequenceNumber(); 225 } 226 227 // "flip" but skip over header again, add MAC & encrypt 228 if (authenticator instanceof MAC) { 229 MAC signer = (MAC)authenticator; 230 if (signer.MAClen() != 0) { 231 byte[] hash = signer.compute(contentType, destination, false); 232 233 /* 234 * position was advanced to limit in MAC compute above. 235 * 236 * Mark next area as writable (above layers should have 237 * established that we have plenty of room), then write 238 * out the hash. 239 */ 240 destination.limit(destination.limit() + hash.length); 241 destination.put(hash); 242 243 // reset the position and limit 244 destination.limit(destination.position()); 245 destination.position(dstContent); 246 } 247 } 248 249 if (!encCipher.isNullCipher()) { 250 if (protocolVersion.useTLS11PlusSpec() && 251 (encCipher.isCBCMode() || encCipher.isAEADMode())) { 252 byte[] nonce = encCipher.createExplicitNonce( 253 authenticator, contentType, destination.remaining()); 254 destination.position(headerOffset + headerSize); 255 destination.put(nonce); 256 } 257 if (!encCipher.isAEADMode()) { 258 // The explicit IV in TLS 1.1 and later can be encrypted. 259 destination.position(headerOffset + headerSize); 260 } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode 261 262 // Encrypt may pad, so again the limit may be changed. 263 encCipher.encrypt(destination, dstLim); 264 } else { 265 destination.position(destination.limit()); 266 } 267 268 // Finish out the record header. 269 int fragLen = destination.limit() - headerOffset - headerSize; 270 271 destination.put(headerOffset, contentType); // content type 272 destination.put(headerOffset + 1, protocolVersion.major); 273 destination.put(headerOffset + 2, protocolVersion.minor); 274 if (!isDTLS) { 275 // fragment length 276 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); 277 destination.put(headerOffset + 4, (byte)fragLen); 278 } else { 279 // epoch and sequence_number 280 destination.put(headerOffset + 3, sequenceNumber[0]); 281 destination.put(headerOffset + 4, sequenceNumber[1]); 282 destination.put(headerOffset + 5, sequenceNumber[2]); 283 destination.put(headerOffset + 6, sequenceNumber[3]); 284 destination.put(headerOffset + 7, sequenceNumber[4]); 285 destination.put(headerOffset + 8, sequenceNumber[5]); 286 destination.put(headerOffset + 9, sequenceNumber[6]); 287 destination.put(headerOffset + 10, sequenceNumber[7]); 288 289 // fragment length 290 destination.put(headerOffset + 11, (byte)(fragLen >> 8)); 291 destination.put(headerOffset + 12, (byte)fragLen); 292 293 // Increase the sequence number for next use. 294 authenticator.increaseSequenceNumber(); 295 } 296 297 // Update destination position to reflect the amount of data produced. 298 destination.position(destination.limit()); 299 300 return Authenticator.toLong(sequenceNumber); 301 } 302 303 // Encrypt a fragment and wrap up a record. 304 // 305 // Uses the internal expandable buf variable and the current 306 // protocolVersion variable. 307 void encrypt(Authenticator authenticator, 308 CipherBox encCipher, byte contentType, int headerSize) { 309 310 int position = headerSize + writeCipher.getExplicitNonceSize(); 311 312 // "flip" but skip over header again, add MAC & encrypt 313 int macLen = 0; 314 if (authenticator instanceof MAC) { 315 MAC signer = (MAC)authenticator; 316 macLen = signer.MAClen(); 317 if (macLen != 0) { 318 byte[] hash = signer.compute(contentType, 319 buf, position, (count - position), false); 320 321 write(hash, 0, hash.length); 322 } 323 } 324 325 if (!encCipher.isNullCipher()) { 326 // Requires explicit IV/nonce for CBC/AEAD cipher suites for 327 // TLS 1.1 or later. 328 if (protocolVersion.useTLS11PlusSpec() && 329 (encCipher.isCBCMode() || encCipher.isAEADMode())) { 330 331 byte[] nonce = encCipher.createExplicitNonce( 332 authenticator, contentType, (count - position)); 333 int noncePos = position - nonce.length; 334 System.arraycopy(nonce, 0, buf, noncePos, nonce.length); 335 } 336 337 if (!encCipher.isAEADMode()) { 338 // The explicit IV in TLS 1.1 and later can be encrypted. 339 position = headerSize; 340 } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode 341 342 // increase buf capacity if necessary 343 int fragSize = count - position; 344 int packetSize = 345 encCipher.calculatePacketSize(fragSize, macLen, headerSize); 346 if (packetSize > (buf.length - position)) { 347 byte[] newBuf = new byte[position + packetSize]; 348 System.arraycopy(buf, 0, newBuf, 0, count); 349 buf = newBuf; 350 } 351 352 // Encrypt may pad, so again the count may be changed. 353 count = position + 354 encCipher.encrypt(buf, position, (count - position)); 355 } 356 357 // Fill out the header, write it and the message. 358 int fragLen = count - headerSize; 359 buf[0] = contentType; 360 buf[1] = protocolVersion.major; 361 buf[2] = protocolVersion.minor; 362 buf[3] = (byte)((fragLen >> 8) & 0xFF); 363 buf[4] = (byte)(fragLen & 0xFF); 364 } 365 366 static ByteBuffer encodeV2ClientHello( 367 byte[] fragment, int offset, int length) throws IOException { 368 369 int v3SessIdLenOffset = offset + 34; // 2: client_version 370 // 32: random 371 372 int v3SessIdLen = fragment[v3SessIdLenOffset]; 373 int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen; 374 int v3CSLen = ((fragment[v3CSLenOffset] & 0xff) << 8) + 375 (fragment[v3CSLenOffset + 1] & 0xff); 376 int cipherSpecs = v3CSLen / 2; // 2: cipher spec size 377 378 // Estimate the max V2ClientHello message length 379 // 380 // 11: header size 381 // (cipherSpecs * 6): cipher_specs 382 // 6: one cipher suite may need 6 bytes, see V3toV2CipherSuite. 383 // 3: placeholder for the TLS_EMPTY_RENEGOTIATION_INFO_SCSV 384 // signaling cipher suite 385 // 32: challenge size 386 int v2MaxMsgLen = 11 + (cipherSpecs * 6) + 3 + 32; 387 388 // Create a ByteBuffer backed by an accessible byte array. 389 byte[] dstBytes = new byte[v2MaxMsgLen]; 390 ByteBuffer dstBuf = ByteBuffer.wrap(dstBytes); 391 392 /* 393 * Copy over the cipher specs. We don't care about actually 394 * translating them for use with an actual V2 server since 395 * we only talk V3. Therefore, just copy over the V3 cipher 396 * spec values with a leading 0. 397 */ 398 int v3CSOffset = v3CSLenOffset + 2; // skip length field 399 int v2CSLen = 0; 400 401 dstBuf.position(11); 402 boolean containsRenegoInfoSCSV = false; 403 for (int i = 0; i < cipherSpecs; i++) { 404 byte byte1, byte2; 405 406 byte1 = fragment[v3CSOffset++]; 407 byte2 = fragment[v3CSOffset++]; 408 v2CSLen += V3toV2CipherSuite(dstBuf, byte1, byte2); 409 if (!containsRenegoInfoSCSV && 410 byte1 == (byte)0x00 && byte2 == (byte)0xFF) { 411 containsRenegoInfoSCSV = true; 412 } 413 } 414 415 if (!containsRenegoInfoSCSV) { 416 v2CSLen += V3toV2CipherSuite(dstBuf, (byte)0x00, (byte)0xFF); 417 } 418 419 /* 420 * Copy in the nonce. 421 */ 422 dstBuf.put(fragment, (offset + 2), 32); 423 424 /* 425 * Build the first part of the V3 record header from the V2 one 426 * that's now buffered up. (Lengths are fixed up later). 427 */ 428 int msgLen = dstBuf.position() - 2; // Exclude the legth field itself 429 dstBuf.position(0); 430 dstBuf.put((byte)(0x80 | ((msgLen >>> 8) & 0xFF))); // pos: 0 431 dstBuf.put((byte)(msgLen & 0xFF)); // pos: 1 432 dstBuf.put(HandshakeMessage.ht_client_hello); // pos: 2 433 dstBuf.put(fragment[offset]); // major version, pos: 3 434 dstBuf.put(fragment[offset + 1]); // minor version, pos: 4 435 dstBuf.put((byte)(v2CSLen >>> 8)); // pos: 5 436 dstBuf.put((byte)(v2CSLen & 0xFF)); // pos: 6 437 dstBuf.put((byte)0x00); // session_id_length, pos: 7 438 dstBuf.put((byte)0x00); // pos: 8 439 dstBuf.put((byte)0x00); // challenge_length, pos: 9 440 dstBuf.put((byte)32); // pos: 10 441 442 dstBuf.position(0); 443 dstBuf.limit(msgLen + 2); 444 445 return dstBuf; 446 } 447 448 private static int V3toV2CipherSuite(ByteBuffer dstBuf, 449 byte byte1, byte byte2) { 450 dstBuf.put((byte)0); 451 dstBuf.put(byte1); 452 dstBuf.put(byte2); 453 454 if (((byte2 & 0xff) > 0xA) || (V3toV2CipherMap1[byte2] == -1)) { 455 return 3; 456 } 457 458 dstBuf.put((byte)V3toV2CipherMap1[byte2]); 459 dstBuf.put((byte)0); 460 dstBuf.put((byte)V3toV2CipherMap3[byte2]); 461 462 return 6; 463 } 464 }