1 /* 2 * Copyright (c) 1996, 2018, 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.ByteArrayOutputStream; 29 import java.io.Closeable; 30 import java.io.IOException; 31 import java.io.OutputStream; 32 import java.nio.ByteBuffer; 33 import sun.security.ssl.SSLCipher.SSLWriteCipher; 34 35 /** 36 * {@code OutputRecord} takes care of the management of SSL/(D)TLS 37 * output records, including buffering, encryption, handshake 38 * messages marshal, etc. 39 * 40 * @author David Brownell 41 */ 42 abstract class OutputRecord 43 extends ByteArrayOutputStream implements Record, Closeable { 44 SSLWriteCipher writeCipher; 45 // Needed for KeyUpdate 46 TransportContext tc; 47 48 final HandshakeHash handshakeHash; 49 boolean firstMessage; 50 51 // current protocol version, sent as record version 52 ProtocolVersion protocolVersion; 53 54 // version for the ClientHello message. Only relevant if this is a 55 // client handshake record. If set to ProtocolVersion.SSL20Hello, 56 // the V3 client hello is converted to V2 format. 57 ProtocolVersion helloVersion; 58 59 // Is it the first application record to write? 60 boolean isFirstAppOutputRecord = true; 61 62 // packet size 63 int packetSize; 64 65 // fragment size 66 int fragmentSize; 67 68 // closed or not? 69 boolean isClosed; 70 71 /* 72 * Mappings from V3 cipher suite encodings to their pure V2 equivalents. 73 * This is taken from the SSL V3 specification, Appendix E. 74 */ 75 private static final int[] V3toV2CipherMap1 = 76 {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07}; 77 private static final int[] V3toV2CipherMap3 = 78 {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0}; 79 80 OutputRecord(HandshakeHash handshakeHash, SSLWriteCipher writeCipher) { 81 this.writeCipher = writeCipher; 82 this.firstMessage = true; 83 this.fragmentSize = Record.maxDataSize; 84 85 this.handshakeHash = handshakeHash; 86 87 // Please set packetSize and protocolVersion in the implementation. 88 } 89 90 void setVersion(ProtocolVersion protocolVersion) { 91 this.protocolVersion = protocolVersion; 92 } 93 94 /* 95 * Updates helloVersion of this record. 96 */ 97 synchronized void setHelloVersion(ProtocolVersion helloVersion) { 98 this.helloVersion = helloVersion; 99 } 100 101 /* 102 * Return true iff the record is empty -- to avoid doing the work 103 * of sending empty records over the network. 104 */ 105 boolean isEmpty() { 106 return false; 107 } 108 109 boolean seqNumIsHuge() { 110 return (writeCipher.authenticator != null) && 111 writeCipher.authenticator.seqNumIsHuge(); 112 } 113 114 // SSLEngine and SSLSocket 115 abstract void encodeAlert(byte level, byte description) throws IOException; 116 117 // SSLEngine and SSLSocket 118 abstract void encodeHandshake(byte[] buffer, 119 int offset, int length) throws IOException; 120 121 // SSLEngine and SSLSocket 122 abstract void encodeChangeCipherSpec() throws IOException; 123 124 // apply to SSLEngine only 125 Ciphertext encode( 126 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 127 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 128 129 throw new UnsupportedOperationException(); 130 } 131 132 // apply to SSLEngine only 133 void encodeV2NoCipher() throws IOException { 134 throw new UnsupportedOperationException(); 135 } 136 137 // apply to SSLSocket only 138 void deliver( 139 byte[] source, int offset, int length) throws IOException { 140 throw new UnsupportedOperationException(); 141 } 142 143 // apply to SSLSocket only 144 void setDeliverStream(OutputStream outputStream) { 145 throw new UnsupportedOperationException(); 146 } 147 148 void changeWriteCiphers(SSLWriteCipher writeCipher, 149 boolean useChangeCipherSpec) throws IOException { 150 if (useChangeCipherSpec) { 151 encodeChangeCipherSpec(); 152 } 153 154 /* 155 * Dispose of any intermediate state in the underlying cipher. 156 * For PKCS11 ciphers, this will release any attached sessions, 157 * and thus make finalization faster. 158 * 159 * Since MAC's doFinal() is called for every SSL/TLS packet, it's 160 * not necessary to do the same with MAC's. 161 */ 162 writeCipher.dispose(); 163 164 this.writeCipher = writeCipher; 165 this.isFirstAppOutputRecord = true; 166 } 167 168 void changePacketSize(int packetSize) { 169 this.packetSize = packetSize; 170 } 171 172 void changeFragmentSize(int fragmentSize) { 173 this.fragmentSize = fragmentSize; 174 } 175 176 int getMaxPacketSize() { 177 return packetSize; 178 } 179 180 // apply to DTLS SSLEngine 181 void initHandshaker() { 182 // blank 183 } 184 185 // apply to DTLS SSLEngine 186 void finishHandshake() { 187 // blank 188 } 189 190 // apply to DTLS SSLEngine 191 void launchRetransmission() { 192 // blank 193 } 194 195 @Override 196 public synchronized void close() throws IOException { 197 if (!isClosed) { 198 isClosed = true; 199 writeCipher.dispose(); 200 } 201 } 202 203 synchronized boolean isClosed() { 204 return isClosed; 205 } 206 207 // 208 // shared helpers 209 // 210 211 // Encrypt a fragment and wrap up a record. 212 // 213 // To be consistent with the spec of SSLEngine.wrap() methods, the 214 // destination ByteBuffer's position is updated to reflect the amount 215 // of data produced. The limit remains the same. 216 static long encrypt( 217 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, 218 int headerOffset, int dstLim, int headerSize, 219 ProtocolVersion protocolVersion) { 220 boolean isDTLS = protocolVersion.isDTLS; 221 if (isDTLS) { 222 if (protocolVersion.useTLS13PlusSpec()) { 223 return d13Encrypt(encCipher, 224 contentType, destination, headerOffset, 225 dstLim, headerSize, protocolVersion); 226 } else { 227 return d10Encrypt(encCipher, 228 contentType, destination, headerOffset, 229 dstLim, headerSize, protocolVersion); 230 } 231 } else { 232 if (protocolVersion.useTLS13PlusSpec()) { 233 return t13Encrypt(encCipher, 234 contentType, destination, headerOffset, 235 dstLim, headerSize, protocolVersion); 236 } else { 237 return t10Encrypt(encCipher, 238 contentType, destination, headerOffset, 239 dstLim, headerSize, protocolVersion); 240 } 241 } 242 } 243 244 static long d13Encrypt( 245 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, 246 int headerOffset, int dstLim, int headerSize, 247 ProtocolVersion protocolVersion) { 248 throw new UnsupportedOperationException("Not supported yet."); 249 } 250 251 private static long d10Encrypt( 252 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, 253 int headerOffset, int dstLim, int headerSize, 254 ProtocolVersion protocolVersion) { 255 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); 256 encCipher.encrypt(contentType, destination); 257 258 // Finish out the record header. 259 int fragLen = destination.limit() - headerOffset - headerSize; 260 261 destination.put(headerOffset, contentType); // content type 262 destination.put(headerOffset + 1, protocolVersion.major); 263 destination.put(headerOffset + 2, protocolVersion.minor); 264 265 // epoch and sequence_number 266 destination.put(headerOffset + 3, sequenceNumber[0]); 267 destination.put(headerOffset + 4, sequenceNumber[1]); 268 destination.put(headerOffset + 5, sequenceNumber[2]); 269 destination.put(headerOffset + 6, sequenceNumber[3]); 270 destination.put(headerOffset + 7, sequenceNumber[4]); 271 destination.put(headerOffset + 8, sequenceNumber[5]); 272 destination.put(headerOffset + 9, sequenceNumber[6]); 273 destination.put(headerOffset + 10, sequenceNumber[7]); 274 275 // fragment length 276 destination.put(headerOffset + 11, (byte)(fragLen >> 8)); 277 destination.put(headerOffset + 12, (byte)fragLen); 278 279 // Update destination position to reflect the amount of data produced. 280 destination.position(destination.limit()); 281 282 return Authenticator.toLong(sequenceNumber); 283 } 284 285 static long t13Encrypt( 286 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, 287 int headerOffset, int dstLim, int headerSize, 288 ProtocolVersion protocolVersion) { 289 if (!encCipher.isNullCipher()) { 290 // inner plaintext, using zero length padding. 291 int pos = destination.position(); 292 destination.position(destination.limit()); 293 destination.limit(destination.limit() + 1); 294 destination.put(contentType); 295 destination.position(pos); 296 } 297 298 // use the right TLSCiphertext.opaque_type and legacy_record_version 299 ProtocolVersion pv = protocolVersion; 300 if (!encCipher.isNullCipher()) { 301 pv = ProtocolVersion.TLS12; 302 contentType = ContentType.APPLICATION_DATA.id; 303 } else if (protocolVersion.useTLS13PlusSpec()) { 304 pv = ProtocolVersion.TLS12; 305 } 306 307 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); 308 encCipher.encrypt(contentType, destination); 309 310 // Finish out the record header. 311 int fragLen = destination.limit() - headerOffset - headerSize; 312 destination.put(headerOffset, contentType); 313 destination.put(headerOffset + 1, pv.major); 314 destination.put(headerOffset + 2, pv.minor); 315 316 // fragment length 317 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); 318 destination.put(headerOffset + 4, (byte)fragLen); 319 320 // Update destination position to reflect the amount of data produced. 321 destination.position(destination.limit()); 322 323 return Authenticator.toLong(sequenceNumber); 324 } 325 326 static long t10Encrypt( 327 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, 328 int headerOffset, int dstLim, int headerSize, 329 ProtocolVersion protocolVersion) { 330 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); 331 encCipher.encrypt(contentType, destination); 332 333 // Finish out the record header. 334 int fragLen = destination.limit() - headerOffset - headerSize; 335 336 destination.put(headerOffset, contentType); // content type 337 destination.put(headerOffset + 1, protocolVersion.major); 338 destination.put(headerOffset + 2, protocolVersion.minor); 339 340 // fragment length 341 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); 342 destination.put(headerOffset + 4, (byte)fragLen); 343 344 // Update destination position to reflect the amount of data produced. 345 destination.position(destination.limit()); 346 347 return Authenticator.toLong(sequenceNumber); 348 } 349 350 // Encrypt a fragment and wrap up a record. 351 // 352 // Uses the internal expandable buf variable and the current 353 // protocolVersion variable. 354 long encrypt( 355 SSLWriteCipher encCipher, byte contentType, int headerSize) { 356 if (protocolVersion.useTLS13PlusSpec()) { 357 return t13Encrypt(encCipher, contentType, headerSize); 358 } else { 359 return t10Encrypt(encCipher, contentType, headerSize); 360 } 361 } 362 363 private static final class T13PaddingHolder { 364 private static final byte[] zeros = new byte[16]; 365 } 366 367 long t13Encrypt( 368 SSLWriteCipher encCipher, byte contentType, int headerSize) { 369 if (!encCipher.isNullCipher()) { 370 // inner plaintext 371 write(contentType); 372 write(T13PaddingHolder.zeros, 0, T13PaddingHolder.zeros.length); 373 } 374 375 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); 376 int position = headerSize; 377 int contentLen = count - position; 378 379 // ensure the capacity 380 int packetSize = encCipher.calculatePacketSize(contentLen, headerSize); 381 if (packetSize > buf.length) { 382 byte[] newBuf = new byte[packetSize]; 383 System.arraycopy(buf, 0, newBuf, 0, count); 384 buf = newBuf; 385 } 386 387 // use the right TLSCiphertext.opaque_type and legacy_record_version 388 ProtocolVersion pv = protocolVersion; 389 if (!encCipher.isNullCipher()) { 390 pv = ProtocolVersion.TLS12; 391 contentType = ContentType.APPLICATION_DATA.id; 392 } else { 393 pv = ProtocolVersion.TLS12; 394 } 395 396 ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen); 397 count = headerSize + encCipher.encrypt(contentType, destination); 398 399 // Fill out the header, write it and the message. 400 int fragLen = count - headerSize; 401 402 buf[0] = contentType; 403 buf[1] = pv.major; 404 buf[2] = pv.minor; 405 buf[3] = (byte)((fragLen >> 8) & 0xFF); 406 buf[4] = (byte)(fragLen & 0xFF); 407 408 return Authenticator.toLong(sequenceNumber); 409 } 410 411 long t10Encrypt( 412 SSLWriteCipher encCipher, byte contentType, int headerSize) { 413 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); 414 int position = headerSize + writeCipher.getExplicitNonceSize(); 415 int contentLen = count - position; 416 417 // ensure the capacity 418 int packetSize = encCipher.calculatePacketSize(contentLen, headerSize); 419 if (packetSize > buf.length) { 420 byte[] newBuf = new byte[packetSize]; 421 System.arraycopy(buf, 0, newBuf, 0, count); 422 buf = newBuf; 423 } 424 ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen); 425 count = headerSize + encCipher.encrypt(contentType, destination); 426 427 // Fill out the header, write it and the message. 428 int fragLen = count - headerSize; 429 buf[0] = contentType; 430 buf[1] = protocolVersion.major; 431 buf[2] = protocolVersion.minor; 432 buf[3] = (byte)((fragLen >> 8) & 0xFF); 433 buf[4] = (byte)(fragLen & 0xFF); 434 435 return Authenticator.toLong(sequenceNumber); 436 } 437 438 static ByteBuffer encodeV2ClientHello( 439 byte[] fragment, int offset, int length) throws IOException { 440 int v3SessIdLenOffset = offset + 34; // 2: client_version 441 // 32: random 442 443 int v3SessIdLen = fragment[v3SessIdLenOffset]; 444 int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen; 445 int v3CSLen = ((fragment[v3CSLenOffset] & 0xff) << 8) + 446 (fragment[v3CSLenOffset + 1] & 0xff); 447 int cipherSpecs = v3CSLen / 2; // 2: cipher spec size 448 449 // Estimate the max V2ClientHello message length 450 // 451 // 11: header size 452 // (cipherSpecs * 6): cipher_specs 453 // 6: one cipher suite may need 6 bytes, see V3toV2CipherSuite. 454 // 3: placeholder for the TLS_EMPTY_RENEGOTIATION_INFO_SCSV 455 // signaling cipher suite 456 // 32: challenge size 457 int v2MaxMsgLen = 11 + (cipherSpecs * 6) + 3 + 32; 458 459 // Create a ByteBuffer backed by an accessible byte array. 460 byte[] dstBytes = new byte[v2MaxMsgLen]; 461 ByteBuffer dstBuf = ByteBuffer.wrap(dstBytes); 462 463 /* 464 * Copy over the cipher specs. We don't care about actually 465 * translating them for use with an actual V2 server since 466 * we only talk V3. Therefore, just copy over the V3 cipher 467 * spec values with a leading 0. 468 */ 469 int v3CSOffset = v3CSLenOffset + 2; // skip length field 470 int v2CSLen = 0; 471 472 dstBuf.position(11); 473 boolean containsRenegoInfoSCSV = false; 474 for (int i = 0; i < cipherSpecs; i++) { 475 byte byte1, byte2; 476 477 byte1 = fragment[v3CSOffset++]; 478 byte2 = fragment[v3CSOffset++]; 479 v2CSLen += V3toV2CipherSuite(dstBuf, byte1, byte2); 480 if (!containsRenegoInfoSCSV && 481 byte1 == (byte)0x00 && byte2 == (byte)0xFF) { 482 containsRenegoInfoSCSV = true; 483 } 484 } 485 486 if (!containsRenegoInfoSCSV) { 487 v2CSLen += V3toV2CipherSuite(dstBuf, (byte)0x00, (byte)0xFF); 488 } 489 490 /* 491 * Copy in the nonce. 492 */ 493 dstBuf.put(fragment, (offset + 2), 32); 494 495 /* 496 * Build the first part of the V3 record header from the V2 one 497 * that's now buffered up. (Lengths are fixed up later). 498 */ 499 int msgLen = dstBuf.position() - 2; // Exclude the legth field itself 500 dstBuf.position(0); 501 dstBuf.put((byte)(0x80 | ((msgLen >>> 8) & 0xFF))); // pos: 0 502 dstBuf.put((byte)(msgLen & 0xFF)); // pos: 1 503 dstBuf.put(SSLHandshake.CLIENT_HELLO.id); // pos: 2 504 dstBuf.put(fragment[offset]); // major version, pos: 3 505 dstBuf.put(fragment[offset + 1]); // minor version, pos: 4 506 dstBuf.put((byte)(v2CSLen >>> 8)); // pos: 5 507 dstBuf.put((byte)(v2CSLen & 0xFF)); // pos: 6 508 dstBuf.put((byte)0x00); // session_id_length, pos: 7 509 dstBuf.put((byte)0x00); // pos: 8 510 dstBuf.put((byte)0x00); // challenge_length, pos: 9 511 dstBuf.put((byte)32); // pos: 10 512 513 dstBuf.position(0); 514 dstBuf.limit(msgLen + 2); 515 516 return dstBuf; 517 } 518 519 private static int V3toV2CipherSuite(ByteBuffer dstBuf, 520 byte byte1, byte byte2) { 521 dstBuf.put((byte)0); 522 dstBuf.put(byte1); 523 dstBuf.put(byte2); 524 525 if (((byte2 & 0xff) > 0xA) || (V3toV2CipherMap1[byte2] == -1)) { 526 return 3; 527 } 528 529 dstBuf.put((byte)V3toV2CipherMap1[byte2]); 530 dstBuf.put((byte)0); 531 dstBuf.put((byte)V3toV2CipherMap3[byte2]); 532 533 return 6; 534 } 535 }