1 /* AbstractHandshake.java -- abstract handshake handler. 2 Copyright (C) 2006 Free Software Foundation, Inc. 3 4 This file is a part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or (at 9 your option) any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 USA 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.javax.net.ssl.provider; 40 41 import gnu.classpath.debug.Component; 42 import gnu.classpath.debug.SystemLogger; 43 import gnu.java.security.action.GetSecurityPropertyAction; 44 import gnu.java.security.prng.IRandom; 45 import gnu.java.security.prng.LimitReachedException; 46 import gnu.java.security.util.ByteArray; 47 import gnu.javax.security.auth.callback.CertificateCallback; 48 import gnu.javax.security.auth.callback.DefaultCallbackHandler; 49 50 import java.nio.ByteBuffer; 51 import java.security.AccessController; 52 import java.security.DigestException; 53 import java.security.InvalidAlgorithmParameterException; 54 import java.security.InvalidKeyException; 55 import java.security.KeyManagementException; 56 import java.security.MessageDigest; 57 import java.security.NoSuchAlgorithmException; 58 import java.security.PrivilegedExceptionAction; 59 import java.security.SecureRandom; 60 import java.security.cert.CertificateException; 61 import java.security.cert.X509Certificate; 62 import java.util.Arrays; 63 import java.util.HashMap; 64 import java.util.LinkedList; 65 import java.util.zip.Deflater; 66 import java.util.zip.Inflater; 67 68 import javax.crypto.Cipher; 69 import javax.crypto.KeyAgreement; 70 import javax.crypto.Mac; 71 import javax.crypto.NoSuchPaddingException; 72 import javax.crypto.SecretKey; 73 import javax.crypto.interfaces.DHPrivateKey; 74 import javax.crypto.interfaces.DHPublicKey; 75 import javax.crypto.spec.IvParameterSpec; 76 import javax.crypto.spec.SecretKeySpec; 77 import javax.net.ssl.SSLEngineResult; 78 import javax.net.ssl.SSLException; 79 import javax.net.ssl.X509TrustManager; 80 import javax.net.ssl.SSLEngineResult.HandshakeStatus; 81 import javax.security.auth.callback.Callback; 82 import javax.security.auth.callback.CallbackHandler; 83 import javax.security.auth.callback.ConfirmationCallback; 84 85 /** 86 * The base interface for handshake implementations. Concrete 87 * subclasses of this class (one for the server, one for the client) 88 * handle the HANDSHAKE content-type in communications. 89 */ 90 public abstract class AbstractHandshake 91 { 92 protected static final SystemLogger logger = SystemLogger.SYSTEM; 93 94 /** 95 * "server finished" -- TLS 1.0 and later 96 */ 97 protected static final byte[] SERVER_FINISHED 98 = new byte[] { 99 115, 101, 114, 118, 101, 114, 32, 102, 105, 110, 105, 115, 100 104, 101, 100 101 }; 102 103 /** 104 * "client finished" -- TLS 1.0 and later 105 */ 106 protected static final byte[] CLIENT_FINISHED 107 = new byte[] { 108 99, 108, 105, 101, 110, 116, 32, 102, 105, 110, 105, 115, 109 104, 101, 100 110 }; 111 112 /** 113 * "key expansion" -- TLS 1.0 and later 114 */ 115 private static final byte[] KEY_EXPANSION = 116 new byte[] { 107, 101, 121, 32, 101, 120, 112, 117 97, 110, 115, 105, 111, 110 }; 118 119 /** 120 * "master secret" -- TLS 1.0 and later 121 */ 122 private static final byte[] MASTER_SECRET 123 = new byte[] { 124 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 125 }; 126 127 /** 128 * "client write key" -- TLS 1.0 exportable whitener. 129 */ 130 private static final byte[] CLIENT_WRITE_KEY 131 = new byte[] { 132 99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32, 107, 133 101, 121 134 }; 135 136 /** 137 * "server write key" -- TLS 1.0 exportable whitener. 138 */ 139 private static final byte[] SERVER_WRITE_KEY 140 = new byte[] { 141 115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32, 107, 142 101, 121 143 }; 144 145 private static final byte[] IV_BLOCK 146 = new byte[] { 147 73, 86, 32, 98, 108, 111, 99, 107 148 }; 149 150 /** 151 * SSL 3.0; the string "CLNT" 152 */ 153 private static final byte[] SENDER_CLIENT 154 = new byte[] { 0x43, 0x4C, 0x4E, 0x54 }; 155 156 /** 157 * SSL 3.0; the string "SRVR" 158 */ 159 private static final byte[] SENDER_SERVER 160 = new byte[] { 0x53, 0x52, 0x56, 0x52 }; 161 162 /** 163 * SSL 3.0; the value 0x36 40 (for SHA-1 hashes) or 48 (for MD5 hashes) 164 * times. 165 */ 166 protected static final byte[] PAD1 = new byte[48]; 167 168 /** 169 * SSL 3.0; the value 0x5c 40 (for SHA-1 hashes) or 48 (for MD5 hashes) 170 * times. 171 */ 172 protected static final byte[] PAD2 = new byte[48]; 173 174 static 175 { Arrays.fill(PAD1, SSLHMac.PAD1)176 Arrays.fill(PAD1, SSLHMac.PAD1); Arrays.fill(PAD2, SSLHMac.PAD2)177 Arrays.fill(PAD2, SSLHMac.PAD2); 178 } 179 180 /** 181 * The currently-read handshake messages. There may be zero, or 182 * multiple, handshake messages in this buffer. 183 */ 184 protected ByteBuffer handshakeBuffer; 185 186 /** 187 * The offset into `handshakeBuffer' where the first unread 188 * handshake message resides. 189 */ 190 protected int handshakeOffset; 191 192 protected MessageDigest sha; 193 protected MessageDigest md5; 194 195 protected final SSLEngineImpl engine; 196 protected KeyAgreement keyAgreement; 197 protected byte[] preMasterSecret; 198 protected InputSecurityParameters inParams; 199 protected OutputSecurityParameters outParams; 200 protected LinkedList<DelegatedTask> tasks; 201 protected Random serverRandom; 202 protected Random clientRandom; 203 protected CompressionMethod compression; 204 AbstractHandshake(SSLEngineImpl engine)205 protected AbstractHandshake(SSLEngineImpl engine) 206 throws NoSuchAlgorithmException 207 { 208 this.engine = engine; 209 sha = MessageDigest.getInstance("SHA-1"); 210 md5 = MessageDigest.getInstance("MD5"); 211 tasks = new LinkedList<DelegatedTask>(); 212 } 213 214 /** 215 * Handles the next input message in the handshake. This is called 216 * in response to a call to {@link javax.net.ssl.SSLEngine#unwrap} 217 * for a message with content-type HANDSHAKE. 218 * 219 * @param record The input record. The callee should not assume that 220 * the record's buffer is writable, and should not try to use it for 221 * output or temporary storage. 222 * @return An {@link SSLEngineResult} describing the result. 223 */ handleInput(ByteBuffer fragment)224 public final HandshakeStatus handleInput (ByteBuffer fragment) 225 throws SSLException 226 { 227 if (!tasks.isEmpty()) 228 return HandshakeStatus.NEED_TASK; 229 230 HandshakeStatus status = status(); 231 if (status != HandshakeStatus.NEED_UNWRAP) 232 return status; 233 234 // Try to read another... 235 if (!pollHandshake(fragment)) 236 return HandshakeStatus.NEED_UNWRAP; 237 238 while (hasMessage() && status != HandshakeStatus.NEED_WRAP) 239 { 240 int pos = handshakeOffset; 241 status = implHandleInput(); 242 int len = handshakeOffset - pos; 243 if (len == 0) 244 { 245 // Don't bother; the impl is just telling us to go around 246 // again. 247 continue; 248 } 249 if (doHash()) 250 { 251 if (Debug.DEBUG) 252 logger.logv(Component.SSL_HANDSHAKE, "hashing output\n{0}", 253 Util.hexDump((ByteBuffer) handshakeBuffer 254 .duplicate().position(pos) 255 .limit(pos+len), " >> ")); 256 sha.update((ByteBuffer) handshakeBuffer.duplicate() 257 .position(pos).limit(pos+len)); 258 md5.update((ByteBuffer) handshakeBuffer.duplicate() 259 .position(pos).limit(pos+len)); 260 } 261 } 262 return status; 263 } 264 265 /** 266 * Called to process more handshake data. This method will be called 267 * repeatedly while there is remaining handshake data, and while the 268 * status is 269 * @return 270 * @throws SSLException 271 */ implHandleInput()272 protected abstract HandshakeStatus implHandleInput() 273 throws SSLException; 274 275 /** 276 * Produce more handshake output. This is called in response to a 277 * call to {@link javax.net.ssl.SSLEngine#wrap}, when the handshake 278 * is still in progress. 279 * 280 * @param record The output record; the callee should put its output 281 * handshake message (or a part of it) in the argument's 282 * <code>fragment</code>, and should set the record length 283 * appropriately. 284 * @return An {@link SSLEngineResult} describing the result. 285 */ handleOutput(ByteBuffer fragment)286 public final HandshakeStatus handleOutput (ByteBuffer fragment) 287 throws SSLException 288 { 289 if (!tasks.isEmpty()) 290 return HandshakeStatus.NEED_TASK; 291 292 int orig = fragment.position(); 293 SSLEngineResult.HandshakeStatus status = implHandleOutput(fragment); 294 if (doHash()) 295 { 296 if (Debug.DEBUG) 297 logger.logv(Component.SSL_HANDSHAKE, "hashing output:\n{0}", 298 Util.hexDump((ByteBuffer) fragment.duplicate().flip().position(orig), " >> ")); 299 sha.update((ByteBuffer) fragment.duplicate().flip().position(orig)); 300 md5.update((ByteBuffer) fragment.duplicate().flip().position(orig)); 301 } 302 return status; 303 } 304 305 /** 306 * Called to implement the underlying output handling. The callee should 307 * attempt to fill the given buffer as much as it can; this can include 308 * multiple, and even partial, handshake messages. 309 * 310 * @param fragment The buffer the callee should write handshake messages to. 311 * @return The new status of the handshake. 312 * @throws SSLException If an error occurs processing the output message. 313 */ implHandleOutput(ByteBuffer fragment)314 protected abstract SSLEngineResult.HandshakeStatus implHandleOutput (ByteBuffer fragment) 315 throws SSLException; 316 317 /** 318 * Return a new instance of input security parameters, initialized with 319 * the session key. It is, of course, only valid to invoke this method 320 * once the handshake is complete, and the session keys established. 321 * 322 * <p>In the presence of a well-behaving peer, this should be called once 323 * the <code>ChangeCipherSpec</code> message is recieved. 324 * 325 * @return The input parameters for the newly established session. 326 * @throws SSLException If the handshake is not complete. 327 */ getInputParams()328 final InputSecurityParameters getInputParams() throws SSLException 329 { 330 checkKeyExchange(); 331 return inParams; 332 } 333 334 /** 335 * Return a new instance of output security parameters, initialized with 336 * the session key. This should be called after the 337 * <code>ChangeCipherSpec</code> message is sent to the peer. 338 * 339 * @return The output parameters for the newly established session. 340 * @throws SSLException If the handshake is not complete. 341 */ getOutputParams()342 final OutputSecurityParameters getOutputParams() throws SSLException 343 { 344 checkKeyExchange(); 345 return outParams; 346 } 347 348 /** 349 * Fetch a delegated task waiting to run, if any. 350 * 351 * @return The task. 352 */ getTask()353 final Runnable getTask() 354 { 355 if (tasks.isEmpty()) 356 return null; 357 return tasks.removeFirst(); 358 } 359 360 /** 361 * Used by the skeletal code to query the current status of the handshake. 362 * This <em>should</em> be the same value as returned by the previous call 363 * to {@link #implHandleOutput(ByteBuffer)} or {@link 364 * #implHandleInput(ByteBuffer)}. 365 * 366 * @return The current handshake status. 367 */ status()368 abstract HandshakeStatus status(); 369 370 /** 371 * Check if the key exchange completed successfully, throwing an exception 372 * if not. 373 * 374 * <p>Note that we assume that the caller of our SSLEngine is correct, and 375 * that they did run the delegated tasks that encapsulate the key exchange. 376 * What we are primarily checking, therefore, is that no error occurred in the 377 * key exchange operation itself. 378 * 379 * @throws SSLException If the key exchange did not complete successfully. 380 */ checkKeyExchange()381 abstract void checkKeyExchange() throws SSLException; 382 383 /** 384 * Handle an SSLv2 client hello. This is only used by SSL servers. 385 * 386 * @param hello The hello message. 387 */ handleV2Hello(ByteBuffer hello)388 abstract void handleV2Hello(ByteBuffer hello) throws SSLException; 389 390 /** 391 * Attempt to read the next handshake message from the given 392 * record. If only a partial handshake message is available, then 393 * this method saves the incoming bytes and returns false. If a 394 * complete handshake is read, or if there was one buffered in the 395 * handshake buffer, this method returns true, and `handshakeBuffer' 396 * can be used to read the handshake. 397 * 398 * @param record The input record. 399 * @return True if a complete handshake is present in the buffer; 400 * false if only a partial one. 401 */ pollHandshake(final ByteBuffer fragment)402 protected boolean pollHandshake (final ByteBuffer fragment) 403 { 404 // Allocate space for the new fragment. 405 if (handshakeBuffer == null 406 || handshakeBuffer.remaining() < fragment.remaining()) 407 { 408 // We need space for anything still unread in the handshake 409 // buffer... 410 int len = ((handshakeBuffer == null) ? 0 411 : handshakeBuffer.position() - handshakeOffset); 412 413 // Plus room for the incoming record. 414 len += fragment.remaining(); 415 reallocateBuffer(len); 416 } 417 418 if (Debug.DEBUG) 419 logger.logv(Component.SSL_HANDSHAKE, "inserting {0} into {1}", 420 fragment, handshakeBuffer); 421 422 // Put the fragment into the buffer. 423 handshakeBuffer.put(fragment); 424 425 return hasMessage(); 426 } 427 doHash()428 protected boolean doHash() 429 { 430 return true; 431 } 432 433 /** 434 * Tell if the handshake buffer currently has a full handshake 435 * message. 436 */ hasMessage()437 protected boolean hasMessage() 438 { 439 if (handshakeBuffer == null) 440 return false; 441 ByteBuffer tmp = handshakeBuffer.duplicate(); 442 tmp.flip(); 443 tmp.position(handshakeOffset); 444 if (Debug.DEBUG) 445 logger.logv(Component.SSL_HANDSHAKE, "current buffer: {0}; test buffer {1}", 446 handshakeBuffer, tmp); 447 if (tmp.remaining() < 4) 448 return false; 449 Handshake handshake = new Handshake(tmp.slice()); 450 if (Debug.DEBUG) 451 logger.logv(Component.SSL_HANDSHAKE, "handshake len:{0} remaining:{1}", 452 handshake.length(), tmp.remaining()); 453 return (handshake.length() <= tmp.remaining() - 4); 454 } 455 456 /** 457 * Reallocate the handshake buffer so it can hold `totalLen' 458 * bytes. The smallest buffer allocated is 1024 bytes, and the size 459 * doubles from there until the buffer is sufficiently large. 460 */ reallocateBuffer(final int totalLen)461 private void reallocateBuffer (final int totalLen) 462 { 463 int len = handshakeBuffer == null ? -1 464 : handshakeBuffer.capacity() - (handshakeBuffer.limit() - handshakeOffset); 465 if (len >= totalLen) 466 { 467 // Big enough; no need to reallocate; but maybe shift the contents 468 // down. 469 if (handshakeOffset > 0) 470 { 471 handshakeBuffer.flip().position(handshakeOffset); 472 handshakeBuffer.compact(); 473 handshakeOffset = 0; 474 } 475 return; 476 } 477 478 // Start at 1K (probably the system's page size). Double the size 479 // from there. 480 len = 1024; 481 while (len < totalLen) 482 len = len << 1; 483 ByteBuffer newBuf = ByteBuffer.allocate (len); 484 485 // Copy the unread bytes from the old buffer. 486 if (handshakeBuffer != null) 487 { 488 handshakeBuffer.flip (); 489 handshakeBuffer.position(handshakeOffset); 490 newBuf.put(handshakeBuffer); 491 } 492 handshakeBuffer = newBuf; 493 494 // We just put only unread handshake messages in the new buffer; 495 // the offset of the next one is now zero. 496 handshakeOffset = 0; 497 } 498 499 /** 500 * Generate a certificate verify message for SSLv3. In SSLv3, a different 501 * algorithm was used to generate this value was subtly different than 502 * that used in TLSv1.0 and later. In TLSv1.0 and later, this value is 503 * just the digest over the handshake messages. 504 * 505 * <p>SSLv3 uses the algorithm: 506 * 507 * <pre> 508 CertificateVerify.signature.md5_hash 509 MD5(master_secret + pad_2 + 510 MD5(handshake_messages + master_secret + pad_1)); 511 Certificate.signature.sha_hash 512 SHA(master_secret + pad_2 + 513 SHA(handshake_messages + master_secret + pad_1));</pre> 514 * 515 * @param md5 The running MD5 hash of the handshake. 516 * @param sha The running SHA-1 hash of the handshake. 517 * @param session The current session being negotiated. 518 * @return The computed to-be-signed value. 519 */ genV3CertificateVerify(MessageDigest md5, MessageDigest sha, SessionImpl session)520 protected byte[] genV3CertificateVerify(MessageDigest md5, 521 MessageDigest sha, 522 SessionImpl session) 523 { 524 byte[] md5value = null; 525 if (session.suite.signatureAlgorithm() == SignatureAlgorithm.RSA) 526 { 527 md5.update(session.privateData.masterSecret); 528 md5.update(PAD1, 0, 48); 529 byte[] tmp = md5.digest(); 530 md5.reset(); 531 md5.update(session.privateData.masterSecret); 532 md5.update(PAD2, 0, 48); 533 md5.update(tmp); 534 md5value = md5.digest(); 535 } 536 537 sha.update(session.privateData.masterSecret); 538 sha.update(PAD1, 0, 40); 539 byte[] tmp = sha.digest(); 540 sha.reset(); 541 sha.update(session.privateData.masterSecret); 542 sha.update(PAD2, 0, 40); 543 sha.update(tmp); 544 byte[] shavalue = sha.digest(); 545 546 if (md5value != null) 547 return Util.concat(md5value, shavalue); 548 549 return shavalue; 550 } 551 552 /** 553 * Generate the session keys from the computed master secret. 554 * 555 * @param clientRandom The client's nonce. 556 * @param serverRandom The server's nonce. 557 * @param session The session being established. 558 * @return The derived keys. 559 */ generateKeys(Random clientRandom, Random serverRandom, SessionImpl session)560 protected byte[][] generateKeys(Random clientRandom, Random serverRandom, 561 SessionImpl session) 562 { 563 int maclen = 20; // SHA-1. 564 if (session.suite.macAlgorithm() == MacAlgorithm.MD5) 565 maclen = 16; 566 int ivlen = 0; 567 if (session.suite.cipherAlgorithm() == CipherAlgorithm.DES 568 || session.suite.cipherAlgorithm() == CipherAlgorithm.DESede) 569 ivlen = 8; 570 if (session.suite.cipherAlgorithm() == CipherAlgorithm.AES) 571 ivlen = 16; 572 int keylen = session.suite.keyLength(); 573 574 byte[][] keys = new byte[6][]; 575 keys[0] = new byte[maclen]; // client_write_MAC_secret 576 keys[1] = new byte[maclen]; // server_write_MAC_secret 577 keys[2] = new byte[keylen]; // client_write_key 578 keys[3] = new byte[keylen]; // server_write_key 579 keys[4] = new byte[ivlen]; // client_write_iv 580 keys[5] = new byte[ivlen]; // server_write_iv 581 582 IRandom prf = null; 583 if (session.version == ProtocolVersion.SSL_3) 584 { 585 byte[] seed = new byte[clientRandom.length() 586 + serverRandom.length()]; 587 serverRandom.buffer().get(seed, 0, serverRandom.length()); 588 clientRandom.buffer().get(seed, serverRandom.length(), 589 clientRandom.length()); 590 prf = new SSLRandom(); 591 HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2); 592 attr.put(SSLRandom.SECRET, session.privateData.masterSecret); 593 attr.put(SSLRandom.SEED, seed); 594 prf.init(attr); 595 } 596 else 597 { 598 byte[] seed = new byte[KEY_EXPANSION.length 599 + clientRandom.length() 600 + serverRandom.length()]; 601 System.arraycopy(KEY_EXPANSION, 0, seed, 0, KEY_EXPANSION.length); 602 serverRandom.buffer().get(seed, KEY_EXPANSION.length, 603 serverRandom.length()); 604 clientRandom.buffer().get(seed, (KEY_EXPANSION.length 605 + serverRandom.length()), 606 clientRandom.length()); 607 608 prf = new TLSRandom(); 609 HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2); 610 attr.put(TLSRandom.SECRET, session.privateData.masterSecret); 611 attr.put(TLSRandom.SEED, seed); 612 prf.init(attr); 613 } 614 615 try 616 { 617 prf.nextBytes(keys[0], 0, keys[0].length); 618 prf.nextBytes(keys[1], 0, keys[1].length); 619 prf.nextBytes(keys[2], 0, keys[2].length); 620 prf.nextBytes(keys[3], 0, keys[3].length); 621 622 if (session.suite.isExportable()) 623 { 624 if (session.version == ProtocolVersion.SSL_3) 625 { 626 MessageDigest md5 = MessageDigest.getInstance("MD5"); 627 md5.update(clientRandom.buffer()); 628 md5.update(serverRandom.buffer()); 629 byte[] d = md5.digest(); 630 System.arraycopy(d, 0, keys[4], 0, keys[4].length); 631 632 md5.reset(); 633 md5.update(serverRandom.buffer()); 634 md5.update(clientRandom.buffer()); 635 d = md5.digest(); 636 System.arraycopy(d, 0, keys[5], 0, keys[5].length); 637 638 md5.reset(); 639 md5.update(keys[2]); 640 md5.update(clientRandom.buffer()); 641 md5.update(serverRandom.buffer()); 642 keys[2] = Util.trim(md5.digest(), 8); 643 644 md5.reset(); 645 md5.update(keys[3]); 646 md5.update(serverRandom.buffer()); 647 md5.update(clientRandom.buffer()); 648 keys[3] = Util.trim(md5.digest(), 8); 649 } 650 else 651 { 652 TLSRandom prf2 = new TLSRandom(); 653 HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2); 654 attr.put(TLSRandom.SECRET, keys[2]); 655 byte[] seed = new byte[CLIENT_WRITE_KEY.length + 656 clientRandom.length() + 657 serverRandom.length()]; 658 System.arraycopy(CLIENT_WRITE_KEY, 0, seed, 0, 659 CLIENT_WRITE_KEY.length); 660 clientRandom.buffer().get(seed, CLIENT_WRITE_KEY.length, 661 clientRandom.length()); 662 serverRandom.buffer().get(seed, CLIENT_WRITE_KEY.length 663 + clientRandom.length(), 664 serverRandom.length()); 665 attr.put(TLSRandom.SEED, seed); 666 prf2.init(attr); 667 keys[2] = new byte[8]; 668 prf2.nextBytes(keys[2], 0, keys[2].length); 669 670 attr.put(TLSRandom.SECRET, keys[3]); 671 seed = new byte[SERVER_WRITE_KEY.length + 672 serverRandom.length() + 673 clientRandom.length()]; 674 System.arraycopy(SERVER_WRITE_KEY, 0, seed, 0, 675 SERVER_WRITE_KEY.length); 676 serverRandom.buffer().get(seed, SERVER_WRITE_KEY.length, 677 serverRandom.length()); 678 clientRandom.buffer().get(seed, SERVER_WRITE_KEY.length 679 + serverRandom.length(), 680 + clientRandom.length()); 681 attr.put(TLSRandom.SEED, seed); 682 prf2.init(attr); 683 keys[3] = new byte[8]; 684 prf2.nextBytes(keys[3], 0, keys[3].length); 685 686 attr.put(TLSRandom.SECRET, new byte[0]); 687 seed = new byte[IV_BLOCK.length + 688 clientRandom.length() + 689 serverRandom.length()]; 690 System.arraycopy(IV_BLOCK, 0, seed, 0, IV_BLOCK.length); 691 clientRandom.buffer().get(seed, IV_BLOCK.length, 692 clientRandom.length()); 693 serverRandom.buffer().get(seed, IV_BLOCK.length 694 + clientRandom.length(), 695 serverRandom.length()); 696 attr.put(TLSRandom.SEED, seed); 697 prf2.init(attr); 698 prf2.nextBytes(keys[4], 0, keys[4].length); 699 prf2.nextBytes(keys[5], 0, keys[5].length); 700 } 701 } 702 else 703 { 704 prf.nextBytes(keys[4], 0, keys[4].length); 705 prf.nextBytes(keys[5], 0, keys[5].length); 706 } 707 } 708 catch (LimitReachedException lre) 709 { 710 // Won't happen with our implementation. 711 throw new Error(lre); 712 } 713 catch (NoSuchAlgorithmException nsae) 714 { 715 throw new Error(nsae); 716 } 717 718 if (Debug.DEBUG_KEY_EXCHANGE) 719 logger.logv(Component.SSL_KEY_EXCHANGE, 720 "keys generated;\n [0]: {0}\n [1]: {1}\n [2]: {2}\n" + 721 " [3]: {3}\n [4]: {4}\n [5]: {5}", 722 Util.toHexString(keys[0], ':'), 723 Util.toHexString(keys[1], ':'), 724 Util.toHexString(keys[2], ':'), 725 Util.toHexString(keys[3], ':'), 726 Util.toHexString(keys[4], ':'), 727 Util.toHexString(keys[5], ':')); 728 return keys; 729 } 730 731 /** 732 * Generate a "finished" message. The hashes passed in are modified 733 * by this function, so they should be clone copies of the digest if 734 * the hash function needs to be used more. 735 * 736 * @param md5 The MD5 computation. 737 * @param sha The SHA-1 computation. 738 * @param isClient Whether or not the client-side finished message is 739 * being computed. 740 * @param session The current session. 741 * @return A byte buffer containing the computed finished message. 742 */ generateFinished(MessageDigest md5, MessageDigest sha, boolean isClient, SessionImpl session)743 protected ByteBuffer generateFinished(MessageDigest md5, 744 MessageDigest sha, 745 boolean isClient, 746 SessionImpl session) 747 { 748 ByteBuffer finishedBuffer = null; 749 if (session.version.compareTo(ProtocolVersion.TLS_1) >= 0) 750 { 751 finishedBuffer = ByteBuffer.allocate(12); 752 TLSRandom prf = new TLSRandom(); 753 byte[] md5val = md5.digest(); 754 byte[] shaval = sha.digest(); 755 if (Debug.DEBUG) 756 logger.logv(Component.SSL_HANDSHAKE, "finished md5:{0} sha:{1}", 757 Util.toHexString(md5val, ':'), 758 Util.toHexString(shaval, ':')); 759 byte[] seed = new byte[CLIENT_FINISHED.length 760 + md5val.length 761 + shaval.length]; 762 if (isClient) 763 System.arraycopy(CLIENT_FINISHED, 0, seed, 0, CLIENT_FINISHED.length); 764 else 765 System.arraycopy(SERVER_FINISHED, 0, seed, 0, SERVER_FINISHED.length); 766 System.arraycopy(md5val, 0, 767 seed, CLIENT_FINISHED.length, 768 md5val.length); 769 System.arraycopy(shaval, 0, 770 seed, CLIENT_FINISHED.length + md5val.length, 771 shaval.length); 772 HashMap<String, Object> params = new HashMap<String, Object>(2); 773 params.put(TLSRandom.SECRET, session.privateData.masterSecret); 774 params.put(TLSRandom.SEED, seed); 775 prf.init(params); 776 byte[] buf = new byte[12]; 777 prf.nextBytes(buf, 0, buf.length); 778 finishedBuffer.put(buf).position(0); 779 } 780 else 781 { 782 // The SSLv3 algorithm is: 783 // 784 // enum { client(0x434C4E54), server(0x53525652) } Sender; 785 // 786 // struct { 787 // opaque md5_hash[16]; 788 // opaque sha_hash[20]; 789 // } Finished; 790 // 791 // md5_hash MD5(master_secret + pad2 + 792 // MD5(handshake_messages + Sender + 793 // master_secret + pad1)); 794 // sha_hash SHA(master_secret + pad2 + 795 // SHA(handshake_messages + Sender + 796 // master_secret + pad1)); 797 // 798 799 finishedBuffer = ByteBuffer.allocate(36); 800 801 md5.update(isClient ? SENDER_CLIENT : SENDER_SERVER); 802 md5.update(session.privateData.masterSecret); 803 md5.update(PAD1); 804 805 byte[] tmp = md5.digest(); 806 md5.reset(); 807 md5.update(session.privateData.masterSecret); 808 md5.update(PAD2); 809 md5.update(tmp); 810 finishedBuffer.put(md5.digest()); 811 812 sha.update(isClient ? SENDER_CLIENT : SENDER_SERVER); 813 sha.update(session.privateData.masterSecret); 814 sha.update(PAD1, 0, 40); 815 816 tmp = sha.digest(); 817 sha.reset(); 818 sha.update(session.privateData.masterSecret); 819 sha.update(PAD2, 0, 40); 820 sha.update(tmp); 821 finishedBuffer.put(sha.digest()).position(0); 822 } 823 return finishedBuffer; 824 } 825 initDiffieHellman(DHPrivateKey dhKey, SecureRandom random)826 protected void initDiffieHellman(DHPrivateKey dhKey, SecureRandom random) 827 throws SSLException 828 { 829 try 830 { 831 keyAgreement = KeyAgreement.getInstance("DH"); 832 keyAgreement.init(dhKey, random); 833 } 834 catch (InvalidKeyException ike) 835 { 836 throw new SSLException(ike); 837 } 838 catch (NoSuchAlgorithmException nsae) 839 { 840 throw new SSLException(nsae); 841 } 842 } 843 generateMasterSecret(Random clientRandom, Random serverRandom, SessionImpl session)844 protected void generateMasterSecret(Random clientRandom, 845 Random serverRandom, 846 SessionImpl session) 847 throws SSLException 848 { 849 assert(clientRandom != null); 850 assert(serverRandom != null); 851 assert(session != null); 852 853 if (Debug.DEBUG_KEY_EXCHANGE) 854 logger.logv(Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}", 855 new ByteArray(preMasterSecret)); 856 857 if (session.version == ProtocolVersion.SSL_3) 858 { 859 try 860 { 861 MessageDigest _md5 = MessageDigest.getInstance("MD5"); 862 MessageDigest _sha = MessageDigest.getInstance("SHA"); 863 session.privateData.masterSecret = new byte[48]; 864 865 _sha.update((byte) 'A'); 866 _sha.update(preMasterSecret); 867 _sha.update(clientRandom.buffer()); 868 _sha.update(serverRandom.buffer()); 869 _md5.update(preMasterSecret); 870 _md5.update(_sha.digest()); 871 _md5.digest(session.privateData.masterSecret, 0, 16); 872 873 _sha.update((byte) 'B'); 874 _sha.update((byte) 'B'); 875 _sha.update(preMasterSecret); 876 _sha.update(clientRandom.buffer()); 877 _sha.update(serverRandom.buffer()); 878 _md5.update(preMasterSecret); 879 _md5.update(_sha.digest()); 880 _md5.digest(session.privateData.masterSecret, 16, 16); 881 882 _sha.update((byte) 'C'); 883 _sha.update((byte) 'C'); 884 _sha.update((byte) 'C'); 885 _sha.update(preMasterSecret); 886 _sha.update(clientRandom.buffer()); 887 _sha.update(serverRandom.buffer()); 888 _md5.update(preMasterSecret); 889 _md5.update(_sha.digest()); 890 _md5.digest(session.privateData.masterSecret, 32, 16); 891 } 892 catch (DigestException de) 893 { 894 throw new SSLException(de); 895 } 896 catch (NoSuchAlgorithmException nsae) 897 { 898 throw new SSLException(nsae); 899 } 900 } 901 else // TLSv1.0 and later 902 { 903 byte[] seed = new byte[clientRandom.length() 904 + serverRandom.length() 905 + MASTER_SECRET.length]; 906 System.arraycopy(MASTER_SECRET, 0, seed, 0, MASTER_SECRET.length); 907 clientRandom.buffer().get(seed, MASTER_SECRET.length, 908 clientRandom.length()); 909 serverRandom.buffer().get(seed, 910 MASTER_SECRET.length + clientRandom.length(), 911 serverRandom.length()); 912 TLSRandom prf = new TLSRandom(); 913 HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2); 914 attr.put(TLSRandom.SECRET, preMasterSecret); 915 attr.put(TLSRandom.SEED, seed); 916 prf.init(attr); 917 918 session.privateData.masterSecret = new byte[48]; 919 prf.nextBytes(session.privateData.masterSecret, 0, 48); 920 } 921 922 if (Debug.DEBUG_KEY_EXCHANGE) 923 logger.log(Component.SSL_KEY_EXCHANGE, "master_secret: {0}", 924 new ByteArray(session.privateData.masterSecret)); 925 926 // Wipe out the preMasterSecret. 927 for (int i = 0; i < preMasterSecret.length; i++) 928 preMasterSecret[i] = 0; 929 } 930 setupSecurityParameters(byte[][] keys, boolean isClient, SSLEngineImpl engine, CompressionMethod compression)931 protected void setupSecurityParameters(byte[][] keys, boolean isClient, 932 SSLEngineImpl engine, 933 CompressionMethod compression) 934 throws SSLException 935 { 936 assert(keys.length == 6); 937 assert(engine != null); 938 assert(compression != null); 939 940 try 941 { 942 CipherSuite s = engine.session().suite; 943 Cipher inCipher = s.cipher(); 944 Mac inMac = s.mac(engine.session().version); 945 Inflater inflater = (compression == CompressionMethod.ZLIB 946 ? new Inflater() : null); 947 inCipher.init(Cipher.DECRYPT_MODE, 948 new SecretKeySpec(keys[isClient ? 3 : 2], 949 s.cipherAlgorithm().toString()), 950 new IvParameterSpec(keys[isClient ? 5 : 4])); 951 inMac.init(new SecretKeySpec(keys[isClient ? 1 : 0], 952 inMac.getAlgorithm())); 953 inParams = new InputSecurityParameters(inCipher, inMac, 954 inflater, 955 engine.session(), s); 956 957 Cipher outCipher = s.cipher(); 958 Mac outMac = s.mac(engine.session().version); 959 Deflater deflater = (compression == CompressionMethod.ZLIB 960 ? new Deflater() : null); 961 outCipher.init(Cipher.ENCRYPT_MODE, 962 new SecretKeySpec(keys[isClient ? 2 : 3], 963 s.cipherAlgorithm().toString()), 964 new IvParameterSpec(keys[isClient ? 4 : 5])); 965 outMac.init(new SecretKeySpec(keys[isClient ? 0 : 1], 966 outMac.getAlgorithm())); 967 outParams = new OutputSecurityParameters(outCipher, outMac, 968 deflater, 969 engine.session(), s); 970 } 971 catch (InvalidAlgorithmParameterException iape) 972 { 973 throw new SSLException(iape); 974 } 975 catch (InvalidKeyException ike) 976 { 977 throw new SSLException(ike); 978 } 979 catch (NoSuchAlgorithmException nsae) 980 { 981 throw new SSLException(nsae); 982 } 983 catch (NoSuchPaddingException nspe) 984 { 985 throw new SSLException(nspe); 986 } 987 } 988 generatePSKSecret(String identity, byte[] otherkey, boolean isClient)989 protected void generatePSKSecret(String identity, byte[] otherkey, 990 boolean isClient) 991 throws SSLException 992 { 993 SecretKey key = null; 994 try 995 { 996 key = engine.contextImpl.pskManager.getKey(identity); 997 } 998 catch (KeyManagementException kme) 999 { 1000 } 1001 if (key != null) 1002 { 1003 byte[] keyb = key.getEncoded(); 1004 if (otherkey == null) 1005 { 1006 otherkey = new byte[keyb.length]; 1007 } 1008 preMasterSecret = new byte[otherkey.length + keyb.length + 4]; 1009 preMasterSecret[0] = (byte) (otherkey.length >>> 8); 1010 preMasterSecret[1] = (byte) otherkey.length; 1011 System.arraycopy(otherkey, 0, preMasterSecret, 2, otherkey.length); 1012 preMasterSecret[otherkey.length + 2] 1013 = (byte) (keyb.length >>> 8); 1014 preMasterSecret[otherkey.length + 3] 1015 = (byte) keyb.length; 1016 System.arraycopy(keyb, 0, preMasterSecret, 1017 otherkey.length + 4, keyb.length); 1018 } 1019 else 1020 { 1021 // Generate a random, fake secret. 1022 preMasterSecret = new byte[8]; 1023 preMasterSecret[1] = 2; 1024 preMasterSecret[5] = 2; 1025 preMasterSecret[6] = (byte) engine.session().random().nextInt(); 1026 preMasterSecret[7] = (byte) engine.session().random().nextInt(); 1027 } 1028 1029 if (Debug.DEBUG_KEY_EXCHANGE) 1030 logger.logv(Component.SSL_KEY_EXCHANGE, "PSK identity {0} key {1}", 1031 identity, key); 1032 1033 generateMasterSecret(clientRandom, serverRandom, 1034 engine.session()); 1035 byte[][] keys = generateKeys(clientRandom, serverRandom, 1036 engine.session()); 1037 setupSecurityParameters(keys, isClient, engine, compression); 1038 } 1039 1040 protected class DHPhase extends DelegatedTask 1041 { 1042 private final DHPublicKey key; 1043 private final boolean full; 1044 DHPhase(DHPublicKey key)1045 protected DHPhase(DHPublicKey key) 1046 { 1047 this(key, true); 1048 } 1049 DHPhase(DHPublicKey key, boolean full)1050 protected DHPhase(DHPublicKey key, boolean full) 1051 { 1052 this.key = key; 1053 this.full = full; 1054 } 1055 implRun()1056 protected void implRun() throws InvalidKeyException, SSLException 1057 { 1058 keyAgreement.doPhase(key, true); 1059 preMasterSecret = keyAgreement.generateSecret(); 1060 if (full) 1061 { 1062 generateMasterSecret(clientRandom, serverRandom, engine.session()); 1063 byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session()); 1064 setupSecurityParameters(keys, engine.getUseClientMode(), engine, compression); 1065 } 1066 } 1067 } 1068 1069 protected class CertVerifier extends DelegatedTask 1070 { 1071 private final boolean clientSide; 1072 private final X509Certificate[] chain; 1073 private boolean verified; 1074 CertVerifier(boolean clientSide, X509Certificate[] chain)1075 protected CertVerifier(boolean clientSide, X509Certificate[] chain) 1076 { 1077 this.clientSide = clientSide; 1078 this.chain = chain; 1079 } 1080 verified()1081 boolean verified() 1082 { 1083 return verified; 1084 } 1085 implRun()1086 protected void implRun() 1087 { 1088 X509TrustManager tm = engine.contextImpl.trustManager; 1089 if (clientSide) 1090 { 1091 try 1092 { 1093 tm.checkServerTrusted(chain, null); 1094 verified = true; 1095 } 1096 catch (CertificateException ce) 1097 { 1098 if (Debug.DEBUG) 1099 logger.log(Component.SSL_DELEGATED_TASK, "cert verify", ce); 1100 // For client connections, ask the user if the certificate is OK. 1101 CallbackHandler verify = new DefaultCallbackHandler(); 1102 GetSecurityPropertyAction gspa 1103 = new GetSecurityPropertyAction("jessie.certificate.handler"); 1104 String clazz = AccessController.doPrivileged(gspa); 1105 try 1106 { 1107 ClassLoader cl = 1108 AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>() 1109 { 1110 public ClassLoader run() throws Exception 1111 { 1112 return ClassLoader.getSystemClassLoader(); 1113 } 1114 }); 1115 verify = (CallbackHandler) cl.loadClass(clazz).newInstance(); 1116 } 1117 catch (Exception x) 1118 { 1119 // Ignore. 1120 if (Debug.DEBUG) 1121 logger.log(Component.SSL_DELEGATED_TASK, 1122 "callback handler loading", x); 1123 } 1124 // XXX Internationalize 1125 CertificateCallback confirm = 1126 new CertificateCallback(chain[0], 1127 "The server's certificate could not be verified. There is no proof " + 1128 "that this server is who it claims to be, or that their certificate " + 1129 "is valid. Do you wish to continue connecting? "); 1130 1131 try 1132 { 1133 verify.handle(new Callback[] { confirm }); 1134 verified = confirm.getSelectedIndex() == ConfirmationCallback.YES; 1135 } 1136 catch (Exception x) 1137 { 1138 if (Debug.DEBUG) 1139 logger.log(Component.SSL_DELEGATED_TASK, 1140 "callback handler exception", x); 1141 verified = false; 1142 } 1143 } 1144 } 1145 else 1146 { 1147 try 1148 { 1149 tm.checkClientTrusted(chain, null); 1150 } 1151 catch (CertificateException ce) 1152 { 1153 verified = false; 1154 } 1155 } 1156 1157 if (verified) 1158 engine.session().setPeerVerified(true); 1159 } 1160 } 1161 1162 protected class DHE_PSKGen extends DelegatedTask 1163 { 1164 private final DHPublicKey dhKey; 1165 private final SecretKey psKey; 1166 private final boolean isClient; 1167 DHE_PSKGen(DHPublicKey dhKey, SecretKey psKey, boolean isClient)1168 protected DHE_PSKGen(DHPublicKey dhKey, SecretKey psKey, boolean isClient) 1169 { 1170 this.dhKey = dhKey; 1171 this.psKey = psKey; 1172 this.isClient = isClient; 1173 } 1174 1175 /* (non-Javadoc) 1176 * @see gnu.javax.net.ssl.provider.DelegatedTask#implRun() 1177 */ implRun()1178 @Override protected void implRun() throws Throwable 1179 { 1180 keyAgreement.doPhase(dhKey, true); 1181 byte[] dhSecret = keyAgreement.generateSecret(); 1182 byte[] psSecret = null; 1183 if (psKey != null) 1184 psSecret = psKey.getEncoded(); 1185 else 1186 { 1187 psSecret = new byte[8]; 1188 engine.session().random().nextBytes(psSecret); 1189 } 1190 1191 preMasterSecret = new byte[dhSecret.length + psSecret.length + 4]; 1192 preMasterSecret[0] = (byte) (dhSecret.length >>> 8); 1193 preMasterSecret[1] = (byte) dhSecret.length; 1194 System.arraycopy(dhSecret, 0, preMasterSecret, 2, dhSecret.length); 1195 preMasterSecret[dhSecret.length + 2] = (byte) (psSecret.length >>> 8); 1196 preMasterSecret[dhSecret.length + 3] = (byte) psSecret.length; 1197 System.arraycopy(psSecret, 0, preMasterSecret, dhSecret.length + 4, 1198 psSecret.length); 1199 1200 generateMasterSecret(clientRandom, serverRandom, engine.session()); 1201 byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session()); 1202 setupSecurityParameters(keys, isClient, engine, compression); 1203 } 1204 } 1205 } 1206