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/] [SSLEngineImpl.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* SSLEngineImpl.java -- implementation of SSLEngine.
2
   Copyright (C) 2006  Free Software Foundation, Inc.
3
 
4
This file is a part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or (at
9
your option) any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19
USA
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version.  */
37
 
38
 
39
package gnu.javax.net.ssl.provider;
40
 
41
import gnu.classpath.debug.Component;
42
import gnu.classpath.debug.SystemLogger;
43
 
44
import gnu.java.security.util.ByteBufferOutputStream;
45
import gnu.javax.net.ssl.Session;
46
import gnu.javax.net.ssl.SSLRecordHandler;
47
 
48
import java.nio.BufferOverflowException;
49
import java.nio.ByteBuffer;
50
import java.nio.ByteOrder;
51
 
52
import java.security.NoSuchAlgorithmException;
53
import java.util.ArrayList;
54
import java.util.List;
55
import java.util.zip.DataFormatException;
56
 
57
import javax.crypto.IllegalBlockSizeException;
58
import javax.crypto.ShortBufferException;
59
import javax.net.ssl.SSLEngine;
60
import javax.net.ssl.SSLEngineResult;
61
import javax.net.ssl.SSLException;
62
import javax.net.ssl.SSLSession;
63
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
64
import javax.net.ssl.SSLEngineResult.Status;
65
 
66
public final class SSLEngineImpl extends SSLEngine
67
{
68
  final SSLContextImpl contextImpl;
69
  private SSLRecordHandler[] handlers;
70
  private static final SystemLogger logger = SystemLogger.SYSTEM;
71
  private SessionImpl session;
72
  private InputSecurityParameters insec;
73
  private OutputSecurityParameters outsec;
74
  private boolean inClosed;
75
  private boolean outClosed;
76
  private boolean createSessions;
77
  private boolean needClientAuth;
78
  private boolean wantClientAuth;
79
  private boolean initialHandshakeDone;
80
  private AbstractHandshake handshake;
81
  private Alert lastAlert;
82
  private SSLEngineResult.HandshakeStatus handshakeStatus;
83
  private boolean changeCipherSpec;
84
 
85
  private String[] enabledSuites;
86
  private String[] enabledProtocols;
87
 
88
  /**
89
   * We can receive any message chunked across multiple records,
90
   * including alerts, even though all alert messages are only two
91
   * bytes long. Handshake messages are de-chunked in the handshake
92
   * handler, change-cipher-spec messages are always empty, and we
93
   * don't care about chunking of application messages.
94
   *
95
   * This buffer will hold the incomplete alert that we receive, if
96
   * any.
97
   */
98
  private final ByteBuffer alertBuffer;
99
 
100
  private Mode mode;
101
 
102
  private enum Mode { SERVER, CLIENT }
103
 
104
  SSLEngineImpl (SSLContextImpl contextImpl, String host, int port)
105
  {
106
    super(host, port);
107
    this.contextImpl = contextImpl;
108
    handlers = new SSLRecordHandler[256];
109
    session = new SessionImpl();
110
    session.suite = CipherSuite.TLS_NULL_WITH_NULL_NULL;
111
    session.version = ProtocolVersion.TLS_1_1;
112
    byte[] sid = new byte[32];
113
    contextImpl.random.nextBytes(sid);
114
    session.setId(new Session.ID(sid));
115
    session.setRandom(contextImpl.random);
116
 
117
    if (Debug.DEBUG)
118
      logger.logv(Component.SSL_RECORD_LAYER, "generated session ID {0} with random {1}",
119
                  session.id(), contextImpl.random);
120
 
121
    // Begin with no encryption.
122
    insec = new InputSecurityParameters (null, null, null, session,
123
                                         CipherSuite.TLS_NULL_WITH_NULL_NULL);
124
    outsec = new OutputSecurityParameters (null, null, null, session,
125
                                           CipherSuite.TLS_NULL_WITH_NULL_NULL);
126
    inClosed = false;
127
    outClosed = false;
128
    needClientAuth = false;
129
    wantClientAuth = false;
130
    createSessions = true;
131
    initialHandshakeDone = false;
132
    alertBuffer = ByteBuffer.wrap (new byte[2]);
133
    mode = null;
134
    lastAlert = null;
135
    handshakeStatus = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
136
    changeCipherSpec = false;
137
 
138
    // Set up default protocols and suites.
139
    enabledProtocols = new String[] {
140
      ProtocolVersion.TLS_1_1.toString(),
141
      ProtocolVersion.TLS_1.toString(),
142
      ProtocolVersion.SSL_3.toString()
143
    };
144
    enabledSuites = defaultSuites();
145
  }
146
 
147
  static String[] defaultSuites()
148
  {
149
    return new String[] {
150
      CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA.toString(),
151
      CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA.toString(),
152
      CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA.toString(),
153
      CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA.toString(),
154
      CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA.toString(),
155
      CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA.toString(),
156
      CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA.toString(),
157
      CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA.toString(),
158
      CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA.toString(),
159
      CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.toString(),
160
      CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
161
      CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
162
      CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
163
      CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
164
      CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
165
      CipherSuite.TLS_RSA_WITH_RC4_128_MD5.toString(),
166
      CipherSuite.TLS_RSA_WITH_RC4_128_SHA.toString(),
167
      CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA.toString(),
168
      CipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA.toString(),
169
      CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA.toString(),
170
      CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.toString(),
171
      CipherSuite.TLS_RSA_WITH_DES_CBC_SHA.toString(),
172
      CipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
173
      CipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
174
      CipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
175
      CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5.toString(),
176
      CipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
177
      CipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
178
      CipherSuite.TLS_RSA_WITH_NULL_MD5.toString(),
179
      CipherSuite.TLS_RSA_WITH_NULL_SHA.toString()
180
    };
181
  }
182
 
183
  // XXX implement?
184
  /*public void registerHandler (final int contentType,
185
                               SSLRecordHandler handler)
186
    throws SSLException
187
  {
188
    if (type.equals (ContentType.CHANGE_CIPHER_SPEC)
189
        || type.equals (ContentType.ALERT)
190
        || type.equals (ContentType.HANDSHAKE)
191
        || type.equals (ContentType.APPLICATION_DATA))
192
      throw new SSLException ("can't override handler for content type " + type);
193
    int i = type.getValue ();
194
    if (i < 0 || i > 255)
195
      throw new SSLException ("illegal content type: " + type);
196
    handlers[i] = handler;
197
  }*/
198
 
199
  @Override
200
  public void beginHandshake () throws SSLException
201
  {
202
    if (Debug.DEBUG)
203
      logger.log(Component.SSL_HANDSHAKE, "{0} handshake begins", mode);
204
 
205
    if (mode == null)
206
      throw new IllegalStateException("setUseClientMode was never used");
207
 
208
    switch (mode)
209
      {
210
      case SERVER:
211
        if (getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
212
          throw new SSLException("handshake already in progress");
213
        try
214
          {
215
            handshake = new ServerHandshake(initialHandshakeDone, this);
216
          }
217
        catch (NoSuchAlgorithmException nsae)
218
          {
219
            throw new SSLException(nsae);
220
          }
221
        break;
222
 
223
      case CLIENT:
224
        try
225
          {
226
            handshake = new ClientHandshake(this);
227
          }
228
        catch (NoSuchAlgorithmException nsae)
229
          {
230
            throw new SSLException(nsae);
231
          }
232
        break;
233
      }
234
  }
235
 
236
  @Override
237
  public void closeInbound()
238
  {
239
    inClosed = true;
240
  }
241
 
242
  @Override
243
  public void closeOutbound()
244
  {
245
    lastAlert = new Alert(Alert.Level.WARNING, Alert.Description.CLOSE_NOTIFY);
246
  }
247
 
248
  @Override
249
  public Runnable getDelegatedTask()
250
  {
251
    if (handshake == null)
252
      return null;
253
    return handshake.getTask();
254
  }
255
 
256
  @Override
257
  public String[] getEnabledCipherSuites()
258
  {
259
    return (String[]) enabledSuites.clone();
260
  }
261
 
262
  @Override
263
  public String[] getEnabledProtocols()
264
  {
265
    return (String[]) enabledProtocols.clone();
266
  }
267
 
268
  @Override
269
  public boolean getEnableSessionCreation()
270
  {
271
    return createSessions;
272
  }
273
 
274
  @Override
275
  public HandshakeStatus getHandshakeStatus()
276
  {
277
    if (handshake == null)
278
      return HandshakeStatus.NOT_HANDSHAKING;
279
    return handshake.status();
280
  }
281
 
282
  @Override
283
  public boolean getNeedClientAuth()
284
  {
285
    return needClientAuth;
286
  }
287
 
288
  @Override
289
  public SSLSession getSession()
290
  {
291
    return session;
292
  }
293
 
294
  @Override
295
  public boolean getUseClientMode ()
296
  {
297
    return (mode == Mode.CLIENT);
298
  }
299
 
300
  @Override
301
  public boolean getWantClientAuth()
302
  {
303
    return wantClientAuth;
304
  }
305
 
306
  @Override
307
  public boolean isInboundDone()
308
  {
309
    return inClosed;
310
  }
311
 
312
  @Override
313
  public boolean isOutboundDone()
314
  {
315
    return outClosed;
316
  }
317
 
318
  @Override
319
  public void setEnableSessionCreation(final boolean createSessions)
320
  {
321
    this.createSessions = createSessions;
322
  }
323
 
324
  @Override
325
  public void setEnabledCipherSuites(final String[] suites)
326
  {
327
    if (suites.length == 0)
328
      throw new IllegalArgumentException("need at least one suite");
329
    enabledSuites = (String[]) suites.clone();
330
  }
331
 
332
  @Override
333
  public void setEnabledProtocols(final String[] protocols)
334
  {
335
    if (protocols.length == 0)
336
      throw new IllegalArgumentException("need at least one protocol");
337
    enabledProtocols = (String[]) protocols.clone();
338
  }
339
 
340
  @Override
341
  public String[] getSupportedCipherSuites()
342
  {
343
    // XXX if we ever want to support "pluggable" cipher suites, we'll need
344
    // to figure this out.
345
 
346
    return CipherSuite.availableSuiteNames().toArray(new String[0]);
347
  }
348
 
349
  @Override
350
  public String[] getSupportedProtocols()
351
  {
352
    return new String[] { ProtocolVersion.SSL_3.toString(),
353
                          ProtocolVersion.TLS_1.toString(),
354
                          ProtocolVersion.TLS_1_1.toString() };
355
  }
356
 
357
  @Override
358
  public void setNeedClientAuth(final boolean needClientAuth)
359
  {
360
    this.needClientAuth = needClientAuth;
361
  }
362
 
363
  @Override
364
  public void setUseClientMode (final boolean clientMode)
365
  {
366
    if (clientMode)
367
      mode = Mode.CLIENT;
368
    else
369
      mode = Mode.SERVER;
370
  }
371
 
372
  public @Override void setWantClientAuth(final boolean wantClientAuth)
373
  {
374
    this.wantClientAuth = wantClientAuth;
375
  }
376
 
377
  public @Override SSLEngineResult unwrap (final ByteBuffer source,
378
                                           final ByteBuffer[] sinks,
379
                                           final int offset, final int length)
380
    throws SSLException
381
  {
382
    if (mode == null)
383
      throw new IllegalStateException ("setUseClientMode was never called");
384
 
385
    if (inClosed)
386
      return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
387
                                 handshakeStatus, 0, 0);
388
 
389
    if (source.remaining() < 5)
390
      {
391
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW,
392
                                   handshakeStatus, 0, 0);
393
      }
394
 
395
    Record record = null;
396
    boolean helloV2 = false;
397
 
398
    // XXX: messages may be chunked across multiple records; does this
399
    // include the SSLv2 message? I don't think it does, but we should
400
    // make sure.
401
    if (!getUseClientMode() && (source.get(source.position()) & 0x80) == 0x80)
402
      {
403
        if (handshake == null)
404
          beginHandshake();
405
        int hellolen = source.getShort(source.position()) & 0x7FFF;
406
        this.handshake.handleV2Hello(source.slice());
407
        if (!insec.cipherSuite().equals (CipherSuite.TLS_NULL_WITH_NULL_NULL))
408
          throw new SSLException ("received SSLv2 client hello in encrypted "
409
                                  + "session; this is invalid.");
410
        if (Debug.DEBUG)
411
          logger.log (Component.SSL_RECORD_LAYER,
412
                      "converting SSLv2 client hello to version 3 hello");
413
 
414
        source.getShort(); // skip length
415
        ClientHelloV2 v2 = new ClientHelloV2(source.slice());
416
 
417
        if (Debug.DEBUG)
418
          logger.log(Component.SSL_RECORD_LAYER, "v2 hello: {0}", v2);
419
 
420
        List<CipherSuite> suites = v2.cipherSpecs();
421
 
422
        ClientHelloBuilder hello = new ClientHelloBuilder();
423
        hello.setVersion(v2.version ());
424
 
425
        Random random = hello.random();
426
        byte[] challenge = v2.challenge();
427
        if (challenge.length < 32)
428
          {
429
            byte[] b = new byte[32];
430
            System.arraycopy(challenge, 0, b, b.length - challenge.length,
431
                             challenge.length);
432
            challenge = b;
433
          }
434
        random.setGmtUnixTime((challenge[0] & 0xFF) << 24
435
                              | (challenge[1] & 0xFF) << 16
436
                              | (challenge[2] & 0xFF) <<  8
437
                              | (challenge[3] & 0xFF));
438
        random.setRandomBytes(challenge, 4);
439
 
440
        byte[] sessionId = v2.sessionId();
441
        hello.setSessionId(sessionId, 0, sessionId.length);
442
        hello.setCipherSuites(suites);
443
        ArrayList<CompressionMethod> comps = new ArrayList<CompressionMethod>(1);
444
        comps.add(CompressionMethod.NULL);
445
        hello.setCompressionMethods(comps);
446
 
447
        record = new Record(ByteBuffer.allocate(hello.length() + 9));
448
        record.setContentType(ContentType.HANDSHAKE);
449
        record.setVersion(v2.version());
450
        record.setLength(hello.length() + 4);
451
 
452
        Handshake handshake = new Handshake(record.fragment());
453
        handshake.setLength(hello.length());
454
        handshake.setType(Handshake.Type.CLIENT_HELLO);
455
 
456
        handshake.bodyBuffer().put(hello.buffer());
457
        source.position(source.position() + hellolen);
458
        helloV2 = true;
459
      }
460
    else
461
      record = new Record(source);
462
 
463
    ContentType type = record.contentType ();
464
 
465
    if (Debug.DEBUG)
466
      logger.log(Component.SSL_RECORD_LAYER, "input record:\n{0}", record);
467
 
468
    if (record.length() > session.getPacketBufferSize() - 5)
469
      {
470
        lastAlert = new Alert(Alert.Level.FATAL,
471
                              Alert.Description.RECORD_OVERFLOW);
472
        throw new AlertException(lastAlert);
473
      }
474
 
475
    ByteBufferOutputStream sysMsg = null;
476
    ByteBuffer msg = null;
477
 
478
    int produced = 0;
479
    try
480
      {
481
        // Application data will get decrypted directly into the user's
482
        // output buffers.
483
        if (record.contentType() == ContentType.APPLICATION_DATA)
484
          produced = insec.decrypt(record, sinks, offset, length);
485
        else
486
          {
487
            if (insec.cipherSuite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
488
              msg = record.fragment();
489
            else
490
              {
491
                sysMsg = new ByteBufferOutputStream();
492
                insec.decrypt(record, sysMsg);
493
              }
494
          }
495
 
496
        // Advance the input buffer past the record we just read.
497
        if (!helloV2)
498
          source.position(source.position() + record.length() + 5);
499
      }
500
    catch (BufferOverflowException boe)
501
      {
502
        // We throw this if the output buffers are not large enough; signal
503
        // the caller about this.
504
        logger.log(Component.SSL_RECORD_LAYER, "buffer overflow when decrypting", boe);
505
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW,
506
                                   handshakeStatus, 0, 0);
507
      }
508
    catch (IllegalBlockSizeException ibse)
509
      {
510
        lastAlert = new Alert(Alert.Level.FATAL,
511
                              Alert.Description.BAD_RECORD_MAC);
512
        throw new AlertException(lastAlert, ibse);
513
      }
514
    catch (DataFormatException dfe)
515
      {
516
        lastAlert = new Alert(Alert.Level.FATAL,
517
                              Alert.Description.DECOMPRESSION_FAILURE);
518
        throw new AlertException(lastAlert, dfe);
519
      }
520
    catch (MacException me)
521
      {
522
        lastAlert = new Alert(Alert.Level.FATAL,
523
                              Alert.Description.BAD_RECORD_MAC);
524
        throw new AlertException(lastAlert, me);
525
      }
526
    catch (ShortBufferException sbe)
527
      {
528
        // We've messed up if this happens.
529
        lastAlert = new Alert(Alert.Level.FATAL,
530
                              Alert.Description.INTERNAL_ERROR);
531
        throw new AlertException(lastAlert, sbe);
532
      }
533
 
534
    SSLEngineResult result = null;
535
 
536
    // If we need to handle the output here, do it. Otherwise, the output
537
    // has been stored in the supplied output buffers.
538
    if (sysMsg != null)
539
      {
540
        if (Debug.DEBUG)
541
          logger.logv(Component.SSL_RECORD_LAYER, "sysmessage {0}", sysMsg);
542
        msg = sysMsg.buffer();
543
      }
544
 
545
    if (type == ContentType.CHANGE_CIPHER_SPEC)
546
      {
547
        // We *may* get a partial message, even though the message is only
548
        // one byte long.
549
        if (msg.remaining() == 0)
550
          {
551
            result = new SSLEngineResult (SSLEngineResult.Status.OK,
552
                                          handshakeStatus,
553
                                          record.length() + 5, 0);
554
          }
555
        else
556
          {
557
            byte b = msg.get();
558
            if (b != 1)
559
              throw new SSLException ("unknown ChangeCipherSpec value: " + (b & 0xFF));
560
            InputSecurityParameters params = handshake.getInputParams();
561
            logger.log (Component.SSL_RECORD_LAYER,
562
                        "switching to input security parameters {0}",
563
                        params.cipherSuite());
564
            insec = params;
565
            result = new SSLEngineResult (SSLEngineResult.Status.OK,
566
                                          handshakeStatus,
567
                                          record.length() + 5, 0);
568
          }
569
      }
570
    else if (type == ContentType.ALERT)
571
      {
572
        int len = 0;
573
        if (alertBuffer.position() > 0)
574
          {
575
            alertBuffer.put(msg.get());
576
            len = 1;
577
          }
578
        if (Debug.DEBUG)
579
          logger.logv(Component.SSL_RECORD_LAYER, "processing alerts {0}",
580
                      Util.wrapBuffer(msg));
581
        len += msg.remaining() / 2;
582
        Alert[] alerts = new Alert[len];
583
        int i = 0;
584
        if (alertBuffer.position() > 0)
585
          {
586
            alertBuffer.flip();
587
            alerts[0] = new Alert(alertBuffer);
588
            i++;
589
          }
590
        while (i < alerts.length)
591
          {
592
            alerts[i++] = new Alert(msg.duplicate());
593
            msg.position(msg.position() + 2);
594
          }
595
        if (Debug.DEBUG)
596
          logger.logv(Component.SSL_RECORD_LAYER, "alerts: {0}", alerts.length);
597
 
598
        for (i = 0; i < alerts.length; i++)
599
          {
600
            if (alerts[i].level() == Alert.Level.FATAL)
601
              throw new AlertException(alerts[i], false);
602
            if (alerts[i].description() != Alert.Description.CLOSE_NOTIFY)
603
              logger.log(java.util.logging.Level.WARNING,
604
                         "received alert: {0}", alerts[i]);
605
            if (alerts[i].description() == Alert.Description.CLOSE_NOTIFY)
606
              inClosed = true;
607
          }
608
 
609
        if (msg.hasRemaining())
610
          alertBuffer.position(0).limit(2);
611
 
612
        result = new SSLEngineResult (SSLEngineResult.Status.OK,
613
                                      handshakeStatus,
614
                                      record.length() + 5, 0);
615
      }
616
    else if (type == ContentType.HANDSHAKE)
617
      {
618
        if (handshake == null)
619
          beginHandshake();
620
        try
621
          {
622
            handshakeStatus = handshake.handleInput(msg);
623
          }
624
        catch (AlertException ae)
625
          {
626
            lastAlert = ae.alert();
627
            return new SSLEngineResult(SSLEngineResult.Status.OK,
628
                                       SSLEngineResult.HandshakeStatus.NEED_WRAP,
629
                                       0, 0);
630
          }
631
        if (Debug.DEBUG)
632
          logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}", handshakeStatus);
633
        result = new SSLEngineResult(SSLEngineResult.Status.OK,
634
                                     handshakeStatus,
635
                                     record.length() + 5,
636
                                     0);
637
        if (handshakeStatus == HandshakeStatus.FINISHED)
638
          {
639
            handshake = null;
640
            handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
641
          }
642
      }
643
    else if (type == ContentType.APPLICATION_DATA)
644
      {
645
        // Do nothing more; the application data has been put into
646
        // the output buffers.
647
        result = new SSLEngineResult(SSLEngineResult.Status.OK,
648
                                     handshakeStatus,
649
                                     record.length() + 5,
650
                                     produced);
651
      }
652
    else
653
      {
654
        SSLRecordHandler handler = handlers[type.getValue()];
655
        if (handler != null)
656
          {
657
            result = new SSLEngineResult(SSLEngineResult.Status.OK,
658
                                         handshakeStatus,
659
                                         record.length() + 5,
660
                                         0);
661
          }
662
        else
663
          throw new SSLException ("unknown content type: " + type);
664
      }
665
 
666
    if (Debug.DEBUG)
667
      logger.logv(Component.SSL_RECORD_LAYER, "return result: {0}", result);
668
 
669
    return result;
670
  }
