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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [crypto/] [sasl/] [srp/] [SRPServer.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* SRPServer.java --
2
   Copyright (C) 2003, 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.crypto.sasl.srp;
40
 
41
import gnu.java.lang.CPStringBuilder;
42
 
43
import gnu.java.security.Configuration;
44
import gnu.java.security.Registry;
45
import gnu.java.security.util.PRNG;
46
import gnu.java.security.util.Util;
47
import gnu.javax.crypto.assembly.Direction;
48
import gnu.javax.crypto.cipher.CipherFactory;
49
import gnu.javax.crypto.cipher.IBlockCipher;
50
import gnu.javax.crypto.key.IKeyAgreementParty;
51
import gnu.javax.crypto.key.IncomingMessage;
52
import gnu.javax.crypto.key.KeyAgreementException;
53
import gnu.javax.crypto.key.KeyAgreementFactory;
54
import gnu.javax.crypto.key.OutgoingMessage;
55
import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;
56
import gnu.javax.crypto.sasl.IllegalMechanismStateException;
57
import gnu.javax.crypto.sasl.InputBuffer;
58
import gnu.javax.crypto.sasl.IntegrityException;
59
import gnu.javax.crypto.sasl.OutputBuffer;
60
import gnu.javax.crypto.sasl.ServerMechanism;
61
 
62
import java.io.ByteArrayOutputStream;
63
import java.io.IOException;
64
import java.io.UnsupportedEncodingException;
65
import java.math.BigInteger;
66
import java.util.Arrays;
67
import java.util.HashMap;
68
import java.util.StringTokenizer;
69
import java.util.logging.Logger;
70
 
71
import javax.security.sasl.AuthenticationException;
72
import javax.security.sasl.SaslException;
73
import javax.security.sasl.SaslServer;
74
 
75
/**
76
 * The SASL-SRP server-side mechanism.
77
 */
78
public class SRPServer
79
    extends ServerMechanism
80
    implements SaslServer
81
{
82
  private static final Logger log = Logger.getLogger(SRPServer.class.getName());
83
  private String U = null; // client's username
84
  private BigInteger N, g, A, B;
85
  private byte[] s; // salt
86
  private byte[] cIV, sIV; // client+server IVs, when confidentiality is on
87
  private byte[] cn, sn; // client's and server's nonce
88
  private SRP srp; // SRP algorithm instance used by this server
89
  private byte[] sid; // session ID when re-used
90
  private int ttl = 360; // session time-to-live in seconds
91
  private byte[] cCB; // peer's channel binding'
92
  private String mandatory; // List of available options
93
  private String L = null;
94
  private String o;
95
  private String chosenIntegrityAlgorithm;
96
  private String chosenConfidentialityAlgorithm;
97
  private int rawSendSize = Registry.SASL_BUFFER_MAX_LIMIT;
98
  private byte[] K; // shared session key
99
  private boolean replayDetection = true; // whether Replay Detection is on
100
  private int inCounter = 0; // messages sequence numbers
101
  private int outCounter = 0;
102
  private IALG inMac, outMac; // if !null, use for integrity
103
  private CALG inCipher, outCipher; // if !null, use for confidentiality
104
  private IKeyAgreementParty serverHandler =
105
      KeyAgreementFactory.getPartyBInstance(Registry.SRP_SASL_KA);
106
  /** Our default source of randomness. */
107
  private PRNG prng = null;
108
 
109
  public SRPServer()
110
  {
111
    super(Registry.SASL_SRP_MECHANISM);
112
  }
113
 
114
  protected void initMechanism() throws SaslException
115
  {
116
    // TODO:
117
    // we must have a means to map a given username to a preferred
118
    // SRP hash algorithm; otherwise we end up using _always_ SHA.
119
    // for the time being get it from the mechanism properties map
120
    // and apply it for all users.
121
    final String mda = (String) properties.get(SRPRegistry.SRP_HASH);
122
    srp = SRP.instance(mda == null ? SRPRegistry.SRP_DEFAULT_DIGEST_NAME : mda);
123
  }
124
 
125
  protected void resetMechanism() throws SaslException
126
  {
127
    s = null;
128
    A = B = null;
129
    K = null;
130
    inMac = outMac = null;
131
    inCipher = outCipher = null;
132
    sid = null;
133
  }
134
 
135
  public byte[] evaluateResponse(final byte[] response) throws SaslException
136
  {
137
    switch (state)
138
      {
139
      case 0:
140
        if (response == null)
141
          return null;
142
        state++;
143
        return sendProtocolElements(response);
144
      case 1:
145
        if (! complete)
146
          {
147
            state++;
148
            return sendEvidence(response);
149
          }
150
      // else fall through
151
      default:
152
        throw new IllegalMechanismStateException("evaluateResponse()");
153
      }
154
  }
155
 
156
  protected byte[] engineUnwrap(final byte[] incoming, final int offset,
157
                                final int len) throws SaslException
158
  {
159
    if (Configuration.DEBUG)
160
      log.entering(this.getClass().getName(), "engineUnwrap");
161
    if (inMac == null && inCipher == null)
162
      throw new IllegalStateException("connection is not protected");
163
    if (Configuration.DEBUG)
164
      log.fine("Incoming buffer (before security): "
165
               + Util.dumpString(incoming, offset, len));
166
    // at this point one, or both, of confidentiality and integrity protection
167
    // services are active.
168
    final byte[] result;
169
    try
170
      {
171
        if (inMac != null)
172
          { // integrity bytes are at the end of the stream
173
            final int macBytesCount = inMac.length();
174
            final int payloadLength = len - macBytesCount;
175
            final byte[] received_mac = new byte[macBytesCount];
176
            System.arraycopy(incoming, offset + payloadLength, received_mac, 0,
177
                             macBytesCount);
178
            if (Configuration.DEBUG)
179
              log.fine("Got C (received MAC): " + Util.dumpString(received_mac));
180
            inMac.update(incoming, offset, payloadLength);
181
            if (replayDetection)
182
              {
183
                inCounter++;
184
                if (Configuration.DEBUG)
185
                  log.fine("inCounter=" + String.valueOf(inCounter));
186
                inMac.update(new byte[] {
187
                    (byte)(inCounter >>> 24),
188
                    (byte)(inCounter >>> 16),
189
                    (byte)(inCounter >>> 8),
190
                    (byte) inCounter });
191
              }
192
            final byte[] computed_mac = inMac.doFinal();
193
            if (Configuration.DEBUG)
194
              log.fine("Computed MAC: " + Util.dumpString(computed_mac));
195
            if (! Arrays.equals(received_mac, computed_mac))
196
              throw new IntegrityException("engineUnwrap()");
197
            // deal with the payload, which can be either plain or encrypted
198
            if (inCipher != null)
199
              result = inCipher.doFinal(incoming, offset, payloadLength);
200
            else
201
              {
202
                result = new byte[payloadLength];
203
                System.arraycopy(incoming, offset, result, 0, result.length);
204
              }
205
          }
206
        else // no integrity protection; just confidentiality
207
          result = inCipher.doFinal(incoming, offset, len);
208
      }
209
    catch (IOException x)
210
      {
211
        if (x instanceof SaslException)
212
          throw (SaslException) x;
213
        throw new SaslException("engineUnwrap()", x);
214
      }
215
    if (Configuration.DEBUG)
216
      {
217
        log.fine("Incoming buffer (after security): " + Util.dumpString(result));
218
        log.exiting(this.getClass().getName(), "engineUnwrap");
219
      }
220
    return result;
221
  }
222
 
223
  protected byte[] engineWrap(final byte[] outgoing, final int offset,
224
                              final int len) throws SaslException
225
  {
226
    if (Configuration.DEBUG)
227
      log.entering(this.getClass().getName(), "engineWrap");
228
    if (outMac == null && outCipher == null)
229
      throw new IllegalStateException("connection is not protected");
230
    if (Configuration.DEBUG)
231
      {
232
        log.fine("Outgoing buffer (before security) (hex): "
233
                 + Util.dumpString(outgoing, offset, len));
234
        log.fine("Outgoing buffer (before security) (str): \""
235
                 + new String(outgoing, offset, len) + "\"");
236
      }
237
    // at this point one, or both, of confidentiality and integrity protection
238
    // services are active.
239
    byte[] result;
240
    try
241
      {
242
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
243
        if (outCipher != null)
244
          {
245
            result = outCipher.doFinal(outgoing, offset, len);
246
            if (Configuration.DEBUG)
247
              log.fine("Encoding c (encrypted plaintext): "
248
                       + Util.dumpString(result));
249
            out.write(result);
250
            if (outMac != null)
251
              {
252
                outMac.update(result);
253
                if (replayDetection)
254
                  {
255
                    outCounter++;
256
                    if (Configuration.DEBUG)
257
                      log.fine("outCounter=" + outCounter);
258
                    outMac.update(new byte[] {
259
                        (byte)(outCounter >>> 24),
260
                        (byte)(outCounter >>> 16),
261
                        (byte)(outCounter >>> 8),
262
                        (byte) outCounter });
263
                  }
264
                final byte[] C = outMac.doFinal();
265
                out.write(C);
266
                if (Configuration.DEBUG)
267
                  log.fine("Encoding C (integrity checksum): " + Util.dumpString(C));
268
              }
269
            // else ciphertext only; do nothing
270
          }
271
        else // no confidentiality; just integrity [+ replay detection]
272
          {
273
            if (Configuration.DEBUG)
274
              log.fine("Encoding p (plaintext): "
275
                       + Util.dumpString(outgoing, offset, len));
276
            out.write(outgoing, offset, len);
277
            outMac.update(outgoing, offset, len);
278
            if (replayDetection)
279
              {
280
                outCounter++;
281
                if (Configuration.DEBUG)
282
                  log.fine("outCounter=" + outCounter);
283
                outMac.update(new byte[] {
284
                    (byte)(outCounter >>> 24),
285
                    (byte)(outCounter >>> 16),
286
                    (byte)(outCounter >>> 8),
287
                    (byte) outCounter });
288
              }
289
            final byte[] C = outMac.doFinal();
290
            out.write(C);
291
            if (Configuration.DEBUG)
292
              log.fine("Encoding C (integrity checksum): " + Util.dumpString(C));
293
          }
294
        result = out.toByteArray();
295
      }
296
    catch (IOException x)
297
      {
298
        if (x instanceof SaslException)
299
          throw (SaslException) x;
300
        throw new SaslException("engineWrap()", x);
301
      }
302
    if (Configuration.DEBUG)
303
      log.exiting(this.getClass().getName(), "engineWrap");
304
    return result;
305
  }
306
 
307
  protected String getNegotiatedQOP()
308
  {
309
    if (inMac != null)
310
      {
311
        if (inCipher != null)
312
          return Registry.QOP_AUTH_CONF;
313
        return Registry.QOP_AUTH_INT;
314
      }
315
    return Registry.QOP_AUTH;
316
  }
317
 
318
  protected String getNegotiatedStrength()
319
  {
320
    if (inMac != null)
321
      {
322
        if (inCipher != null)
323
          return Registry.STRENGTH_HIGH;
324
        return Registry.STRENGTH_MEDIUM;
325
      }
326
    return Registry.STRENGTH_LOW;
327
  }
328
 
329
  protected String getNegotiatedRawSendSize()
330
  {
331
    return String.valueOf(rawSendSize);
332
  }
333
 
334
  protected String getReuse()
335
  {
336
    return Registry.REUSE_TRUE;
337
  }
338
 
339
  private byte[] sendProtocolElements(final byte[] input) throws SaslException
340
  {
341
    if (Configuration.DEBUG)
342
      {
343
        log.entering(this.getClass().getName(), "sendProtocolElements");
344
        log.fine("C: " + Util.dumpString(input));
345
      }
346
    // Client send U, I, sid, cn
347
    final InputBuffer frameIn = new InputBuffer(input);
348
    try
349
      {
350
        U = frameIn.getText(); // Extract username
351
        if (Configuration.DEBUG)
352
          log.fine("Got U (username): \"" + U + "\"");
353
        authorizationID = frameIn.getText(); // Extract authorisation ID
354
        if (Configuration.DEBUG)
355
          log.fine("Got I (userid): \"" + authorizationID + "\"");
356
        sid = frameIn.getEOS();
357
        if (Configuration.DEBUG)
358
          log.fine("Got sid (session ID): " + new String(sid));
359
        cn = frameIn.getOS();
360
        if (Configuration.DEBUG)
361
          log.fine("Got cn (client nonce): " + Util.dumpString(cn));
362
        cCB = frameIn.getEOS();
363
        if (Configuration.DEBUG)
364
          log.fine("Got cCB (client channel binding): " + Util.dumpString(cCB));
365
      }
366
    catch (IOException x)
367
      {
368
        if (x instanceof SaslException)
369
          throw (SaslException) x;
370
        throw new AuthenticationException("sendProtocolElements()", x);
371
      }
372
    // do/can we re-use?
373
    if (ServerStore.instance().isAlive(sid))
374
      {
375
        final SecurityContext ctx = ServerStore.instance().restoreSession(sid);
376
        srp = SRP.instance(ctx.getMdName());
377
        K = ctx.getK();
378
        cIV = ctx.getClientIV();
379
        sIV = ctx.getServerIV();
380
        replayDetection = ctx.hasReplayDetection();
381
        inCounter = ctx.getInCounter();
382
        outCounter = ctx.getOutCounter();
383
        inMac = ctx.getInMac();
384
        outMac = ctx.getOutMac();
385
        inCipher = ctx.getInCipher();
386
        outCipher = ctx.getOutCipher();
387
        if (sn == null || sn.length != 16)
388
          sn = new byte[16];
389
        getDefaultPRNG().nextBytes(sn);
390
        setupSecurityServices(false);
391
        final OutputBuffer frameOut = new OutputBuffer();
392
        try
393
          {
394
            frameOut.setScalar(1, 0xFF);
395
            frameOut.setOS(sn);
396
            frameOut.setEOS(channelBinding);
397
          }
398
        catch (IOException x)
399
          {
400
            if (x instanceof SaslException)
401
              throw (SaslException) x;
402
            throw new AuthenticationException("sendProtocolElements()", x);
403
          }
404
        final byte[] result = frameOut.encode();
405
        if (Configuration.DEBUG)
406
          {
407
            log.fine("Old session...");
408
            log.fine("S: " + Util.dumpString(result));
409
            log.fine("  sn = " + Util.dumpString(sn));
410
            log.fine(" sCB = " + Util.dumpString(channelBinding));
411
            log.exiting(this.getClass().getName(), "sendProtocolElements");
412
          }
413
        return result;
414
      }
415
    else
416
      { // new session
417
        authenticator.activate(properties);
418
        // -------------------------------------------------------------------
419
        final HashMap mapB = new HashMap();
420
        mapB.put(SRP6KeyAgreement.HASH_FUNCTION, srp.getAlgorithm());
421
        mapB.put(SRP6KeyAgreement.HOST_PASSWORD_DB, authenticator);
422
        try
423
          {
424
            serverHandler.init(mapB);
425
            OutgoingMessage out = new OutgoingMessage();
426
            out.writeString(U);
427
            IncomingMessage in = new IncomingMessage(out.toByteArray());
428
            out = serverHandler.processMessage(in);
429
            in = new IncomingMessage(out.toByteArray());
430
            N = in.readMPI();
431
            g = in.readMPI();
432
            s = in.readMPI().toByteArray();
433
            B = in.readMPI();
434
          }
435
        catch (KeyAgreementException x)
436
          {
437
            throw new SaslException("sendProtocolElements()", x);
438
          }
439
        // -------------------------------------------------------------------
440
        if (Configuration.DEBUG)
441
          {
442
            log.fine("Encoding N (modulus): " + Util.dump(N));
443
            log.fine("Encoding g (generator): " + Util.dump(g));
444
            log.fine("Encoding s (client's salt): " + Util.dumpString(s));
445
            log.fine("Encoding B (server ephemeral public key): " + Util.dump(B));
446
          }
447
        // The server creates an options list (L), which consists of a
448
        // comma-separated list of option strings that specify the security
449
        // service options the server supports.
450
        L = createL();
451
        if (Configuration.DEBUG)
452
          {
453
            log.fine("Encoding L (available options): \"" + L + "\"");
454
            log.fine("Encoding sIV (server IV): " + Util.dumpString(sIV));
455
          }
456
        final OutputBuffer frameOut = new OutputBuffer();
457
        try
458
          {
459
            frameOut.setScalar(1, 0x00);
460
            frameOut.setMPI(N);
461
            frameOut.setMPI(g);
462
            frameOut.setOS(s);
463
            frameOut.setMPI(B);
464
            frameOut.setText(L);
465
          }
466
        catch (IOException x)
467
          {
468
            if (x instanceof SaslException)
469
              throw (SaslException) x;
470
            throw new AuthenticationException("sendProtocolElements()", x);
471
          }
472
        final byte[] result = frameOut.encode();
473
        if (Configuration.DEBUG)
474
          {
475
            log.fine("New session...");
476
            log.fine("S: " + Util.dumpString(result));
477
            log.fine("   N = 0x" + N.toString(16));
478
            log.fine("   g = 0x" + g.toString(16));
479
            log.fine("   s = " + Util.dumpString(s));
480
            log.fine("   B = 0x" + B.toString(16));
481
            log.fine("   L = " + L);
482
            log.exiting(this.getClass().getName(), "sendProtocolElements");
483
          }
484
        return result;
485
      }
486
  }
487
 
488
  private byte[] sendEvidence(final byte[] input) throws SaslException
489
  {
490
    if (Configuration.DEBUG)
491
      {
492
        log.entering(this.getClass().getName(), "sendEvidence");
493
        log.fine("C: " + Util.dumpString(input));
494
      }
495
    // Client send A, M1, o, cIV
496
    final InputBuffer frameIn = new InputBuffer(input);
497
    final byte[] M1;
498
    try
499
      {
500
        A = frameIn.getMPI(); // Extract client's ephemeral public key
501
        if (Configuration.DEBUG)
502
          log.fine("Got A (client ephemeral public key): " + Util.dump(A));
503
        M1 = frameIn.getOS(); // Extract evidence
504
        if (Configuration.DEBUG)
505
          log.fine("Got M1 (client evidence): " + Util.dumpString(M1));
506
        o = frameIn.getText(); // Extract client's options list
507
        if (Configuration.DEBUG)
508
          log.fine("Got o (client chosen options): \"" + o + "\"");
509
        cIV = frameIn.getOS(); // Extract client's IV
510
        if (Configuration.DEBUG)
511
          log.fine("Got cIV (client IV): " + Util.dumpString(cIV));
512
      }
513
    catch (IOException x)
514
      {
515
        if (x instanceof SaslException)
516
          throw (SaslException) x;
517
        throw new AuthenticationException("sendEvidence()", x);
518
      }
519
    // Parse client's options and set security layer variables
520
    parseO(o);
521
    // ----------------------------------------------------------------------
522
    try
523
      {
524
        final OutgoingMessage out = new OutgoingMessage();
525
        out.writeMPI(A);
526
        final IncomingMessage in = new IncomingMessage(out.toByteArray());
527
        serverHandler.processMessage(in);
528
        K = serverHandler.getSharedSecret();
529
      }
530
    catch (KeyAgreementException x)
531
      {
532
        throw new SaslException("sendEvidence()", x);
533
      }
534
    // ----------------------------------------------------------------------
535
    if (Configuration.DEBUG)
536
      log.fine("K: " + Util.dumpString(K));
537
    final byte[] expected;
538
    try
539
      {
540
        expected = srp.generateM1(N, g, U, s, A, B, K, authorizationID, L, cn,
541
                                  cCB);
542
      }
543
    catch (UnsupportedEncodingException x)
544
      {
545
        throw new AuthenticationException("sendEvidence()", x);
546
      }
547
    // Verify client evidence
548
    if (! Arrays.equals(M1, expected))
549
      throw new AuthenticationException("M1 mismatch");
550
    setupSecurityServices(true);
551
    final byte[] M2;
552
    try
553
      {
554
        M2 = srp.generateM2(A, M1, K, U, authorizationID, o, sid, ttl, cIV,
555
                            sIV, channelBinding);
556
      }
557
    catch (UnsupportedEncodingException x)
558
      {
559
        throw new AuthenticationException("sendEvidence()", x);
560
      }
561
    final OutputBuffer frameOut = new OutputBuffer();
562
    try
563
      {
564
        frameOut.setOS(M2);
565
        frameOut.setOS(sIV);
566
        frameOut.setEOS(sid);
567
        frameOut.setScalar(4, ttl);
568
        frameOut.setEOS(channelBinding);
569
      }
570
    catch (IOException x)
571
      {
572
        if (x instanceof SaslException)
573
          throw (SaslException) x;
574
        throw new AuthenticationException("sendEvidence()", x);
575
      }
576
    final byte[] result = frameOut.encode();
577
    if (Configuration.DEBUG)
578
      {
579
        log.fine("S: " + Util.dumpString(result));
580
        log.fine("  M2 = " + Util.dumpString(M2));
581
        log.fine(" sIV = " + Util.dumpString(sIV));
582
        log.fine(" sid = " + new String(sid));
583
        log.fine(" ttl = " + ttl);
584
        log.fine(" sCB = " + Util.dumpString(channelBinding));
585
        log.exiting(this.getClass().getName(), "sendEvidence");
586
      }
587
    return result;
588
  }
589
 
590
  private String createL()
591
  {
592
    if (Configuration.DEBUG)
593
      log.entering(this.getClass().getName(), "createL()");
594
    String s = (String) properties.get(SRPRegistry.SRP_MANDATORY);
595
    if (s == null)
596
      s = SRPRegistry.DEFAULT_MANDATORY;
597
 
598
    if (! SRPRegistry.MANDATORY_NONE.equals(s)
599
        && ! SRPRegistry.OPTION_REPLAY_DETECTION.equals(s)
600
        && ! SRPRegistry.OPTION_INTEGRITY.equals(s)
601
        && ! SRPRegistry.OPTION_CONFIDENTIALITY.equals(s))
602
      {
603
        if (Configuration.DEBUG)
604
          log.fine("Unrecognised mandatory option (" + s + "). Using default...");
605
        s = SRPRegistry.DEFAULT_MANDATORY;
606
      }
607
    mandatory = s;
608
    s = (String) properties.get(SRPRegistry.SRP_CONFIDENTIALITY);
609
    final boolean confidentiality = (s == null ? SRPRegistry.DEFAULT_CONFIDENTIALITY
610
                                               : Boolean.valueOf(s).booleanValue());
611
    s = (String) properties.get(SRPRegistry.SRP_INTEGRITY_PROTECTION);
612
    boolean integrity = (s == null ? SRPRegistry.DEFAULT_INTEGRITY
613
                                   : Boolean.valueOf(s).booleanValue());
614
    s = (String) properties.get(SRPRegistry.SRP_REPLAY_DETECTION);
615
    final boolean replayDetection = (s == null ? SRPRegistry.DEFAULT_REPLAY_DETECTION
616
                                               : Boolean.valueOf(s).booleanValue());
617
    final CPStringBuilder sb = new CPStringBuilder();
618
    sb.append(SRPRegistry.OPTION_SRP_DIGEST).append("=")
619
      .append(srp.getAlgorithm()).append(",");
620
 
621
    if (! SRPRegistry.MANDATORY_NONE.equals(mandatory))
622
      sb.append(SRPRegistry.OPTION_MANDATORY)
623
        .append("=").append(mandatory).append(",");
624
 
625
    if (replayDetection)
626
      {
627
        sb.append(SRPRegistry.OPTION_REPLAY_DETECTION).append(",");
628
        // if replay detection is on then force integrity protection
629
        integrity = true;
630
      }
631
    int i;
632
    if (integrity)
633
      {
634
        for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
635
          sb.append(SRPRegistry.OPTION_INTEGRITY).append("=")
636
            .append(SRPRegistry.INTEGRITY_ALGORITHMS[i]).append(",");
637
      }
638
    if (confidentiality)
639
      {
640
        IBlockCipher cipher;
641
        for (i = 0; i < SRPRegistry.CONFIDENTIALITY_ALGORITHMS.length; i++)
642
          {
643
            cipher = CipherFactory.getInstance(SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i]);
644
            if (cipher != null)
645
              sb.append(SRPRegistry.OPTION_CONFIDENTIALITY).append("=")
646
                .append(SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i]).append(",");
647
          }
648
      }
649
    final String result = sb.append(SRPRegistry.OPTION_MAX_BUFFER_SIZE)
650
                            .append("=").append(Registry.SASL_BUFFER_MAX_LIMIT)
651
                            .toString();
652
    if (Configuration.DEBUG)
653
      log.exiting(this.getClass().getName(), "createL");
654
    return result;
655
  }
