OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [net/] [ssl/] [provider/] [ServerHandshake.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* 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
 
116
    private State(final boolean isWriteState, final boolean isReadState)
117
    {
118
      this.isWriteState = isWriteState;
119
      this.isReadState = isReadState;
120
    }
121
 
122
    boolean isReadState()
123
    {
124
      return isReadState;
125
    }
126
 
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
 
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
   */
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
   */
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
   */
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
 
287
  protected @Override boolean doHash()
288
  {
289
    boolean b = helloV2;
290
    helloV2 = false;
291
    return (state != WRITE_HELLO_REQUEST) && !b;
292
  }
293
 
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
 
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
 
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
 
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
 
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
 
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
 
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
  {
1261
    CertLoader()
1262
    {
1263
    }
1264
 
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
 
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
 
1324
    RSAKeyExchange(byte[] encryptedPreMasterSecret)
1325
    {
1326
      this.encryptedPreMasterSecret = encryptedPreMasterSecret;
1327
    }
1328
 
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
 
1348
    RSA_PSKExchange(byte[] encryptedPreMasterSecret, SecretKey psKey)
1349
    {
1350
      this.encryptedPreMasterSecret = encryptedPreMasterSecret;
1351
      this.psKey = psKey;
1352
    }
1353
 
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.