1 /* ServerHandshake.java -- the server-side handshake. 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 static gnu.javax.net.ssl.provider.Handshake.Type.*; 42 import static gnu.javax.net.ssl.provider.KeyExchangeAlgorithm.*; 43 import static gnu.javax.net.ssl.provider.ServerHandshake.State.*; 44 45 import gnu.classpath.debug.Component; 46 import gnu.java.security.action.GetSecurityPropertyAction; 47 import gnu.javax.crypto.key.dh.GnuDHPublicKey; 48 import gnu.javax.net.ssl.AbstractSessionContext; 49 import gnu.javax.net.ssl.Session; 50 import gnu.javax.net.ssl.provider.Alert.Description; 51 import gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType; 52 53 import java.nio.ByteBuffer; 54 55 import java.security.AccessController; 56 import java.security.InvalidAlgorithmParameterException; 57 import java.security.InvalidKeyException; 58 import java.security.KeyManagementException; 59 import java.security.KeyPair; 60 import java.security.KeyPairGenerator; 61 import java.security.MessageDigest; 62 import java.security.NoSuchAlgorithmException; 63 import java.security.Principal; 64 import java.security.PrivateKey; 65 import java.security.SignatureException; 66 import java.security.cert.CertificateException; 67 import java.security.cert.X509Certificate; 68 import java.util.ArrayList; 69 import java.util.Arrays; 70 import java.util.HashSet; 71 import java.util.List; 72 import java.util.logging.Level; 73 import java.util.zip.Deflater; 74 import java.util.zip.Inflater; 75 76 import javax.crypto.BadPaddingException; 77 import javax.crypto.Cipher; 78 import javax.crypto.IllegalBlockSizeException; 79 import javax.crypto.NoSuchPaddingException; 80 import javax.crypto.SecretKey; 81 import javax.crypto.interfaces.DHPrivateKey; 82 import javax.crypto.interfaces.DHPublicKey; 83 import javax.crypto.spec.DHParameterSpec; 84 import javax.crypto.spec.SecretKeySpec; 85 import javax.net.ssl.SSLException; 86 import javax.net.ssl.SSLPeerUnverifiedException; 87 import javax.net.ssl.SSLSession; 88 import javax.net.ssl.X509ExtendedKeyManager; 89 import javax.net.ssl.SSLEngineResult.HandshakeStatus; 90 import javax.security.auth.x500.X500Principal; 91 92 class ServerHandshake extends AbstractHandshake 93 { 94 /** 95 * Handshake state enumeration. 96 */ 97 static enum State 98 { 99 WRITE_HELLO_REQUEST (true, false), 100 WRITE_SERVER_HELLO (true, false), 101 WRITE_CERTIFICATE (true, false), 102 WRITE_SERVER_KEY_EXCHANGE (true, false), 103 WRITE_CERTIFICATE_REQUEST (true, false), 104 WRITE_SERVER_HELLO_DONE (true, false), 105 WRITE_FINISHED (true, false), 106 READ_CLIENT_HELLO (false, true), 107 READ_CERTIFICATE (false, true), 108 READ_CLIENT_KEY_EXCHANGE (false, true), 109 READ_CERTIFICATE_VERIFY (false, true), 110 READ_FINISHED (false, true), 111 DONE (false, false); 112 113 private final boolean isWriteState; 114 private final boolean isReadState; 115 State(final boolean isWriteState, final boolean isReadState)116 private State(final boolean isWriteState, final boolean isReadState) 117 { 118 this.isWriteState = isWriteState; 119 this.isReadState = isReadState; 120 } 121 isReadState()122 boolean isReadState() 123 { 124 return isReadState; 125 } 126 isWriteState()127 boolean isWriteState() 128 { 129 return isWriteState; 130 } 131 } 132 133 private State state; 134 135 /* Handshake result fields. */ 136 private ByteBuffer outBuffer; 137 private boolean clientHadExtensions = false; 138 private boolean continuedSession = false; 139 private ServerNameList requestedNames = null; 140 private String keyAlias = null; 141 private X509Certificate clientCert = null; 142 private X509Certificate localCert = null; 143 private boolean helloV2 = false; 144 private KeyPair dhPair; 145 private PrivateKey serverKey; 146 147 // Delegated tasks we use. 148 private GenDH genDH; 149 private CertVerifier certVerifier; 150 private CertLoader certLoader; 151 private DelegatedTask keyExchangeTask; 152 ServerHandshake(boolean writeHelloRequest, final SSLEngineImpl engine)153 ServerHandshake (boolean writeHelloRequest, final SSLEngineImpl engine) 154 throws NoSuchAlgorithmException 155 { 156 super(engine); 157 if (writeHelloRequest) 158 state = WRITE_HELLO_REQUEST; 159 else 160 state = READ_CLIENT_HELLO; 161 handshakeOffset = 0; 162 } 163 164 /** 165 * Choose the protocol version. Here we choose the largest protocol 166 * version we support that is not greater than the client's 167 * requested version. 168 */ chooseProtocol(final ProtocolVersion clientVersion, final String[] enabledVersions)169 private static ProtocolVersion chooseProtocol (final ProtocolVersion clientVersion, 170 final String[] enabledVersions) 171 throws SSLException 172 { 173 ProtocolVersion version = null; 174 for (int i = 0; i < enabledVersions.length; i++) 175 { 176 ProtocolVersion v = ProtocolVersion.forName (enabledVersions[i]); 177 if (v.compareTo (clientVersion) <= 0) 178 { 179 if (version == null 180 || v.compareTo (version) > 0) 181 version = v; 182 } 183 } 184 185 // The client requested a protocol version too old, or no protocol 186 // versions are enabled. 187 if (version == null) 188 throw new SSLException ("no acceptable protocol version available"); 189 return version; 190 } 191 192 /** 193 * Choose the first cipher suite in the client's requested list that 194 * we have enabled. 195 */ chooseSuite(final CipherSuiteList clientSuites, final String[] enabledSuites, final ProtocolVersion version)196 private CipherSuite chooseSuite (final CipherSuiteList clientSuites, 197 final String[] enabledSuites, 198 final ProtocolVersion version) 199 throws SSLException 200 { 201 // Figure out which SignatureAlgorithms we can support. 202 HashSet<KeyExchangeAlgorithm> kexes = new HashSet<KeyExchangeAlgorithm>(8); 203 204 kexes.add(NONE); 205 X509ExtendedKeyManager km = engine.contextImpl.keyManager; 206 if (km != null) 207 { 208 if (km.getServerAliases(DH_DSS.name(), null).length > 0) 209 kexes.add(DH_DSS); 210 if (km.getServerAliases(DH_RSA.name(), null).length > 0) 211 kexes.add(DH_RSA); 212 if (km.getServerAliases(DHE_DSS.name(), null).length > 0) 213 kexes.add(DHE_DSS); 214 if (km.getServerAliases(DHE_RSA.name(), null).length > 0) 215 kexes.add(DHE_RSA); 216 if (km.getServerAliases(RSA.name(), null).length > 0) 217 kexes.add(RSA); 218 if (km.getServerAliases(RSA_PSK.name(), null).length > 0 219 && engine.contextImpl.pskManager != null) 220 kexes.add(RSA_PSK); 221 } 222 if (engine.contextImpl.pskManager != null) 223 { 224 kexes.add(DHE_PSK); 225 kexes.add(PSK); 226 } 227 228 if (Debug.DEBUG) 229 logger.logv(Component.SSL_HANDSHAKE, 230 "we have certs for key exchange algorithms {0}", kexes); 231 232 HashSet<CipherSuite> suites = new HashSet<CipherSuite>(); 233 for (String s : enabledSuites) 234 { 235 CipherSuite suite = CipherSuite.forName(s); 236 if (suite == null) 237 continue; 238 if (!kexes.contains(suite.keyExchangeAlgorithm())) 239 continue; 240 suites.add(suite); 241 } 242 for (CipherSuite suite : clientSuites) 243 { 244 CipherSuite resolved = suite.resolve(); 245 if (!resolved.isResolved()) 246 continue; 247 if (suites.contains(resolved)) 248 return resolved; 249 } 250 251 // We didn't find a match? 252 throw new AlertException(new Alert(Alert.Level.FATAL, 253 Alert.Description.INSUFFICIENT_SECURITY)); 254 } 255 256 /** 257 * Choose a compression method that we support, among the client's 258 * requested compression methods. We prefer ZLIB over NONE in this 259 * implementation. 260 * 261 * XXX Maybe consider implementing lzo (GNUTLS supports that). 262 */ chooseCompression(final CompressionMethodList comps)263 private static CompressionMethod chooseCompression (final CompressionMethodList comps) 264 throws SSLException 265 { 266 GetSecurityPropertyAction gspa 267 = new GetSecurityPropertyAction("jessie.enable.compression"); 268 String enable = AccessController.doPrivileged(gspa); 269 // Scan for ZLIB first. 270 if (Boolean.valueOf(enable)) 271 { 272 for (CompressionMethod cm : comps) 273 { 274 if (cm.equals (CompressionMethod.ZLIB)) 275 return CompressionMethod.ZLIB; 276 } 277 } 278 for (CompressionMethod cm : comps) 279 { 280 if (cm.equals (CompressionMethod.NULL)) 281 return CompressionMethod.NULL; 282 } 283 284 throw new SSLException ("no supported compression method"); 285 } 286 doHash()287 protected @Override boolean doHash() 288 { 289 boolean b = helloV2; 290 helloV2 = false; 291 return (state != WRITE_HELLO_REQUEST) && !b; 292 } 293 implHandleInput()294 public @Override HandshakeStatus implHandleInput() 295 throws SSLException 296 { 297 if (state == DONE) 298 return HandshakeStatus.FINISHED; 299 300 if (state.isWriteState() 301 || (outBuffer != null && outBuffer.hasRemaining())) 302 return HandshakeStatus.NEED_WRAP; 303 304 // Copy the current buffer, and prepare it for reading. 305 ByteBuffer buffer = handshakeBuffer.duplicate (); 306 buffer.flip(); 307 buffer.position(handshakeOffset); 308 Handshake handshake = new Handshake(buffer.slice(), 309 engine.session().suite, 310 engine.session().version); 311 312 if (Debug.DEBUG) 313 logger.logv(Component.SSL_HANDSHAKE, "processing in state {0}:\n{1}", 314 state, handshake); 315 316 switch (state) 317 { 318 // Client Hello. 319 // 320 // This message is sent by the client to initiate a new handshake. 321 // On a new connection, it is the first handshake message sent. 322 // 323 // The state of the handshake, after this message is processed, 324 // will have a protocol version, cipher suite, compression method, 325 // session ID, and various extensions (that the server also 326 // supports). 327 case READ_CLIENT_HELLO: 328 if (handshake.type () != CLIENT_HELLO) 329 throw new AlertException(new Alert(Alert.Level.FATAL, 330 Alert.Description.UNEXPECTED_MESSAGE)); 331 332 { 333 ClientHello hello = (ClientHello) handshake.body (); 334 engine.session().version 335 = chooseProtocol (hello.version (), 336 engine.getEnabledProtocols ()); 337 engine.session().suite = 338 chooseSuite (hello.cipherSuites (), 339 engine.getEnabledCipherSuites (), 340 engine.session().version); 341 compression = chooseCompression (hello.compressionMethods ()); 342 if (Debug.DEBUG) 343 logger.logv(Component.SSL_HANDSHAKE, 344 "chose version:{0} suite:{1} compression:{2}", 345 engine.session().version, engine.session().suite, 346 compression); 347 clientRandom = hello.random().copy(); 348 byte[] sessionId = hello.sessionId(); 349 if (hello.hasExtensions()) 350 { 351 ExtensionList exts = hello.extensions(); 352 clientHadExtensions = exts.size() > 0; 353 for (Extension e : hello.extensions()) 354 { 355 Extension.Type type = e.type(); 356 if (type == null) 357 continue; 358 switch (type) 359 { 360 case TRUNCATED_HMAC: 361 engine.session().setTruncatedMac(true); 362 break; 363 364 case MAX_FRAGMENT_LENGTH: 365 MaxFragmentLength len = (MaxFragmentLength) e.value(); 366 engine.session().maxLength = len; 367 engine.session().setApplicationBufferSize(len.maxLength()); 368 break; 369 370 case SERVER_NAME: 371 requestedNames = (ServerNameList) e.value(); 372 List<String> names 373 = new ArrayList<String>(requestedNames.size()); 374 for (ServerNameList.ServerName name : requestedNames) 375 names.add(name.name()); 376 engine.session().putValue("gnu.javax.net.ssl.RequestedServerNames", names); 377 break; 378 379 default: 380 logger.log(Level.INFO, "skipping unsupported extension {0}", e); 381 } 382 } 383 } 384 AbstractSessionContext sessions = (AbstractSessionContext) 385 engine.contextImpl.engineGetServerSessionContext(); 386 SSLSession s = sessions.getSession(sessionId); 387 if (Debug.DEBUG) 388 logger.logv(Component.SSL_HANDSHAKE, "looked up saved session {0}", s); 389 if (s != null && s.isValid() && (s instanceof SessionImpl)) 390 { 391 engine.setSession((SessionImpl) s); 392 continuedSession = true; 393 } 394 else 395 { 396 // We *may* wind up with a badly seeded PRNG, and emit the 397 // same session ID over and over (this did happen to me, 398 // so we add this sanity check just in case). 399 if (engine.session().id().equals(new Session.ID(sessionId))) 400 { 401 byte[] newId = new byte[32]; 402 engine.session().random().nextBytes(newId); 403 engine.session().setId(new Session.ID(newId)); 404 } 405 sessions.put(engine.session()); 406 } 407 state = WRITE_SERVER_HELLO; 408 } 409 break; 410 411 // Certificate. 412 // 413 // This message is sent by the client if the server had previously 414 // requested that the client authenticate itself with a certificate, 415 // and if the client has an appropriate certificate available. 416 // 417 // Processing this message will save the client's certificate, 418 // rejecting it if the certificate is not trusted, in preparation 419 // for the certificate verify message that will follow. 420 case READ_CERTIFICATE: 421 { 422 if (handshake.type() != CERTIFICATE) 423 { 424 if (engine.getNeedClientAuth()) // XXX throw better exception. 425 throw new SSLException("client auth required"); 426 state = READ_CLIENT_KEY_EXCHANGE; 427 return HandshakeStatus.NEED_UNWRAP; 428 } 429 430 Certificate cert = (Certificate) handshake.body(); 431 try 432 { 433 engine.session().setPeerVerified(false); 434 X509Certificate[] chain 435 = cert.certificates().toArray(new X509Certificate[0]); 436 if (chain.length == 0) 437 throw new CertificateException("no certificates in chain"); 438 certVerifier = new CertVerifier(false, chain); 439 tasks.add(certVerifier); 440 engine.session().setPeerCertificates(chain); 441 clientCert = chain[0]; 442 // Delay setting 'peerVerified' until CertificateVerify. 443 } 444 catch (CertificateException ce) 445 { 446 if (engine.getNeedClientAuth()) 447 { 448 SSLPeerUnverifiedException x 449 = new SSLPeerUnverifiedException("client certificates could not be verified"); 450 x.initCause(ce); 451 throw x; 452 } 453 } 454 catch (NoSuchAlgorithmException nsae) 455 { 456 throw new SSLException(nsae); 457 } 458 state = READ_CLIENT_KEY_EXCHANGE; 459 } 460 break; 461 462 // Client Key Exchange. 463 // 464 // The client's key exchange. This message is sent either following 465 // the certificate message, or if no certificate is available or 466 // requested, following the server's hello done message. 467 // 468 // After receipt of this message, the session keys for this 469 // session will have been created. 470 case READ_CLIENT_KEY_EXCHANGE: 471 { 472 if (handshake.type() != CLIENT_KEY_EXCHANGE) 473 throw new SSLException("expecting client key exchange"); 474 ClientKeyExchange kex = (ClientKeyExchange) handshake.body(); 475 476 KeyExchangeAlgorithm alg = engine.session().suite.keyExchangeAlgorithm(); 477 switch (alg) 478 { 479 case DHE_DSS: 480 case DHE_RSA: 481 case DH_anon: 482 { 483 ClientDiffieHellmanPublic pub = (ClientDiffieHellmanPublic) 484 kex.exchangeKeys(); 485 DHPublicKey myKey = (DHPublicKey) dhPair.getPublic(); 486 DHPublicKey clientKey = 487 new GnuDHPublicKey(null, myKey.getParams().getP(), 488 myKey.getParams().getG(), 489 pub.publicValue()); 490 keyExchangeTask = new DHPhase(clientKey); 491 tasks.add(keyExchangeTask); 492 } 493 break; 494 495 case RSA: 496 { 497 EncryptedPreMasterSecret secret = (EncryptedPreMasterSecret) 498 kex.exchangeKeys(); 499 keyExchangeTask = new RSAKeyExchange(secret.encryptedSecret()); 500 tasks.add(keyExchangeTask); 501 } 502 break; 503 504 case PSK: 505 { 506 ClientPSKParameters params = (ClientPSKParameters) 507 kex.exchangeKeys(); 508 generatePSKSecret(params.identity(), null, false); 509 } 510 break; 511 512 case DHE_PSK: 513 { 514 ClientDHE_PSKParameters params = (ClientDHE_PSKParameters) 515 kex.exchangeKeys(); 516 DHPublicKey serverKey = (DHPublicKey) dhPair.getPublic(); 517 DHPublicKey clientKey = 518 new GnuDHPublicKey(null, serverKey.getParams().getP(), 519 serverKey.getParams().getG(), 520 params.params().publicValue()); 521 SecretKey psk = null; 522 try 523 { 524 psk = engine.contextImpl.pskManager.getKey(params.identity()); 525 } 526 catch (KeyManagementException kme) 527 { 528 } 529 keyExchangeTask = new DHE_PSKGen(clientKey, psk, false); 530 tasks.add(keyExchangeTask); 531 } 532 break; 533 534 case RSA_PSK: 535 { 536 ClientRSA_PSKParameters params = (ClientRSA_PSKParameters) 537 kex.exchangeKeys(); 538 SecretKey psk = null; 539 try 540 { 541 psk = engine.contextImpl.pskManager.getKey(params.identity()); 542 } 543 catch (KeyManagementException kme) 544 { 545 } 546 if (psk == null) 547 { 548 byte[] fakeKey = new byte[16]; 549 engine.session().random().nextBytes(fakeKey); 550 psk = new SecretKeySpec(fakeKey, "DHE_PSK"); 551 } 552 keyExchangeTask = 553 new RSA_PSKExchange(params.secret().encryptedSecret(), psk); 554 tasks.add(keyExchangeTask); 555 } 556 break; 557 558 case NONE: 559 { 560 Inflater inflater = null; 561 Deflater deflater = null; 562 if (compression == CompressionMethod.ZLIB) 563 { 564 inflater = new Inflater(); 565 deflater = new Deflater(); 566 } 567 inParams = new InputSecurityParameters(null, null, inflater, 568 engine.session(), 569 engine.session().suite); 570 outParams = new OutputSecurityParameters(null, null, deflater, 571 engine.session(), 572 engine.session().suite); 573 engine.session().privateData.masterSecret = new byte[0]; 574 } 575 break; 576 } 577 // XXX SRP 578 579 if (clientCert != null) 580 state = READ_CERTIFICATE_VERIFY; 581 else 582 state = READ_FINISHED; 583 } 584 break; 585 586 // Certificate Verify. 587 // 588 // This message is sent following the client key exchange message, 589 // but only when the client included its certificate in a previous 590 // message. 591 // 592 // After receipt of this message, the client's certificate (and, 593 // to a degree, the client's identity) will have been verified. 594 case READ_CERTIFICATE_VERIFY: 595 { 596 if (handshake.type() != CERTIFICATE_VERIFY) 597 throw new SSLException("expecting certificate verify message"); 598 599 CertificateVerify verify = (CertificateVerify) handshake.body(); 600 try 601 { 602 verifyClient(verify.signature()); 603 if (certVerifier != null && certVerifier.verified()) 604 engine.session().setPeerVerified(true); 605 } 606 catch (SignatureException se) 607 { 608 if (engine.getNeedClientAuth()) 609 throw new SSLException("client auth failed", se); 610 } 611 if (continuedSession) 612 { 613 engine.changeCipherSpec(); 614 state = WRITE_FINISHED; 615 } 616 else 617 state = READ_FINISHED; 618 } 619 break; 620 621 // Finished. 622 // 623 // This message is sent immediately following the change cipher 624 // spec message (which is sent outside of the handshake layer). 625 // After receipt of this message, the session keys for the client 626 // side will have been verified (this is the first message the 627 // client sends encrypted and authenticated with the newly 628 // negotiated keys). 629 // 630 // In the case of a continued session, the client sends its 631 // finished message first. Otherwise, the server will send its 632 // finished message first. 633 case READ_FINISHED: 634 { 635 if (handshake.type() != FINISHED) 636 throw new AlertException(new Alert(Alert.Level.FATAL, 637 Description.UNEXPECTED_MESSAGE)); 638 639 Finished clientFinished = (Finished) handshake.body(); 640 641 MessageDigest md5copy = null; 642 MessageDigest shacopy = null; 643 try 644 { 645 md5copy = (MessageDigest) md5.clone(); 646 shacopy = (MessageDigest) sha.clone(); 647 } 648 catch (CloneNotSupportedException cnse) 649 { 650 // We're improperly configured to use a non-cloneable 651 // md5/sha-1, OR there's a runtime bug. 652 throw new SSLException(cnse); 653 } 654 Finished serverFinished = 655 new Finished(generateFinished(md5copy, shacopy, 656 true, engine.session()), 657 engine.session().version); 658 659 if (Debug.DEBUG) 660 logger.log(Component.SSL_HANDSHAKE, "server finished: {0}", 661 serverFinished); 662 663 if (engine.session().version == ProtocolVersion.SSL_3) 664 { 665 if (!Arrays.equals(clientFinished.md5Hash(), 666 serverFinished.md5Hash()) 667 || !Arrays.equals(clientFinished.shaHash(), 668 serverFinished.shaHash())) 669 { 670 engine.session().invalidate(); 671 throw new SSLException("session verify failed"); 672 } 673 } 674 else 675 { 676 if (!Arrays.equals(clientFinished.verifyData(), 677 serverFinished.verifyData())) 678 { 679 engine.session().invalidate(); 680 throw new SSLException("session verify failed"); 681 } 682 } 683 684 if (continuedSession) 685 state = DONE; 686 else 687 { 688 engine.changeCipherSpec(); 689 state = WRITE_FINISHED; 690 } 691 } 692 break; 693 } 694 695 handshakeOffset += handshake.length() + 4; 696 697 if (!tasks.isEmpty()) 698 return HandshakeStatus.NEED_TASK; 699 if (state.isReadState()) 700 return HandshakeStatus.NEED_UNWRAP; 701 if (state.isWriteState()) 702 return HandshakeStatus.NEED_WRAP; 703 704 return HandshakeStatus.FINISHED; 705 } 706 implHandleOutput(ByteBuffer fragment)707 public @Override HandshakeStatus implHandleOutput (ByteBuffer fragment) 708 throws SSLException 709 { 710 if (Debug.DEBUG) 711 logger.logv(Component.SSL_HANDSHAKE, 712 "handle output state: {0}; output fragment: {1}", 713 state, fragment); 714 715 // Drain the output buffer, if it needs it. 716 if (outBuffer != null && outBuffer.hasRemaining()) 717 { 718 int l = Math.min(fragment.remaining(), outBuffer.remaining()); 719 fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l)); 720 outBuffer.position(outBuffer.position() + l); 721 } 722 723 if (!fragment.hasRemaining()) 724 { 725 if (state.isWriteState() || outBuffer.hasRemaining()) 726 return HandshakeStatus.NEED_WRAP; 727 else 728 return HandshakeStatus.NEED_UNWRAP; 729 } 730 731 // XXX what we need to do here is generate a "stream" of handshake 732 // messages, and insert them into fragment amounts that we have available. 733 // A handshake message can span multiple records, and we can put 734 // multiple records into a single record. 735 // 736 // So, we can have one of two states: 737 // 738 // 1) We have enough space in the record we are creating to push out 739 // everything we need to on this round. This is easy; we just 740 // repeatedly fill in these messages in the buffer, so we get something 741 // that looks like this: 742 // ________________________________ 743 // records: |________________________________| 744 // handshakes: |______|__|__________| 745 // 746 // 2) We can put part of one handshake message in the current record, 747 // but we must put the rest of it in the following record, or possibly 748 // more than one following record. So here, we'd see this: 749 // 750 // ________________________ 751 // records: |_______|_______|________| 752 // handshakes: |____|_______|_________| 753 // 754 // We *could* make this a lot easier by just only ever emitting one 755 // record per call, but then we would waste potentially a lot of space 756 // and waste a lot of TCP packets by doing it the simple way. What 757 // we desire here is that we *maximize* our usage of the resources 758 // given to us, and to use as much space in the present fragment as 759 // we can. 760 // 761 // Note that we pretty much have to support this, anyway, because SSL 762 // provides no guarantees that the record size is large enough to 763 // admit *even one* handshake message. Also, callers could call on us 764 // with a short buffer, even though they aren't supposed to. 765 // 766 // This is somewhat complicated by the fact that we don't know, a priori, 767 // how large a handshake message will be until we've built it, and our 768 // design builds the message around the byte buffer. 769 // 770 // Some ways to handle this: 771 // 772 // 1. Write our outgoing handshake messages to a private buffer, 773 // big enough per message (and, if we run out of space, resize that 774 // buffer) and push (possibly part of) this buffer out to the 775 // outgoing buffer. This isn't that great because we'd need to 776 // store and copy things unnecessarily. 777 // 778 // 2. Build outgoing handshake objects 'virtually', that is, store them 779 // as collections of objects, then compute the length, and then write 780 // them to a buffer, instead of making the objects views on 781 // ByteBuffers for both input and output. This would complicate the 782 // protocol objects a bit (although, it would amount to doing 783 // separation between client objects and server objects, which is 784 // pretty OK), and we still need to figure out how exactly to chunk 785 // those objects across record boundaries. 786 // 787 // 3. Try to build these objects on the buffer we're given, but detect 788 // when we run out of space in the output buffer, and split the 789 // overflow message. This sounds like the best, but also probably 790 // the hardest to code. 791 output_loop: 792 while (fragment.remaining() >= 4 && state.isWriteState()) 793 { 794 switch (state) 795 { 796 // Hello Request. 797 // 798 // This message is sent by the server to initiate a new 799 // handshake, to establish new session keys. 800 case WRITE_HELLO_REQUEST: 801 { 802 Handshake handshake = new Handshake(fragment); 803 handshake.setType(Handshake.Type.HELLO_REQUEST); 804 handshake.setLength(0); 805 fragment.position(fragment.position() + 4); 806 if (Debug.DEBUG) 807 logger.log(Component.SSL_HANDSHAKE, "{0}", handshake); 808 state = READ_CLIENT_HELLO; 809 } 810 break output_loop; // XXX temporary 811 812 // Server Hello. 813 // 814 // This message is sent immediately following the client hello. 815 // It informs the client of the cipher suite, compression method, 816 // session ID (which may have been a continued session), and any 817 // supported extensions. 818 case WRITE_SERVER_HELLO: 819 { 820 ServerHelloBuilder hello = new ServerHelloBuilder(); 821 hello.setVersion(engine.session().version); 822 Random r = hello.random(); 823 r.setGmtUnixTime(Util.unixTime()); 824 byte[] nonce = new byte[28]; 825 engine.session().random().nextBytes(nonce); 826 r.setRandomBytes(nonce); 827 serverRandom = r.copy(); 828 hello.setSessionId(engine.session().getId()); 829 hello.setCipherSuite(engine.session().suite); 830 hello.setCompressionMethod(compression); 831 if (clientHadExtensions) 832 { 833 // XXX figure this out. 834 } 835 else // Don't send any extensions. 836 hello.setDisableExtensions(true); 837 838 if (Debug.DEBUG) 839 logger.log(Component.SSL_HANDSHAKE, "{0}", hello); 840 841 int typeLen = ((Handshake.Type.SERVER_HELLO.getValue() << 24) 842 | (hello.length() & 0xFFFFFF)); 843 fragment.putInt(typeLen); 844 845 outBuffer = hello.buffer(); 846 int l = Math.min(fragment.remaining(), outBuffer.remaining()); 847 fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l)); 848 outBuffer.position(outBuffer.position() + l); 849 850 CipherSuite cs = engine.session().suite; 851 KeyExchangeAlgorithm kex = cs.keyExchangeAlgorithm(); 852 if (continuedSession) 853 { 854 byte[][] keys = generateKeys(clientRandom, serverRandom, 855 engine.session()); 856 setupSecurityParameters(keys, false, engine, compression); 857 engine.changeCipherSpec(); 858 state = WRITE_FINISHED; 859 } 860 else if (kex == DHE_DSS || kex == DHE_RSA || kex == RSA 861 || kex == RSA_PSK) 862 { 863 certLoader = new CertLoader(); 864 tasks.add(certLoader); 865 state = WRITE_CERTIFICATE; 866 if (kex == DHE_DSS || kex == DHE_RSA) 867 { 868 genDH = new GenDH(); 869 tasks.add(genDH); 870 } 871 break output_loop; 872 } 873 else if (kex == PSK) 874 { 875 state = WRITE_SERVER_KEY_EXCHANGE; 876 } 877 else if (kex == DHE_PSK || kex == DH_anon) 878 { 879 genDH = new GenDH(); 880 tasks.add(genDH); 881 state = WRITE_SERVER_KEY_EXCHANGE; 882 break output_loop; 883 } 884 else if (engine.getWantClientAuth() || engine.getNeedClientAuth()) 885 { 886 state = WRITE_CERTIFICATE_REQUEST; 887 } 888 else 889 state = WRITE_SERVER_HELLO_DONE; 890 } 891 break; 892 893 // Certificate. 894 // 895 // This message is sent immediately following the server hello, 896 // IF the cipher suite chosen requires that the server identify 897 // itself (usually, servers must authenticate). 898 case WRITE_CERTIFICATE: 899 { 900 // We must have scheduled a certificate loader to run. 901 assert(certLoader != null); 902 assert(certLoader.hasRun()); 903 if (certLoader.thrown() != null) 904 throw new AlertException(new Alert(Alert.Level.FATAL, 905 Alert.Description.HANDSHAKE_FAILURE), 906 certLoader.thrown()); 907 java.security.cert.Certificate[] chain 908 = engine.session().getLocalCertificates(); 909 CertificateBuilder cert = new CertificateBuilder(CertificateType.X509); 910 try 911 { 912 cert.setCertificates(Arrays.asList(chain)); 913 } 914 catch (CertificateException ce) 915 { 916 throw new SSLException(ce); 917 } 918 919 if (Debug.DEBUG) 920 { 921 logger.logv(Component.SSL_HANDSHAKE, "my cert:\n{0}", localCert); 922 logger.logv(Component.SSL_HANDSHAKE, "{0}", cert); 923 } 924 925 int typeLen = ((CERTIFICATE.getValue() << 24) 926 | (cert.length() & 0xFFFFFF)); 927 fragment.putInt(typeLen); 928 929 outBuffer = cert.buffer(); 930 final int l = Math.min(fragment.remaining(), outBuffer.remaining()); 931 fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l)); 932 outBuffer.position(outBuffer.position() + l); 933 934 CipherSuite s = engine.session().suite; 935 KeyExchangeAlgorithm kexalg = s.keyExchangeAlgorithm(); 936 if (kexalg == DHE_DSS || kexalg == DHE_RSA) 937 { 938 genDH = new GenDH(); 939 tasks.add(genDH); 940 state = WRITE_SERVER_KEY_EXCHANGE; 941 break output_loop; 942 } 943 else if (kexalg == RSA_PSK) 944 state = WRITE_SERVER_KEY_EXCHANGE; 945 else if (engine.getWantClientAuth() || engine.getNeedClientAuth()) 946 { 947 state = WRITE_CERTIFICATE_REQUEST; 948 } 949 else 950 state = WRITE_SERVER_HELLO_DONE; 951 } 952 break output_loop; // XXX temporary 953 954 // Server key exchange. 955 // 956 // This message is sent, following the certificate if sent, 957 // otherwise following the server hello, IF the chosen cipher 958 // suite requires that the server send explicit key exchange 959 // parameters (that is, if the key exchange parameters are not 960 // implicit in the server's certificate). 961 case WRITE_SERVER_KEY_EXCHANGE: 962 { 963 KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm(); 964 965 ByteBuffer paramBuffer = null; 966 ByteBuffer sigBuffer = null; 967 if (kex == DHE_DSS || kex == DHE_RSA || kex == DH_anon 968 || kex == DHE_PSK) 969 { 970 assert(genDH != null); 971 assert(genDH.hasRun()); 972 if (genDH.thrown() != null) 973 throw new AlertException(new Alert(Alert.Level.FATAL, 974 Alert.Description.HANDSHAKE_FAILURE), 975 genDH.thrown()); 976 assert(dhPair != null); 977 initDiffieHellman((DHPrivateKey) dhPair.getPrivate(), 978 engine.session().random()); 979 paramBuffer = genDH.paramsBuffer; 980 sigBuffer = genDH.sigBuffer; 981 982 if (kex == DHE_PSK) 983 { 984 String identityHint 985 = engine.contextImpl.pskManager.chooseIdentityHint(); 986 ServerDHE_PSKParameters psk = 987 new ServerDHE_PSKParameters(identityHint, paramBuffer); 988 paramBuffer = psk.buffer(); 989 } 990 } 991 if (kex == RSA_PSK) 992 { 993 String idHint = engine.contextImpl.pskManager.chooseIdentityHint(); 994 if (idHint != null) 995 { 996 ServerRSA_PSKParameters params 997 = new ServerRSA_PSKParameters(idHint); 998 paramBuffer = params.buffer(); 999 } 1000 } 1001 if (kex == PSK) 1002 { 1003 String idHint = engine.contextImpl.pskManager.chooseIdentityHint(); 1004 if (idHint != null) 1005 { 1006 ServerPSKParameters params 1007 = new ServerPSKParameters(idHint); 1008 paramBuffer = params.buffer(); 1009 } 1010 } 1011 // XXX handle SRP 1012 1013 if (paramBuffer != null) 1014 { 1015 ServerKeyExchangeBuilder ske 1016 = new ServerKeyExchangeBuilder(engine.session().suite); 1017 ske.setParams(paramBuffer); 1018 if (sigBuffer != null) 1019 ske.setSignature(sigBuffer); 1020 1021 if (Debug.DEBUG) 1022 logger.log(Component.SSL_HANDSHAKE, "{0}", ske); 1023 1024 outBuffer = ske.buffer(); 1025 int l = Math.min(fragment.remaining(), outBuffer.remaining()); 1026 fragment.putInt((SERVER_KEY_EXCHANGE.getValue() << 24) 1027 | (ske.length() & 0xFFFFFF)); 1028 fragment.put((ByteBuffer) outBuffer.duplicate().limit 1029 (outBuffer.position() + l)); 1030 outBuffer.position(outBuffer.position() + l); 1031 } 1032 1033 if (engine.getWantClientAuth() || engine.getNeedClientAuth()) 1034 state = WRITE_CERTIFICATE_REQUEST; 1035 else 1036 state = WRITE_SERVER_HELLO_DONE; 1037 } 1038 break; 1039 1040 // Certificate Request. 1041 // 1042 // This message is sent when the server desires or requires 1043 // client authentication with a certificate; if it is sent, it 1044 // will be sent just after the Certificate or Server Key 1045 // Exchange messages, whichever is sent. If neither of the 1046 // above are sent, it will be the message that follows the 1047 // server hello. 1048 case WRITE_CERTIFICATE_REQUEST: 1049 { 1050 CertificateRequestBuilder req = new CertificateRequestBuilder(); 1051 1052 List<ClientCertificateType> types 1053 = new ArrayList<ClientCertificateType>(4); 1054 types.add(ClientCertificateType.RSA_SIGN); 1055 types.add(ClientCertificateType.RSA_FIXED_DH); 1056 types.add(ClientCertificateType.DSS_SIGN); 1057 types.add(ClientCertificateType.DSS_FIXED_DH); 1058 req.setTypes(types); 1059 1060 X509Certificate[] anchors 1061 = engine.contextImpl.trustManager.getAcceptedIssuers(); 1062 List<X500Principal> issuers 1063 = new ArrayList<X500Principal>(anchors.length); 1064 for (X509Certificate cert : anchors) 1065 issuers.add(cert.getIssuerX500Principal()); 1066 req.setAuthorities(issuers); 1067 1068 if (Debug.DEBUG) 1069 logger.log(Component.SSL_HANDSHAKE, "{0}", req); 1070 1071 fragment.putInt((CERTIFICATE_REQUEST.getValue() << 24) 1072 | (req.length() & 0xFFFFFF)); 1073 1074 outBuffer = req.buffer(); 1075 int l = Math.min(outBuffer.remaining(), fragment.remaining()); 1076 fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l)); 1077 outBuffer.position(outBuffer.position() + l); 1078 1079 state = WRITE_SERVER_HELLO_DONE; 1080 } 1081 break; 1082 1083 // Server Hello Done. 1084 // 1085 // This message is always sent by the server, to terminate its 1086 // side of the handshake. Since the server's handshake message 1087 // may comprise multiple, optional messages, this sentinel 1088 // message lets the client know when the server's message stream 1089 // is complete. 1090 case WRITE_SERVER_HELLO_DONE: 1091 { 1092 // ServerHelloDone is zero-length; just put in the type 1093 // field. 1094 fragment.putInt(SERVER_HELLO_DONE.getValue() << 24); 1095 if (Debug.DEBUG) 1096 logger.logv(Component.SSL_HANDSHAKE, "writing ServerHelloDone"); 1097 state = READ_CERTIFICATE; 1098 } 1099 break output_loop; // XXX temporary 1100 1101 // Finished. 1102 // 1103 // This is always sent by the server to verify the keys that the 1104 // server will use to encrypt and authenticate. In a full 1105 // handshake, this message will be sent after the client's 1106 // finished message; in an abbreviated handshake (with a continued 1107 // session) the server sends its finished message first. 1108 // 1109 // This message follows the change cipher spec message, which is 1110 // sent out-of-band in a different SSL content-type. 1111 // 1112 // This is the first message that the server will send encrypted 1113 // and authenticated with the newly negotiated session keys. 1114 case WRITE_FINISHED: 1115 { 1116 MessageDigest md5copy = null; 1117 MessageDigest shacopy = null; 1118 try 1119 { 1120 md5copy = (MessageDigest) md5.clone(); 1121 shacopy = (MessageDigest) sha.clone(); 1122 } 1123 catch (CloneNotSupportedException cnse) 1124 { 1125 // We're improperly configured to use a non-cloneable 1126 // md5/sha-1, OR there's a runtime bug. 1127 throw new SSLException(cnse); 1128 } 1129 outBuffer 1130 = generateFinished(md5copy, shacopy, false, 1131 engine.session()); 1132 1133 fragment.putInt((FINISHED.getValue() << 24) 1134 | outBuffer.remaining() & 0xFFFFFF); 1135 1136 int l = Math.min(outBuffer.remaining(), fragment.remaining()); 1137 fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l)); 1138 outBuffer.position(outBuffer.position() + l); 1139 1140 if (continuedSession) 1141 state = READ_FINISHED; 1142 else 1143 state = DONE; 1144 } 1145 break; 1146 } 1147 } 1148 if (!tasks.isEmpty()) 1149 return HandshakeStatus.NEED_TASK; 1150 if (state.isWriteState() || outBuffer.hasRemaining()) 1151 return HandshakeStatus.NEED_WRAP; 1152 if (state.isReadState()) 1153 return HandshakeStatus.NEED_UNWRAP; 1154 1155 return HandshakeStatus.FINISHED; 1156 } 1157 status()1158 @Override HandshakeStatus status() 1159 { 1160 if (!tasks.isEmpty()) 1161 return HandshakeStatus.NEED_TASK; 1162 if (state.isReadState()) 1163 return HandshakeStatus.NEED_UNWRAP; 1164 if (state.isWriteState()) 1165 return HandshakeStatus.NEED_WRAP; 1166 1167 return HandshakeStatus.FINISHED; 1168 } 1169 checkKeyExchange()1170 @Override void checkKeyExchange() throws SSLException 1171 { 1172 if (continuedSession) // No key exchange needed. 1173 return; 1174 KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm(); 1175 if (kex == NONE || kex == PSK || kex == RSA_PSK) // Don't need one. 1176 return; 1177 if (keyExchangeTask == null) // An error if we never created one. 1178 throw new AlertException(new Alert(Alert.Level.FATAL, 1179 Alert.Description.INTERNAL_ERROR)); 1180 if (!keyExchangeTask.hasRun()) // An error if the caller never ran it. 1181 throw new AlertException(new Alert(Alert.Level.FATAL, 1182 Alert.Description.INTERNAL_ERROR)); 1183 if (keyExchangeTask.thrown() != null) // An error was thrown. 1184 throw new AlertException(new Alert(Alert.Level.FATAL, 1185 Alert.Description.HANDSHAKE_FAILURE), 1186 keyExchangeTask.thrown()); 1187 } 1188 handleV2Hello(ByteBuffer hello)1189 @Override void handleV2Hello(ByteBuffer hello) 1190 { 1191 int len = hello.getShort(0) & 0x7FFF; 1192 md5.update((ByteBuffer) hello.duplicate().position(2).limit(len+2)); 1193 sha.update((ByteBuffer) hello.duplicate().position(2).limit(len+2)); 1194 helloV2 = true; 1195 } 1196 signParams(ByteBuffer serverParams)1197 private ByteBuffer signParams(ByteBuffer serverParams) 1198 throws NoSuchAlgorithmException, InvalidKeyException, SignatureException 1199 { 1200 SignatureAlgorithm alg = engine.session().suite.signatureAlgorithm(); 1201 java.security.Signature sig 1202 = java.security.Signature.getInstance(alg.algorithm()); 1203 PrivateKey key = engine.contextImpl.keyManager.getPrivateKey(keyAlias); 1204 if (Debug.DEBUG_KEY_EXCHANGE) 1205 logger.logv(Component.SSL_HANDSHAKE, "server key: {0}", key); 1206 sig.initSign(key); 1207 sig.update(clientRandom.buffer()); 1208 sig.update(serverRandom.buffer()); 1209 sig.update(serverParams); 1210 byte[] sigVal = sig.sign(); 1211 Signature signature = new Signature(sigVal, engine.session().suite.signatureAlgorithm()); 1212 return signature.buffer(); 1213 } 1214 verifyClient(byte[] sigValue)1215 private void verifyClient(byte[] sigValue) throws SSLException, SignatureException 1216 { 1217 MessageDigest md5copy = null; 1218 MessageDigest shacopy = null; 1219 try 1220 { 1221 md5copy = (MessageDigest) md5.clone(); 1222 shacopy = (MessageDigest) sha.clone(); 1223 } 1224 catch (CloneNotSupportedException cnse) 1225 { 1226 // Mis-configured with non-cloneable digests. 1227 throw new SSLException(cnse); 1228 } 1229 byte[] toSign = null; 1230 if (engine.session().version == ProtocolVersion.SSL_3) 1231 toSign = genV3CertificateVerify(md5copy, shacopy, engine.session()); 1232 else 1233 { 1234 if (engine.session().suite.signatureAlgorithm() == SignatureAlgorithm.RSA) 1235 toSign = Util.concat(md5copy.digest(), shacopy.digest()); 1236 else 1237 toSign = shacopy.digest(); 1238 } 1239 1240 try 1241 { 1242 java.security.Signature sig = java.security.Signature.getInstance(engine.session().suite.signatureAlgorithm().toString()); 1243 sig.initVerify(clientCert); 1244 sig.update(toSign); 1245 sig.verify(sigValue); 1246 } 1247 catch (InvalidKeyException ike) 1248 { 1249 throw new SSLException(ike); 1250 } 1251 catch (NoSuchAlgorithmException nsae) 1252 { 1253 throw new SSLException(nsae); 1254 } 1255 } 1256 1257 // Delegated tasks. 1258 1259 class CertLoader extends DelegatedTask 1260 { CertLoader()1261 CertLoader() 1262 { 1263 } 1264 implRun()1265 public void implRun() throws SSLException 1266 { 1267 KeyExchangeAlgorithm kexalg = engine.session().suite.keyExchangeAlgorithm(); 1268 X509ExtendedKeyManager km = engine.contextImpl.keyManager; 1269 Principal[] issuers = null; // XXX use TrustedAuthorities extension. 1270 keyAlias = km.chooseEngineServerAlias(kexalg.name(), issuers, engine); 1271 if (keyAlias == null) 1272 throw new SSLException("no certificates available"); 1273 X509Certificate[] chain = km.getCertificateChain(keyAlias); 1274 engine.session().setLocalCertificates(chain); 1275 localCert = chain[0]; 1276 serverKey = km.getPrivateKey(keyAlias); 1277 if (kexalg == DH_DSS || kexalg == DH_RSA) 1278 dhPair = new KeyPair(localCert.getPublicKey(), 1279 km.getPrivateKey(keyAlias)); 1280 } 1281 } 1282 1283 /** 1284 * Delegated task for generating Diffie-Hellman parameters. 1285 */ 1286 private class GenDH extends DelegatedTask 1287 { 1288 ByteBuffer paramsBuffer; 1289 ByteBuffer sigBuffer; 1290 implRun()1291 protected void implRun() 1292 throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, 1293 InvalidKeyException, SignatureException 1294 { 1295 KeyPairGenerator dhGen = KeyPairGenerator.getInstance("DH"); 1296 DHParameterSpec dhparams = DiffieHellman.getParams().getParams(); 1297 dhGen.initialize(dhparams, engine.session().random()); 1298 dhPair = dhGen.generateKeyPair(); 1299 DHPublicKey pub = (DHPublicKey) dhPair.getPublic(); 1300 1301 // Generate the parameters message. 1302 ServerDHParams params = new ServerDHParams(pub.getParams().getP(), 1303 pub.getParams().getG(), 1304 pub.getY()); 1305 paramsBuffer = params.buffer(); 1306 1307 // Sign the parameters, if needed. 1308 if (engine.session().suite.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS) 1309 { 1310 sigBuffer = signParams(paramsBuffer); 1311 paramsBuffer.rewind(); 1312 } 1313 if (Debug.DEBUG_KEY_EXCHANGE) 1314 logger.logv(Component.SSL_KEY_EXCHANGE, 1315 "Diffie-Hellman public:{0} private:{1}", 1316 dhPair.getPublic(), dhPair.getPrivate()); 1317 } 1318 } 1319 1320 class RSAKeyExchange extends DelegatedTask 1321 { 1322 private final byte[] encryptedPreMasterSecret; 1323 RSAKeyExchange(byte[] encryptedPreMasterSecret)1324 RSAKeyExchange(byte[] encryptedPreMasterSecret) 1325 { 1326 this.encryptedPreMasterSecret = encryptedPreMasterSecret; 1327 } 1328 implRun()1329 public void implRun() 1330 throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, 1331 NoSuchAlgorithmException, NoSuchPaddingException, SSLException 1332 { 1333 Cipher rsa = Cipher.getInstance("RSA"); 1334 rsa.init(Cipher.DECRYPT_MODE, serverKey); 1335 rsa.init(Cipher.DECRYPT_MODE, localCert); 1336 preMasterSecret = rsa.doFinal(encryptedPreMasterSecret); 1337 generateMasterSecret(clientRandom, serverRandom, engine.session()); 1338 byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session()); 1339 setupSecurityParameters(keys, false, engine, compression); 1340 } 1341 } 1342 1343 class RSA_PSKExchange extends DelegatedTask 1344 { 1345 private final byte[] encryptedPreMasterSecret; 1346 private final SecretKey psKey; 1347 RSA_PSKExchange(byte[] encryptedPreMasterSecret, SecretKey psKey)1348 RSA_PSKExchange(byte[] encryptedPreMasterSecret, SecretKey psKey) 1349 { 1350 this.encryptedPreMasterSecret = encryptedPreMasterSecret; 1351 this.psKey = psKey; 1352 } 1353 implRun()1354 public @Override void implRun() 1355 throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, 1356 NoSuchAlgorithmException, NoSuchPaddingException, SSLException 1357 { 1358 Cipher rsa = Cipher.getInstance("RSA"); 1359 rsa.init(Cipher.DECRYPT_MODE, serverKey); 1360 rsa.init(Cipher.DECRYPT_MODE, localCert); 1361 byte[] rsaSecret = rsa.doFinal(encryptedPreMasterSecret); 1362 byte[] psSecret = psKey.getEncoded(); 1363 preMasterSecret = new byte[rsaSecret.length + psSecret.length + 4]; 1364 preMasterSecret[0] = (byte) (rsaSecret.length >>> 8); 1365 preMasterSecret[1] = (byte) rsaSecret.length; 1366 System.arraycopy(rsaSecret, 0, preMasterSecret, 2, rsaSecret.length); 1367 preMasterSecret[rsaSecret.length + 2] = (byte) (psSecret.length >>> 8); 1368 preMasterSecret[rsaSecret.length + 3] = (byte) psSecret.length; 1369 System.arraycopy(psSecret, 0, preMasterSecret, rsaSecret.length+4, 1370 psSecret.length); 1371 1372 generateMasterSecret(clientRandom, serverRandom, engine.session()); 1373 byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session()); 1374 setupSecurityParameters(keys, false, engine, compression); 1375 } 1376 } 1377 } 1378