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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* UMac32.java --
2
   Copyright (C) 2001, 2002, 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.mac;
40
 
41
import gnu.java.security.Registry;
42
import gnu.java.security.prng.IRandom;
43
import gnu.java.security.prng.LimitReachedException;
44
import gnu.java.security.util.Util;
45
import gnu.javax.crypto.cipher.CipherFactory;
46
import gnu.javax.crypto.cipher.IBlockCipher;
47
import gnu.javax.crypto.prng.UMacGenerator;
48
 
49
import java.io.UnsupportedEncodingException;
50
import java.math.BigInteger;
51
import java.security.InvalidKeyException;
52
import java.util.HashMap;
53
import java.util.Map;
54
 
55
/**
56
 * The implementation of the <i>UMAC</i> (Universal Message Authentication
57
 * Code).
58
 * <p>
59
 * The <i>UMAC</i> algorithms described are <i>parameterized</i>. This means
60
 * that various low-level choices, like the endian convention and the underlying
61
 * cryptographic primitive, have not been fixed. One must choose values for
62
 * these parameters before the authentication tag generated by <i>UMAC</i> (for
63
 * a given message, key, and nonce) becomes fully-defined. In this document we
64
 * provide two collections of parameter settings, and have named the sets
65
 * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based
66
 * on experimentation and provide good performance on a wide variety of
67
 * processors. <i>UMAC16</i> is designed to excel on processors which provide
68
 * small-scale SIMD parallelism of the type found in Intel's MMX and Motorola's
69
 * AltiVec instruction sets, while <i>UMAC32</i> is designed to do well on
70
 * processors with good 32- and 64- bit support. <i>UMAC32</i> may take
71
 * advantage of SIMD parallelism in future processors.
72
 * <p>
73
 * <i>UMAC</i> has been designed to allow implementations which accommodate
74
 * <i>on-line</i> authentication. This means that pieces of the message may be
75
 * presented to <i>UMAC</i> at different times (but in correct order) and an
76
 * on-line implementation will be able to process the message correctly without
77
 * the need to buffer more than a few dozen bytes of the message. For
78
 * simplicity, the algorithms in this specification are presented as if the
79
 * entire message being authenticated were available at once.
80
 * <p>
81
 * To authenticate a message, <code>Msg</code>, one first applies the
82
 * universal hash function, resulting in a string which is typically much
83
 * shorter than the original message. The pseudorandom function is applied to a
84
 * nonce, and the result is used in the manner of a Vernam cipher: the
85
 * authentication tag is the xor of the output from the hash function and the
86
 * output from the pseudorandom function. Thus, an authentication tag is
87
 * generated as
88
 * <pre>
89
 *     AuthTag = f(Nonce) xor h(Msg)
90
 * </pre>
91
 * <p>
92
 * Here <code>f</code> is the pseudorandom function shared between the sender
93
 * and the receiver, and h is a universal hash function shared by the sender and
94
 * the receiver. In <i>UMAC</i>, a shared key is used to key the pseudorandom
95
 * function <code>f</code>, and then <code>f</code> is used for both tag
96
 * generation and internally to generate all of the bits needed by the universal
97
 * hash function.
98
 * <p>
99
 * The universal hash function that we use is called <code>UHASH</code>. It
100
 * combines several software-optimized algorithms into a multi-layered
101
 * structure. The algorithm is moderately complex. Some of this complexity comes
102
 * from extensive speed optimizations.
103
 * <p>
104
 * For the pseudorandom function we use the block cipher of the <i>Advanced
105
 * Encryption Standard</i> (AES).
106
 * <p>
107
 * The UMAC32 parameters, considered in this implementation are:
108
 * <pre>
109
 *                                    UMAC32
110
 *                                    ------
111
 *         WORD-LEN                        4
112
 *         UMAC-OUTPUT-LEN                 8
113
 *         L1-KEY-LEN                   1024
114
 *         UMAC-KEY-LEN                   16
115
 *         ENDIAN-FAVORITE               BIG *
116
 *         L1-OPERATIONS-SIGN       UNSIGNED
117
 * </pre>
118
 * <p>
119
 * Please note that this UMAC32 differs from the one described in the paper by
120
 * the <i>ENDIAN-FAVORITE</i> value.
121
 * <p>
122
 * References:
123
 * <ol>
124
 * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
125
 * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
126
 * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
127
 * </ol>
128
 */
129
public class UMac32
130
    extends BaseMac
131
{
132
  /**
133
   * Property name of the user-supplied <i>Nonce</i>. The value associated to
134
   * this property name is taken to be a byte array.
135
   */
136
  public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material";
137
  /** Known test vector. */
138
  // private static final String TV1 = "3E5A0E09198B0F94";
139
  // private static final String TV1 = "5FD764A6D3A9FD9D";
140
  // private static final String TV1 = "48658DE1D9A70304";
141
  private static final String TV1 = "455ED214A6909F20";
142
  private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8);