671
 
672
  public @Override SSLEngineResult wrap (ByteBuffer[] sources, int offset, int length,
673
                                         ByteBuffer sink)
674
    throws SSLException
675
  {
676
    if (mode == null)
677
      throw new IllegalStateException ("setUseClientMode was never called");
678
 
679
    if (outClosed)
680
      return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
681
                                 handshakeStatus, 0, 0);
682
 
683
    ContentType type = null;
684
    ByteBuffer sysMessage = null;
685
    if (Debug.DEBUG)
686
      logger.logv(Component.SSL_RECORD_LAYER, "wrap {0} {1} {2} {3} / {4}",
687
                  sources, offset, length, sink, getHandshakeStatus());
688
    if (lastAlert != null)
689
      {
690
        type = ContentType.ALERT;
691
        sysMessage = ByteBuffer.allocate(2);
692
        Alert alert = new Alert(sysMessage);
693
        alert.setDescription(lastAlert.description());
694
        alert.setLevel(lastAlert.level());
695
        if (lastAlert.description() == Alert.Description.CLOSE_NOTIFY)
696
          outClosed = true;
697
      }
698
    else if (changeCipherSpec)
699
      {
700
        type = ContentType.CHANGE_CIPHER_SPEC;
701
        sysMessage = ByteBuffer.allocate(1);
702
        sysMessage.put(0, (byte) 1);
703
      }
