1 /* 2 * Copyright (c) 1996, 2014, 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.*; 31 32 import javax.crypto.BadPaddingException; 33 34 import javax.net.ssl.*; 35 36 import sun.security.util.HexDumpEncoder; 37 38 39 /** 40 * {@code InputRecord} takes care of the management of SSL/TLS/DTLS input 41 * records, including buffering, decryption, handshake messages marshal, etc. 42 * 43 * @author David Brownell 44 */ 45 class InputRecord implements Record, Closeable { 46 47 /* Class and subclass dynamic debugging support */ 48 static final Debug debug = Debug.getInstance("ssl"); 49 50 Authenticator readAuthenticator; 51 CipherBox readCipher; 52 53 HandshakeHash handshakeHash; 54 boolean isClosed; 55 56 // The ClientHello version to accept. If set to ProtocolVersion.SSL20Hello 57 // and the first message we read is a ClientHello in V2 format, we convert 58 // it to V3. Otherwise we throw an exception when encountering a V2 hello. 59 ProtocolVersion helloVersion; 60 61 // fragment size 62 int fragmentSize; 63 64 InputRecord() { 65 this.readCipher = CipherBox.NULL; 66 this.readAuthenticator = null; // Please override this assignment. 67 this.helloVersion = ProtocolVersion.DEFAULT_HELLO; 68 this.fragmentSize = Record.maxDataSize; 69 } 70 71 void setHelloVersion(ProtocolVersion helloVersion) { 72 this.helloVersion = helloVersion; 73 } 74 75 ProtocolVersion getHelloVersion() { 76 return helloVersion; 77 } 78 79 /* 80 * Set instance for the computation of handshake hashes. 81 * 82 * For handshaking, we need to be able to hash every byte above the 83 * record marking layer. This is where we're guaranteed to see those 84 * bytes, so this is where we can hash them ... especially in the 85 * case of hashing the initial V2 message! 86 */ 87 void setHandshakeHash(HandshakeHash handshakeHash) { 88 if (handshakeHash != null) { 89 byte[] reserved = null; 90 if (this.handshakeHash != null) { 91 reserved = this.handshakeHash.getAllHandshakeMessages(); 92 } 93 if ((reserved != null) && (reserved.length != 0)) { 94 handshakeHash.update(reserved, 0, reserved.length); 95 96 if (debug != null && Debug.isOn("data")) { 97 Debug.printHex( 98 "[reserved] handshake hash: len = " + reserved.length, 99 reserved); 100 } 101 } 102 } 103 104 this.handshakeHash = handshakeHash; 105 } 106 107 boolean seqNumIsHuge() { 108 return (readAuthenticator != null) && 109 readAuthenticator.seqNumIsHuge(); 110 } 111 112 boolean isEmpty() { 113 return false; 114 } 115 116 // apply to DTLS SSLEngine 117 void expectingFinishFlight() { 118 // blank 119 } 120 121 /** 122 * Prevent any more data from being read into this record, 123 * and flag the record as holding no data. 124 */ 125 @Override 126 public synchronized void close() throws IOException { 127 if (!isClosed) { 128 isClosed = true; 129 readCipher.dispose(); 130 } 131 } 132 133 // apply to SSLSocket and SSLEngine 134 void changeReadCiphers( 135 Authenticator readAuthenticator, CipherBox readCipher) { 136 137 /* 138 * Dispose of any intermediate state in the underlying cipher. 139 * For PKCS11 ciphers, this will release any attached sessions, 140 * and thus make finalization faster. 141 * 142 * Since MAC's doFinal() is called for every SSL/TLS packet, it's 143 * not necessary to do the same with MAC's. 144 */ 145 readCipher.dispose(); 146 147 this.readAuthenticator = readAuthenticator; 148 this.readCipher = readCipher; 149 } 150 151 // change fragment size 152 void changeFragmentSize(int fragmentSize) { 153 this.fragmentSize = fragmentSize; 154 } 155 156 /* 157 * Check if there is enough inbound data in the ByteBuffer to make 158 * a inbound packet. 159 * 160 * @return -1 if there are not enough bytes to tell (small header), 161 */ 162 // apply to SSLEngine only 163 int bytesInCompletePacket(ByteBuffer buf) throws SSLException { 164 throw new UnsupportedOperationException(); 165 } 166 167 // apply to SSLSocket only 168 int bytesInCompletePacket(InputStream is) throws IOException { 169 throw new UnsupportedOperationException(); 170 } 171 172 /** 173 * Return true if the specified record protocol version is out of the 174 * range of the possible supported versions. 175 */ 176 void checkRecordVersion(ProtocolVersion version, 177 boolean allowSSL20Hello) throws SSLException { 178 // blank 179 } 180 181 // apply to DTLS SSLEngine only 182 Plaintext acquirePlaintext() 183 throws IOException, BadPaddingException { 184 throw new UnsupportedOperationException(); 185 } 186 187 // read, decrypt and decompress the network record. 188 // 189 // apply to SSLEngine only 190 Plaintext decode(ByteBuffer netData) 191 throws IOException, BadPaddingException { 192 throw new UnsupportedOperationException(); 193 } 194 195 // apply to SSLSocket only 196 Plaintext decode(InputStream is, ByteBuffer destination) 197 throws IOException, BadPaddingException { 198 throw new UnsupportedOperationException(); 199 } 200 201 // apply to SSLSocket only 202 void setDeliverStream(OutputStream outputStream) { 203 throw new UnsupportedOperationException(); 204 } 205 206 // calculate plaintext fragment size 207 // 208 // apply to SSLEngine only 209 int estimateFragmentSize(int packetSize) { 210 throw new UnsupportedOperationException(); 211 } 212 213 // 214 // shared helpers 215 // 216 217 // Not apply to DTLS 218 static ByteBuffer convertToClientHello(ByteBuffer packet) { 219 220 int srcPos = packet.position(); 221 int srcLim = packet.limit(); 222 223 byte firstByte = packet.get(); 224 byte secondByte = packet.get(); 225 int recordLen = (((firstByte & 0x7F) << 8) | (secondByte & 0xFF)) + 2; 226 227 packet.position(srcPos + 3); // the V2ClientHello record header 228 229 byte majorVersion = packet.get(); 230 byte minorVersion = packet.get(); 231 232 int cipherSpecLen = ((packet.get() & 0xFF) << 8) + 233 (packet.get() & 0xFF); 234 int sessionIdLen = ((packet.get() & 0xFF) << 8) + 235 (packet.get() & 0xFF); 236 int nonceLen = ((packet.get() & 0xFF) << 8) + 237 (packet.get() & 0xFF); 238 239 // Required space for the target SSLv3 ClientHello message. 240 // 5: record header size 241 // 4: handshake header size 242 // 2: ClientHello.client_version 243 // 32: ClientHello.random 244 // 1: length byte of ClientHello.session_id 245 // 2: length bytes of ClientHello.cipher_suites 246 // 2: empty ClientHello.compression_methods 247 int requiredSize = 48 + sessionIdLen + ((cipherSpecLen * 2 ) / 3 ); 248 byte[] converted = new byte[requiredSize]; 249 250 /* 251 * Build the first part of the V3 record header from the V2 one 252 * that's now buffered up. (Lengths are fixed up later). 253 */ 254 // Note: need not to set the header actually. 255 converted[0] = ct_handshake; 256 converted[1] = majorVersion; 257 converted[2] = minorVersion; 258 // header [3..4] for handshake message length 259 // required size is 5; 260 261 /* 262 * Store the generic V3 handshake header: 4 bytes 263 */ 264 converted[5] = 1; // HandshakeMessage.ht_client_hello 265 // buf [6..8] for length of ClientHello (int24) 266 // required size += 4; 267 268 /* 269 * ClientHello header starts with SSL version 270 */ 271 converted[9] = majorVersion; 272 converted[10] = minorVersion; 273 // required size += 2; 274 int pointer = 11; 275 276 /* 277 * Copy Random value/nonce ... if less than the 32 bytes of 278 * a V3 "Random", right justify and zero pad to the left. Else 279 * just take the last 32 bytes. 280 */ 281 int offset = srcPos + 11 + cipherSpecLen + sessionIdLen; 282 283 if (nonceLen < 32) { 284 for (int i = 0; i < (32 - nonceLen); i++) { 285 converted[pointer++] = 0; 286 } 287 packet.position(offset); 288 packet.get(converted, pointer, nonceLen); 289 290 pointer += nonceLen; 291 } else { 292 packet.position(offset + nonceLen - 32); 293 packet.get(converted, pointer, 32); 294 295 pointer += 32; 296 } 297 298 /* 299 * Copy session ID (only one byte length!) 300 */ 301 offset -= sessionIdLen; 302 converted[pointer++] = (byte)(sessionIdLen & 0xFF); 303 packet.position(offset); 304 packet.get(converted, pointer, sessionIdLen); 305 306 /* 307 * Copy and translate cipher suites ... V2 specs with first byte zero 308 * are really V3 specs (in the last 2 bytes), just copy those and drop 309 * the other ones. Preference order remains unchanged. 310 * 311 * Example: Netscape Navigator 3.0 (exportable) says: 312 * 313 * 0/3, SSL_RSA_EXPORT_WITH_RC4_40_MD5 314 * 0/6, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 315 * 316 * Microsoft Internet Explorer 3.0 (exportable) supports only 317 * 318 * 0/3, SSL_RSA_EXPORT_WITH_RC4_40_MD5 319 */ 320 int j; 321 322 offset -= cipherSpecLen; 323 packet.position(offset); 324 325 j = pointer + 2; 326 for (int i = 0; i < cipherSpecLen; i += 3) { 327 if (packet.get() != 0) { 328 // Ignore version 2.0 specifix cipher suite. Clients 329 // should also include the version 3.0 equivalent in 330 // the V2ClientHello message. 331 packet.get(); // ignore the 2nd byte 332 packet.get(); // ignore the 3rd byte 333 continue; 334 } 335 336 converted[j++] = packet.get(); 337 converted[j++] = packet.get(); 338 } 339 340 j -= pointer + 2; 341 converted[pointer++] = (byte)((j >>> 8) & 0xFF); 342 converted[pointer++] = (byte)(j & 0xFF); 343 pointer += j; 344 345 /* 346 * Append compression methods (default/null only) 347 */ 348 converted[pointer++] = 1; 349 converted[pointer++] = 0; // Session.compression_null 350 351 /* 352 * Fill in lengths of the messages we synthesized (nested: 353 * V3 handshake message within V3 record). 354 */ 355 // Note: need not to set the header actually. 356 int fragLen = pointer - 5; // TLSPlaintext.length 357 converted[3] = (byte)((fragLen >>> 8) & 0xFF); 358 converted[4] = (byte)(fragLen & 0xFF); 359 360 /* 361 * Handshake.length, length of ClientHello message 362 */ 363 fragLen = pointer - 9; // Handshake.length 364 converted[6] = (byte)((fragLen >>> 16) & 0xFF); 365 converted[7] = (byte)((fragLen >>> 8) & 0xFF); 366 converted[8] = (byte)(fragLen & 0xFF); 367 368 // consume the full record 369 packet.position(srcPos + recordLen); 370 371 // Need no header bytes. 372 return ByteBuffer.wrap(converted, 5, pointer - 5); // 5: header size 373 } 374 375 static ByteBuffer decrypt(Authenticator authenticator, CipherBox box, 376 byte contentType, ByteBuffer bb) throws BadPaddingException { 377 378 return decrypt(authenticator, box, contentType, bb, null); 379 } 380 381 static ByteBuffer decrypt(Authenticator authenticator, 382 CipherBox box, byte contentType, ByteBuffer bb, 383 byte[] sequence) throws BadPaddingException { 384 385 BadPaddingException reservedBPE = null; 386 int tagLen = 387 (authenticator instanceof MAC) ? ((MAC)authenticator).MAClen() : 0; 388 int cipheredLength = bb.remaining(); 389 int srcPos = bb.position(); 390 if (!box.isNullCipher()) { 391 try { 392 // apply explicit nonce for AEAD/CBC cipher suites if needed 393 int nonceSize = box.applyExplicitNonce( 394 authenticator, contentType, bb, sequence); 395 396 // decrypt the content 397 if (box.isAEADMode()) { 398 // DON'T decrypt the nonce_explicit for AEAD mode 399 bb.position(srcPos + nonceSize); 400 } // The explicit IV for CBC mode can be decrypted. 401 402 // Note that the CipherBox.decrypt() does not change 403 // the capacity of the buffer. 404 box.decrypt(bb, tagLen); 405 // We don't actually remove the nonce. 406 bb.position(srcPos + nonceSize); 407 } catch (BadPaddingException bpe) { 408 // RFC 2246 states that decryption_failed should be used 409 // for this purpose. However, that allows certain attacks, 410 // so we just send bad record MAC. We also need to make 411 // sure to always check the MAC to avoid a timing attack 412 // for the same issue. See paper by Vaudenay et al and the 413 // update in RFC 4346/5246. 414 // 415 // Failover to message authentication code checking. 416 reservedBPE = bpe; 417 } 418 } 419 420 // Requires message authentication code for null, stream and block 421 // cipher suites. 422 if ((authenticator instanceof MAC) && (tagLen != 0)) { 423 MAC signer = (MAC)authenticator; 424 int contentLen = bb.remaining() - tagLen; 425 426 // Note that although it is not necessary, we run the same MAC 427 // computation and comparison on the payload for both stream 428 // cipher and CBC block cipher. 429 if (contentLen < 0) { 430 // negative data length, something is wrong 431 if (reservedBPE == null) { 432 reservedBPE = new BadPaddingException("bad record"); 433 } 434 435 // set offset of the dummy MAC 436 contentLen = cipheredLength - tagLen; 437 bb.limit(srcPos + cipheredLength); 438 } 439 440 // Run MAC computation and comparison on the payload. 441 // 442 // MAC data would be stripped off during the check. 443 if (checkMacTags(contentType, bb, signer, sequence, false)) { 444 if (reservedBPE == null) { 445 reservedBPE = new BadPaddingException("bad record MAC"); 446 } 447 } 448 449 // Run MAC computation and comparison on the remainder. 450 // 451 // It is only necessary for CBC block cipher. It is used to get a 452 // constant time of MAC computation and comparison on each record. 453 if (box.isCBCMode()) { 454 int remainingLen = calculateRemainingLen( 455 signer, cipheredLength, contentLen); 456 457 // NOTE: remainingLen may be bigger (less than 1 block of the 458 // hash algorithm of the MAC) than the cipheredLength. 459 // 460 // Is it possible to use a static buffer, rather than allocate 461 // it dynamically? 462 remainingLen += signer.MAClen(); 463 ByteBuffer temporary = ByteBuffer.allocate(remainingLen); 464 465 // Won't need to worry about the result on the remainder. And 466 // then we won't need to worry about what's actual data to 467 // check MAC tag on. We start the check from the header of the 468 // buffer so that we don't need to construct a new byte buffer. 469 checkMacTags(contentType, temporary, signer, sequence, true); 470 } 471 } 472 473 // Is it a failover? 474 if (reservedBPE != null) { 475 throw reservedBPE; 476 } 477 478 return bb.slice(); 479 } 480 481 /* 482 * Run MAC computation and comparison 483 * 484 */ 485 private static boolean checkMacTags(byte contentType, ByteBuffer bb, 486 MAC signer, byte[] sequence, boolean isSimulated) { 487 488 int tagLen = signer.MAClen(); 489 int position = bb.position(); 490 int lim = bb.limit(); 491 int macOffset = lim - tagLen; 492 493 bb.limit(macOffset); 494 byte[] hash = signer.compute(contentType, bb, sequence, isSimulated); 495 if (hash == null || tagLen != hash.length) { 496 // Something is wrong with MAC implementation. 497 throw new RuntimeException("Internal MAC error"); 498 } 499 500 bb.position(macOffset); 501 bb.limit(lim); 502 try { 503 int[] results = compareMacTags(bb, hash); 504 return (results[0] != 0); 505 } finally { 506 // reset to the data 507 bb.position(position); 508 bb.limit(macOffset); 509 } 510 } 511 512 /* 513 * A constant-time comparison of the MAC tags. 514 * 515 * Please DON'T change the content of the ByteBuffer parameter! 516 */ 517 private static int[] compareMacTags(ByteBuffer bb, byte[] tag) { 518 519 // An array of hits is used to prevent Hotspot optimization for 520 // the purpose of a constant-time check. 521 int[] results = {0, 0}; // {missed #, matched #} 522 523 // The caller ensures there are enough bytes available in the buffer. 524 // So we won't need to check the remaining of the buffer. 525 for (int i = 0; i < tag.length; i++) { 526 if (bb.get() != tag[i]) { 527 results[0]++; // mismatched bytes 528 } else { 529 results[1]++; // matched bytes 530 } 531 } 532 533 return results; 534 } 535 536 /* 537 * Run MAC computation and comparison 538 * 539 * Please DON'T change the content of the byte buffer parameter! 540 */ 541 private static boolean checkMacTags(byte contentType, byte[] buffer, 542 int offset, int contentLen, MAC signer, boolean isSimulated) { 543 544 int tagLen = signer.MAClen(); 545 byte[] hash = signer.compute( 546 contentType, buffer, offset, contentLen, isSimulated); 547 if (hash == null || tagLen != hash.length) { 548 // Something is wrong with MAC implementation. 549 throw new RuntimeException("Internal MAC error"); 550 } 551 552 int[] results = compareMacTags(buffer, offset + contentLen, hash); 553 return (results[0] != 0); 554 } 555 556 /* 557 * A constant-time comparison of the MAC tags. 558 * 559 * Please DON'T change the content of the byte buffer parameter! 560 */ 561 private static int[] compareMacTags( 562 byte[] buffer, int offset, byte[] tag) { 563 564 // An array of hits is used to prevent Hotspot optimization for 565 // the purpose of a constant-time check. 566 int[] results = {0, 0}; // {missed #, matched #} 567 568 // The caller ensures there are enough bytes available in the buffer. 569 // So we won't need to check the length of the buffer. 570 for (int i = 0; i < tag.length; i++) { 571 if (buffer[offset + i] != tag[i]) { 572 results[0]++; // mismatched bytes 573 } else { 574 results[1]++; // matched bytes 575 } 576 } 577 578 return results; 579 } 580 581 /* 582 * Calculate the length of a dummy buffer to run MAC computation 583 * and comparison on the remainder. 584 * 585 * The caller MUST ensure that the fullLen is not less than usedLen. 586 */ 587 private static int calculateRemainingLen( 588 MAC signer, int fullLen, int usedLen) { 589 590 int blockLen = signer.hashBlockLen(); 591 int minimalPaddingLen = signer.minimalPaddingLen(); 592 593 // (blockLen - minimalPaddingLen) is the maximum message size of 594 // the last block of hash function operation. See FIPS 180-4, or 595 // MD5 specification. 596 fullLen += 13 - (blockLen - minimalPaddingLen); 597 usedLen += 13 - (blockLen - minimalPaddingLen); 598 599 // Note: fullLen is always not less than usedLen, and blockLen 600 // is always bigger than minimalPaddingLen, so we don't worry 601 // about negative values. 0x01 is added to the result to ensure 602 // that the return value is positive. The extra one byte does 603 // not impact the overall MAC compression function evaluations. 604 return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) - 605 Math.ceil(usedLen/(1.0d * blockLen))) * blockLen; 606 } 607 } 608