656
 
657
  // Parse client's options and set security layer variables
658
  private void parseO(final String o) throws AuthenticationException
659
  {
660
    this.replayDetection = false;
661
    boolean integrity = false;
662
    boolean confidentiality = false;
663
    String option;
664
    int i;
665
 
666
    final StringTokenizer st = new StringTokenizer(o.toLowerCase(), ",");
667
    while (st.hasMoreTokens())
668
      {
669
        option = st.nextToken();
670
        if (Configuration.DEBUG)
671
          log.fine("option: <" + option + ">");
672
        if (option.equals(SRPRegistry.OPTION_REPLAY_DETECTION))
673
          replayDetection = true;
674
        else if (option.startsWith(SRPRegistry.OPTION_INTEGRITY + "="))
675
          {
676
            if (integrity)
677
              throw new AuthenticationException(
678
                  "Only one integrity algorithm may be chosen");
679
            option = option.substring(option.indexOf('=') + 1);
680
            if (Configuration.DEBUG)
681
              log.fine("algorithm: <" + option + ">");
682
            for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
683
              {
684
                if (SRPRegistry.INTEGRITY_ALGORITHMS[i].equals(option))
685
                  {
686
                    chosenIntegrityAlgorithm = option;
687
                    integrity = true;
688
                    break;
689
                  }
690
              }
691
            if (! integrity)
692
              throw new AuthenticationException("Unknown integrity algorithm: "
693
                                                + option);
694
          }
695
        else if (option.startsWith(SRPRegistry.OPTION_CONFIDENTIALITY + "="))
696
          {
697
            if (confidentiality)
698
              throw new AuthenticationException(
699
                  "Only one confidentiality algorithm may be chosen");
700
            option = option.substring(option.indexOf('=') + 1);
701
            if (Configuration.DEBUG)
702
              log.fine("algorithm: <" + option + ">");
703
            for (i = 0; i < SRPRegistry.CONFIDENTIALITY_ALGORITHMS.length; i++)
704
              {
705
                if (SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i].equals(option))
706
                  {
707
                    chosenConfidentialityAlgorithm = option;
708
                    confidentiality = true;
709
                    break;
710
                  }
711
              }
712
            if (! confidentiality)
713
              throw new AuthenticationException("Unknown confidentiality algorithm: "
714
                                                + option);
715
          }
716
        else if (option.startsWith(SRPRegistry.OPTION_MAX_BUFFER_SIZE + "="))
717
          {
718
            final String maxBufferSize = option.substring(option.indexOf('=') + 1);
719
            try
720
              {
721
                rawSendSize = Integer.parseInt(maxBufferSize);
722
                if (rawSendSize > Registry.SASL_BUFFER_MAX_LIMIT
723
                    || rawSendSize < 1)
724
                  throw new AuthenticationException(
725
                      "Illegal value for 'maxbuffersize' option");
726
              }
727
            catch (NumberFormatException x)
728
              {
729
                throw new AuthenticationException(
730
                    SRPRegistry.OPTION_MAX_BUFFER_SIZE + "=" + maxBufferSize, x);
731
              }
732
          }
733
      }