143
  // UMAC32 parameters
144
  static final int OUTPUT_LEN = 8;
145
  static final int L1_KEY_LEN = 1024;
146
  static final int KEY_LEN = 16;
147
  /** caches the result of the correctness test, once executed. */
148
  private static Boolean valid;
149
  private byte[] nonce;
150
  private UHash32 uhash32;
151
  private BigInteger nonceReuseCount;
152
  /** The authentication key for this instance. */
153
  private transient byte[] K;
154
 
155
  /** Trivial 0-arguments constructor. */
156
  public UMac32()
157
  {
158
    super("umac32");
159
  }
160
 
161
  /**
162
   * Private constructor for cloning purposes.
163
   *
164
   * @param that the instance to clone.
165
   */
166
  private UMac32(UMac32 that)
167
  {
168
    this();
169
 
170
    if (that.K != null)
171
      this.K = (byte[]) that.K.clone();
172
    if (that.nonce != null)
173
      this.nonce = (byte[]) that.nonce.clone();
174
    if (that.uhash32 != null)
175
      this.uhash32 = (UHash32) that.uhash32.clone();
176
    this.nonceReuseCount = that.nonceReuseCount;
177
  }
178
 
179
  public Object clone()
180
  {
181
    return new UMac32(this);
182
  }
183
 
184
  public int macSize()
185
  {
186
    return OUTPUT_LEN;
187
  }
188
 
189
  /**
190
   * Initialising a <i>UMAC</i> instance consists of defining values for the
191
   * following parameters:
192
   * <ol>
193
   * <li>Key Material: as the value of the attribute entry keyed by
194
   * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array
195
   * containing the user-specified key material. The length of this array,
196
   * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li>
197
   * <li>Nonce Material: as the value of the attribute entry keyed by
198
   * {@link #NONCE_MATERIAL}. The value is taken to be a byte array containing
199
   * the user-specified nonce material. The length of this array, if/when
200
   * defined SHOULD be (a) greater than zero, and (b) less or equal to 16 (the
201
   * size of the AES block).</li>
202
   * </ol>
203
   * <p>
204
   * For convenience, this implementation accepts that not both parameters be
205
   * always specified.
206
   * <ul>
207
   * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i>
208
   * is not, then this implementation, re-uses the previously set <i>Nonce
209
   * Material</i> after (a) converting the bytes to an unsigned integer, (b)
210
   * incrementing the number by one, and (c) converting it back to 16 bytes.</li>
211
   * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i>
212
   * is not, then this implementation re-uses the previously set <i>Key Material</i>.
213
   * </li>
214
   * </ul>
215
   * <p>
216
   * This method throws an exception if no <i>Key Material</i> is specified in
217
   * the input map, and there is no previously set/defined <i>Key Material</i>
218
   * (from an earlier invocation of this method). If a <i>Key Material</i> can
219
   * be used, but no <i>Nonce Material</i> is defined or previously
220
   * set/defined, then a default value of all-zeroes shall be used.
221
   *
222
   * @param attributes one or both of required parameters.
223
   * @throws InvalidKeyException the key material specified is not of the
224
   *           correct length.
225
   */
226
  public void init(Map attributes) throws InvalidKeyException,
227
      IllegalStateException
228
  {
229
    byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL);
230
    byte[] n = (byte[]) attributes.get(NONCE_MATERIAL);
231
    boolean newKey = (key != null);
232
    boolean newNonce = (n != null);
233
    if (newKey)
234
      {
235
        if (key.length != KEY_LEN)
236
          throw new InvalidKeyException("Key length: "
237
                                        + String.valueOf(key.length));
238
        K = key;
239
      }
240
    else
241
      {
242
        if (K == null)
243
          throw new InvalidKeyException("Null Key");
244
      }
245
    if (newNonce)
246
      {
247
        if (n.length < 1 || n.length > 16)
248
          throw new IllegalArgumentException("Invalid Nonce length: "
249
                                             + String.valueOf(n.length));
250
        if (n.length < 16) // pad with zeroes
251
          {
252
            byte[] newN = new byte[16];
253
            System.arraycopy(n, 0, newN, 0, n.length);
254
            nonce = newN;
255
          }
256
        else
257
          nonce = n;
258
 
259
        nonceReuseCount = BigInteger.ZERO;
260
      }
261
    else if (nonce == null) // use all-0 nonce if 1st time
262
      {
263
        nonce = new byte[16];
264
        nonceReuseCount = BigInteger.ZERO;
265
      }
266
    else if (! newKey) // increment nonce if still below max count
267
      {
268
        nonceReuseCount = nonceReuseCount.add(BigInteger.ONE);
269
        if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0)
270
          {
271
            // limit reached. we SHOULD have a key
272
            throw new InvalidKeyException("Null Key and unusable old Nonce");
273
          }
274
        BigInteger N = new BigInteger(1, nonce);