704
    else if (getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP)
705
      {
706
        // If we are not encrypting, optimize the handshake to fill
707
        // the buffer directly.
708
        if (outsec.suite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
709
          {
710
            int orig = sink.position();
711
            sink.order(ByteOrder.BIG_ENDIAN);
712
            sink.put((byte) ContentType.HANDSHAKE.getValue());
713
            sink.putShort((short) session.version.rawValue());
714
            sink.putShort((short) 0);
715
            handshakeStatus = handshake.handleOutput(sink);
716
            int produced = sink.position() - orig;
717
            sink.putShort(orig + 3, (short) (produced - 5));
718
            if (Debug.DEBUG)
719
              logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
720
                          new Record((ByteBuffer) sink.duplicate().position(orig)));
721
            SSLEngineResult result = new SSLEngineResult(SSLEngineResult.Status.OK,
722
                                                         handshakeStatus, 0, produced);
723
 
724
            // Note, this will only happen if we transition from
725
            // TLS_NULL_WITH_NULL_NULL *to* TLS_NULL_WITH_NULL_NULL, which
726
            // doesn't make a lot of sense, but we support it anyway.
727
            if (handshakeStatus == HandshakeStatus.FINISHED)
728
              {
729
                handshake = null; // finished with it.
730
                handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
731
              }
732
            return result;
733
          }
734
 
735
        // Rough guideline; XXX.
736
        sysMessage = ByteBuffer.allocate(sink.remaining() - 2048);
737
        type = ContentType.HANDSHAKE;
738
        try
739
          {
740
            handshakeStatus = handshake.handleOutput(sysMessage);
741
          }
742
        catch (AlertException ae)
743
          {
744
            lastAlert = ae.alert();
745
            return new SSLEngineResult(Status.OK,
746
                                       HandshakeStatus.NEED_WRAP, 0, 0);
747
          }
748
        sysMessage.flip();
749
        if (Debug.DEBUG)
750
          logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}",