734
    // check if client did the right thing
735
    if (replayDetection)
736
      {
737
        if (! integrity)
738
          throw new AuthenticationException(
739
              "Missing integrity protection algorithm but replay detection is chosen");
740
      }
741
    if (mandatory.equals(SRPRegistry.OPTION_REPLAY_DETECTION))
742
      {
743
        if (! replayDetection)
744
          throw new AuthenticationException(
745
              "Replay detection is mandatory but was not chosen");
746
      }
747
    if (mandatory.equals(SRPRegistry.OPTION_INTEGRITY))
748
      {
749
        if (! integrity)
750
          throw new AuthenticationException(
751
              "Integrity protection is mandatory but was not chosen");
752
      }
753
    if (mandatory.equals(SRPRegistry.OPTION_CONFIDENTIALITY))
754
      {
755
        if (! confidentiality)
756
          throw new AuthenticationException(
757
              "Confidentiality is mandatory but was not chosen");
758
      }
759
    int blockSize = 0;
760
    if (chosenConfidentialityAlgorithm != null)
761
      {
762
        final IBlockCipher cipher = CipherFactory.getInstance(chosenConfidentialityAlgorithm);
763
        if (cipher != null)
764
          blockSize = cipher.defaultBlockSize();
765
        else // should not happen
766
          throw new AuthenticationException("Confidentiality algorithm ("
767
                                            + chosenConfidentialityAlgorithm
768
                                            + ") not available");
769
      }