275
        N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS);
276
        n = N.toByteArray();
277
        if (n.length == 16)
278
          nonce = n;
279
        else if (n.length < 16)
280
          {
281
            nonce = new byte[16];
282
            System.arraycopy(n, 0, nonce, 16 - n.length, n.length);
283
          }
284
        else
285
          {
286
            nonce = new byte[16];
287
            System.arraycopy(n, n.length - 16, nonce, 0, 16);
288
          }
289
      }
290
    else // do nothing, re-use old nonce value
291
      nonceReuseCount = BigInteger.ZERO;
292
 
293
    if (uhash32 == null)
294
      uhash32 = new UHash32();
295
 
296
    Map map = new HashMap();
297
    map.put(MAC_KEY_MATERIAL, K);
298
    uhash32.init(map);
299
  }
300
 
301
  public void update(byte b)
302
  {
303
    uhash32.update(b);
304
  }
305
 
306
  public void update(byte[] b, int offset, int len)
307
  {
308
    uhash32.update(b, offset, len);
309
  }
310
 
311
  public byte[] digest()
312
  {
313
    byte[] result = uhash32.digest();
314
    byte[] pad = pdf(); // pdf(K, nonce);
315
    for (int i = 0; i < OUTPUT_LEN; i++)
316
      result[i] = (byte)(result[i] ^ pad[i]);
317
 
318
    return result;
319
  }
320
 
321
  public void reset()
322
  {
323
    if (uhash32 != null)
324
      uhash32.reset();
325
  }
326
 
327
  public boolean selfTest()
328
  {
329
    if (valid == null)
330
      {
331
        byte[] key;
332
        try
333
          {
334
            key = "abcdefghijklmnop".getBytes("ASCII");
335
          }
336
        catch (UnsupportedEncodingException x)
337
          {
338
            throw new RuntimeException("ASCII not supported");
339
          }
340
        byte[] nonce = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
341
        UMac32 mac = new UMac32();
342
        Map attributes = new HashMap();
343
        attributes.put(MAC_KEY_MATERIAL, key);
344
        attributes.put(NONCE_MATERIAL, nonce);
345
        try
346
          {
347
            mac.init(attributes);
348
          }
349
        catch (InvalidKeyException x)
350
          {
351
            x.printStackTrace(System.err);
352
            return false;
353
          }
354
        byte[] data = new byte[128];
355
        data[0] = (byte) 0x80;
356
        mac.update(data, 0, 128);
357
        byte[] result = mac.digest();
358
        valid = Boolean.valueOf(TV1.equals(Util.toString(result)));
359
      }
360
    return valid.booleanValue();
361
  }
362
 
363
  /**
364
   * @return byte array of length 8 (or OUTPUT_LEN) bytes.
365
   */
366
  private byte[] pdf()
367
  {
368
    // Make Nonce 16 bytes by prepending zeroes. done (see init())
369
    // one AES invocation is enough for more than one PDF invocation
370
    // number of index bits needed = 1
371
    // Extract index bits and zero low bits of Nonce
372
    BigInteger Nonce = new BigInteger(1, nonce);
373
    int nlowbitsnum = Nonce.testBit(0) ? 1 : 0;
374
    Nonce = Nonce.clearBit(0);
375
    // Generate subkey, AES and extract indexed substring
376
    IRandom kdf = new UMacGenerator();
377
    Map map = new HashMap();
378
    map.put(IBlockCipher.KEY_MATERIAL, K);
379
    map.put(UMacGenerator.INDEX, Integer.valueOf(128));
380
    kdf.init(map);
381
    byte[] Kp = new byte[KEY_LEN];
382
    try
383
      {
384
        kdf.nextBytes(Kp, 0, KEY_LEN);
385
      }
386
    catch (IllegalStateException x)
387
      {
388
        x.printStackTrace(System.err);
389
        throw new RuntimeException(String.valueOf(x));
390
      }
391
    catch (LimitReachedException x)
392
      {
393
        x.printStackTrace(System.err);
394
        throw new RuntimeException(String.valueOf(x));
395
      }
396
    IBlockCipher aes = CipherFactory.getInstance(Registry.AES_CIPHER);
397
    map.put(IBlockCipher.KEY_MATERIAL, Kp);
398
    try
399
      {
400
        aes.init(map);
401
      }
402
    catch (InvalidKeyException x)
403
      {
404
        x.printStackTrace(System.err);
405
        throw new RuntimeException(String.valueOf(x));
406
      }
407
    catch (IllegalStateException x)
408
      {
409
        x.printStackTrace(System.err);
410
        throw new RuntimeException(String.valueOf(x));
411
      }
412
    byte[] T = new byte[16];
413
    aes.encryptBlock(nonce, 0, T, 0);
414
    byte[] result = new byte[OUTPUT_LEN];
415
    System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN);
416
    return result;
417
  }
418
}

powered by: WebSVN 2.1.0

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