751
                      handshakeStatus);
752
      }
753
 
754
    int produced = 0;
755
    int consumed = 0;
756
 
757
    try
758
      {
759
        int orig = sink.position();
760
        int[] inout = null;
761
        if (sysMessage != null)
762
          {
763
            if (Debug.DEBUG)
764
              logger.logv(Component.SSL_RECORD_LAYER, "encrypt system message {0} to {1}", sysMessage, sink);
765
            inout = outsec.encrypt(new ByteBuffer[] { sysMessage }, 0, 1,
766
                                   type, sink);
767
            produced = inout[1];
768
          }
769
        else
770
          {
771
            inout = outsec.encrypt(sources, offset, length,
772
                                   ContentType.APPLICATION_DATA, sink);
773
            consumed = inout[0];
774
            produced = inout[1];
775
          }
776
 
777
        if (Debug.DEBUG)
778
          logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
779
                      new Record((ByteBuffer) sink.duplicate().position(orig).limit(produced)));
780
      }
781
    catch (ShortBufferException sbe)
782
      {
783
        // We don't expect this to happen, except for bugs; signal an
784
        // internal error.
785
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
786
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
787
      }
788
    catch (IllegalBlockSizeException ibse)
789
      {
790
        // We don't expect this to happen, except for bugs; signal an
791
        // internal error.
792
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
793
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
794
      }