770
    sIV = new byte[blockSize];
771
    if (blockSize > 0)
772
      getDefaultPRNG().nextBytes(sIV);
773
  }
774
 
775
  private void setupSecurityServices(final boolean newSession)
776
      throws SaslException
777
  {
778
    complete = true; // signal end of authentication phase
779
    if (newSession)
780
      {
781
        outCounter = inCounter = 0;
782
        // instantiate cipher if confidentiality protection filter is active
783
        if (chosenConfidentialityAlgorithm != null)
784
          {
785
            if (Configuration.DEBUG)
786
              log.fine("Activating confidentiality protection filter");
787
            inCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
788
            outCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
789
          }
790
        // instantiate hmacs if integrity protection filter is active
791
        if (chosenIntegrityAlgorithm != null)
792
          {
793
            if (Configuration.DEBUG)
794
              log.fine("Activating integrity protection filter");
795
            inMac = IALG.getInstance(chosenIntegrityAlgorithm);
796
            outMac = IALG.getInstance(chosenIntegrityAlgorithm);
797
          }
798
        // generate a new sid if at least integrity is used
799
        sid = (inMac != null ? ServerStore.getNewSessionID() : new byte[0]);
800
      }
801
    else // same session new keys
802
      K = srp.generateKn(K, cn, sn);
803
 
804
    final KDF kdf = KDF.getInstance(K);
805
    // initialise in/out ciphers if confidentaility protection is used
806
    if (inCipher != null)
807
      {
808
        outCipher.init(kdf, sIV, Direction.FORWARD);
809
        inCipher.init(kdf, cIV, Direction.REVERSED);
810
      }
811
    // initialise in/out macs if integrity protection is used
812
    if (inMac != null)
813
      {
814
        outMac.init(kdf);
815
        inMac.init(kdf);
816
      }
817
    if (sid != null && sid.length != 0)
818
      { // update the security context and save in map
819
        if (Configuration.DEBUG)
820
          log.fine("Updating security context for sid = " + new String(sid));
821
        ServerStore.instance().cacheSession(ttl,
822
                                            new SecurityContext(srp.getAlgorithm(),
823
                                                                sid,
824
                                                                K,
825
                                                                cIV,
826
                                                                sIV,
827
                                                                replayDetection,
828
                                                                inCounter,
829
                                                                outCounter,
830
                                                                inMac, outMac,
831
                                                                inCipher,
832
                                                                outCipher));
833
      }
834
  }
835
 
836
  private PRNG getDefaultPRNG()
837
  {
838
    if (prng == null)
839
      prng = PRNG.getInstance();
840
    return prng;
841
  }
842
}

powered by: WebSVN 2.1.0

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