795
    catch (DataFormatException dfe)
796
      {
797
        // We don't expect this to happen; signal an internal error.
798
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
799
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
800
      }
801
 
802
    if (lastAlert != null && lastAlert.level() == Alert.Level.FATAL)
803
      {
804
        AlertException ae = new AlertException(lastAlert);
805
        lastAlert = null;
806
        throw ae;
807
      }
808
 
809
    if (changeCipherSpec)
810
      {
811
        outsec = handshake.getOutputParams();
812
        changeCipherSpec = false;
813
      }
814
    SSLEngineResult result
815
      = new SSLEngineResult(outClosed ? SSLEngineResult.Status.CLOSED
816
                                      : SSLEngineResult.Status.OK,
817
                            handshakeStatus, consumed, produced);
818
    if (handshakeStatus == HandshakeStatus.FINISHED)
819
      {
820
        handshake = null; // done with it.
821
        handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
822
      }
823
    return result;
824
  }
825
 
826
  // Package-private methods.
827
 
828
  SessionImpl session ()
829
  {
830
    return session;
831
  }
832
 
833
  void setSession(SessionImpl session)
834
  {
835
    this.session = session;
836
  }
837
 
838
  void changeCipherSpec()
839
  {
840
    changeCipherSpec = true;
841
  }
842
}

powered by: WebSVN 2.1.0

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