View | Details | Return to bug 26067 | Differences between
and this patch

Collapse All | Expand All

(-)BaseMac.java (-32 / +11 lines)
Lines 40-74 Link Here
40
40
41
import gnu.java.security.hash.IMessageDigest;
41
import gnu.java.security.hash.IMessageDigest;
42
42
43
import java.util.Map;
44
import java.security.InvalidKeyException;
43
import java.security.InvalidKeyException;
44
import java.util.Map;
45
45
46
/**
46
/**
47
 * <p>A base abstract class to facilitate <i>MAC</i> (Message Authentication
47
 * A base abstract class to facilitate <i>MAC</i> (Message Authentication Code)
48
 * Code) implementations.</p>
48
 * implementations.
49
 */
49
 */
50
public abstract class BaseMac implements IMac
50
public abstract class BaseMac
51
    implements IMac
51
{
52
{
52
53
  // Constants and variables
54
  // -------------------------------------------------------------------------
55
56
  /** The canonical name prefix of the <i>MAC</i>. */
53
  /** The canonical name prefix of the <i>MAC</i>. */
57
  protected String name;
54
  protected String name;
58
59
  /** Reference to the underlying hash algorithm instance. */
55
  /** Reference to the underlying hash algorithm instance. */
60
  protected IMessageDigest underlyingHash;
56
  protected IMessageDigest underlyingHash;
61
62
  /** The length of the truncated output in bytes. */
57
  /** The length of the truncated output in bytes. */
63
  protected int truncatedSize;
58
  protected int truncatedSize;
64
59
65
  /** The authentication key for this instance. */
66
  //   protected transient byte[] K;
67
  // Constructor(s)
68
  // -------------------------------------------------------------------------
69
  /**
60
  /**
70
   * <p>Trivial constructor for use by concrete subclasses.</p>
61
   * Trivial constructor for use by concrete subclasses.
71
   *
62
   * 
72
   * @param name the canonical name of this instance.
63
   * @param name the canonical name of this instance.
73
   */
64
   */
74
  protected BaseMac(String name)
65
  protected BaseMac(String name)
Lines 79-86 Link Here
79
  }
70
  }
80
71
81
  /**
72
  /**
82
   * <p>Trivial constructor for use by concrete subclasses.</p>
73
   * Trivial constructor for use by concrete subclasses.
83
   *
74
   * 
84
   * @param name the canonical name of this instance.
75
   * @param name the canonical name of this instance.
85
   * @param underlyingHash the underlying message digest algorithm instance.
76
   * @param underlyingHash the underlying message digest algorithm instance.
86
   */
77
   */
Lines 89-108 Link Here
89
    this(name);
80
    this(name);
90
81
91
    if (underlyingHash != null)
82
    if (underlyingHash != null)
92
      {
83
      truncatedSize = underlyingHash.hashSize();
93
        truncatedSize = underlyingHash.hashSize();
94
      }
95
    this.underlyingHash = underlyingHash;
84
    this.underlyingHash = underlyingHash;
96
  }
85
  }
97
86
98
  // Class methods
99
  // -------------------------------------------------------------------------
100
101
  // Instance methods
102
  // -------------------------------------------------------------------------
103
104
  // gnu.crypto.mac.IMac interface implementation ----------------------------
105
106
  public String name()
87
  public String name()
107
  {
88
  {
108
    return name;
89
    return name;
Lines 137-148 Link Here
137
    return result;
118
    return result;
138
  }
119
  }
139
120
140
  // methods to be implemented by concrete subclasses ------------------------
141
142
  public abstract void init(Map attributes) throws InvalidKeyException,
121
  public abstract void init(Map attributes) throws InvalidKeyException,
143
      IllegalStateException;
122
      IllegalStateException;
144
123
145
  public abstract byte[] digest();
124
  public abstract byte[] digest();
146
125
147
  public abstract boolean selfTest();
126
  public abstract boolean selfTest();
148
}
127
}
(-)HMac.java (-130 / +65 lines)
Lines 48-117 Link Here
48
import java.util.Map;
48
import java.util.Map;
49
49
50
/**
50
/**
51
 * <p>The implementation of the <i>HMAC</i> (Keyed-Hash Message Authentication
51
 * The implementation of the <i>HMAC</i> (Keyed-Hash Message Authentication
52
 * Code).</p>
52
 * Code).
53
 *
53
 * <p>
54
 * <p><i>HMAC</i> can be used in combination with any iterated cryptographic
54
 * <i>HMAC</i> can be used in combination with any iterated cryptographic hash
55
 * hash function. <i>HMAC</i> also uses a <i>secret key</i> for calculation and
55
 * function. <i>HMAC</i> also uses a <i>secret key</i> for calculation and
56
 * verification of the message authentication values. The main goals behind this
56
 * verification of the message authentication values. The main goals behind this
57
 * construction are</p>
57
 * construction are:
58
 *
59
 * <ul>
58
 * <ul>
60
 *    <li>To use, without modifications, available hash functions. In
59
 * <li>To use, without modifications, available hash functions. In particular,
61
 *    particular, hash functions that perform well in software, and for which
60
 * hash functions that perform well in software, and for which code is freely
62
 *    code is freely and widely available.</li>
61
 * and widely available.</li>
63
 *
62
 * <li>To preserve the original performance of the hash function without
64
 *    <li>To preserve the original performance of the hash function without
63
 * incurring a significant degradation.</li>
65
 *    incurring a significant degradation.</li>
64
 * <li>To use and handle keys in a simple way.</li>
66
 *
65
 * <li>To have a well understood cryptographic analysis of the strength of the
67
 *    <li>To use and handle keys in a simple way.</li>
66
 * authentication mechanism based on reasonable assumptions on the underlying
68
 *
67
 * hash function.</li>
69
 *    <li>To have a well understood cryptographic analysis of the strength of
68
 * <li>To allow for easy replaceability of the underlying hash function in case
70
 *    the authentication mechanism based on reasonable assumptions on the
69
 * that faster or more secure hash functions are found or required.</li>
71
 *    underlying hash function.</li>
72
 *
73
 *    <li>To allow for easy replaceability of the underlying hash function in
74
 *    case that faster or more secure hash functions are found or required.</li>
75
 * </ul>
70
 * </ul>
76
 *
71
 * <p>
77
 * <p>References:</p>
72
 * References:
78
 *
79
 * <ol>
73
 * <ol>
80
 *    <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
74
 * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
81
 *    Keyed-Hashing for Message Authentication.<br>
75
 * Keyed-Hashing for Message Authentication.<br>
82
 *    H. Krawczyk, M. Bellare, and R. Canetti.</li>
76
 * H. Krawczyk, M. Bellare, and R. Canetti.</li>
83
 * </ol>
77
 * </ol>
84
 */
78
 */
85
public class HMac extends BaseMac implements Cloneable
79
public class HMac
80
    extends BaseMac
81
    implements Cloneable
86
{
82
{
87
88
  // Constants and variables
89
  // -------------------------------------------------------------------------
90
91
  public static final String USE_WITH_PKCS5_V2 = "gnu.crypto.hmac.pkcs5";
83
  public static final String USE_WITH_PKCS5_V2 = "gnu.crypto.hmac.pkcs5";
92
93
  private static final byte IPAD_BYTE = 0x36;
84
  private static final byte IPAD_BYTE = 0x36;
94
95
  private static final byte OPAD_BYTE = 0x5C;
85
  private static final byte OPAD_BYTE = 0x5C;
96
97
  /** caches the result of the correctness test, once executed. */
86
  /** caches the result of the correctness test, once executed. */
98
  private static Boolean valid;
87
  private static Boolean valid;
99
100
  protected int macSize;
88
  protected int macSize;
101
102
  protected int blockSize;
89
  protected int blockSize;
103
104
  protected IMessageDigest ipadHash;
90
  protected IMessageDigest ipadHash;
105
106
  protected IMessageDigest opadHash;
91
  protected IMessageDigest opadHash;
107
108
  protected byte[] ipad;
92
  protected byte[] ipad;
109
93
110
  // Constructor(s)
111
  // -------------------------------------------------------------------------
112
113
  /**
94
  /**
114
   * <p>Trivial constructor for use by concrete subclasses.</p>
95
   * Trivial constructor for use by concrete subclasses.
115
   *
96
   *
116
   * @param underlyingHash the underlying hash algorithm instance.
97
   * @param underlyingHash the underlying hash algorithm instance.
117
   */
98
   */
Lines 124-137 Link Here
124
    ipadHash = opadHash = null;
105
    ipadHash = opadHash = null;
125
  }
106
  }
126
107
127
  // Class methods
128
  // -------------------------------------------------------------------------
129
130
  // Instance methods
131
  // -------------------------------------------------------------------------
132
133
  // java.lang.Cloneable interface implementation ----------------------------
134
135
  public Object clone() throws CloneNotSupportedException
108
  public Object clone() throws CloneNotSupportedException
136
  {
109
  {
137
    HMac result = (HMac) super.clone();
110
    HMac result = (HMac) super.clone();
Lines 145-232 Link Here
145
    return result;
118
    return result;
146
  }
119
  }
147
120
148
  // implementation of abstract methods in BaseMac ---------------------------
149
150
  public void init(Map attributes) throws InvalidKeyException,
121
  public void init(Map attributes) throws InvalidKeyException,
151
      IllegalStateException
122
      IllegalStateException
152
  {
123
  {
153
    Integer ts = (Integer) attributes.get(TRUNCATED_SIZE);
124
    Integer ts = (Integer) attributes.get(TRUNCATED_SIZE);
154
    truncatedSize = (ts == null ? macSize : ts.intValue());
125
    truncatedSize = (ts == null ? macSize : ts.intValue());
155
    if (truncatedSize < (macSize / 2))
126
    if (truncatedSize < (macSize / 2))
156
      {
127
      throw new IllegalArgumentException("Truncated size too small");
157
        throw new IllegalArgumentException("Truncated size too small");
158
      }
159
    else if (truncatedSize < 10)
128
    else if (truncatedSize < 10)
160
      {
129
      throw new IllegalArgumentException("Truncated size less than 80 bits");
161
        throw new IllegalArgumentException("Truncated size less than 80 bits");
162
      }
163
130
164
    // we dont use/save the key outside this method
131
    // we dont use/save the key outside this method
165
    byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
132
    byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
166
    if (K == null)
133
    if (K == null)
167
      { // take it as an indication to re-use previous key if set
134
      { // take it as an indication to re-use previous key if set
168
        if (ipadHash == null)
135
        if (ipadHash == null)
169
          {
136
          throw new InvalidKeyException("Null key");
170
            throw new InvalidKeyException("Null key");
171
          }
172
        // we already went through the motions; ie. up to step #4.  re-use
137
        // we already went through the motions; ie. up to step #4.  re-use
173
        underlyingHash = (IMessageDigest) ipadHash.clone();
138
        underlyingHash = (IMessageDigest) ipadHash.clone();
174
        return;
139
        return;
175
      }
140
      }
176
141
177
    // for HMACs used in key-derivation functions (e.g. PBKDF2) the key
142
    // for HMACs used in key-derivation functions (e.g. PBKDF2) the key material
178
    // material need not be >= the (output) block size of the underlying
143
    // need not be >= the (output) block size of the underlying algorithm
179
    // algorithm
180
    Boolean pkcs5 = (Boolean) attributes.get(USE_WITH_PKCS5_V2);
144
    Boolean pkcs5 = (Boolean) attributes.get(USE_WITH_PKCS5_V2);
181
    if (pkcs5 == null)
145
    if (pkcs5 == null)
182
      {
146
      pkcs5 = Boolean.FALSE;
183
        pkcs5 = Boolean.FALSE;
147
    if (K.length < macSize && ! pkcs5.booleanValue())
184
      }
148
      throw new InvalidKeyException("Key too short");
185
    if (K.length < macSize && !pkcs5.booleanValue())
186
      {
187
        throw new InvalidKeyException("Key too short");
188
      }
189
149
190
    if (K.length > blockSize)
150
    if (K.length > blockSize)
191
      {
151
      {
192
        // (0) replace K with HASH(K) if K is larger than the hash's
152
        // (0) replace K with HASH(K) if K is larger than the hash's block size.
193
        //     block size. Then pad with zeros until it is the correct
153
        //     Then pad with zeros until it is the correct size (the next `if').
194
        //     size (the next `if').
195
        underlyingHash.update(K, 0, K.length);
154
        underlyingHash.update(K, 0, K.length);
196
        K = underlyingHash.digest();
155
        K = underlyingHash.digest();
197
      }
156
      }
198
    if (K.length < blockSize)
157
    if (K.length < blockSize)
199
      {
158
      {
200
        // (1) append zeros to the end of K to create a B byte string
159
        // (1) append zeros to the end of K to create a B byte string (e.g., if
201
        //     (e.g., if K is of length 20 bytes and B=64, then K will be
160
        //     K is of length 20 bytes and B=64, then K will be appended with 44
202
        //     appended with 44 zero bytes 0x00)
161
        //     zero bytes 0x00)
203
        int limit = (K.length > blockSize) ? blockSize : K.length;
162
        int limit = (K.length > blockSize) ? blockSize : K.length;
204
        byte[] newK = new byte[blockSize];
163
        byte[] newK = new byte[blockSize];
205
        System.arraycopy(K, 0, newK, 0, limit);
164
        System.arraycopy(K, 0, newK, 0, limit);
206
        K = newK;
165
        K = newK;
207
      }
166
      }
208
209
    underlyingHash.reset();
167
    underlyingHash.reset();
210
    opadHash = (IMessageDigest) underlyingHash.clone();
168
    opadHash = (IMessageDigest) underlyingHash.clone();
211
    if (ipad == null)
169
    if (ipad == null)
212
      {
170
      ipad = new byte[blockSize];
213
        ipad = new byte[blockSize];
171
    // (2) XOR (bitwise exclusive-OR) the B byte string computed in step (1)
214
      }
172
    //     with ipad
215
    // (2) XOR (bitwise exclusive-OR) the B byte string computed in step
173
    // (3) append the stream of data 'text' to the B byte string resulting from
216
    //     (1) with ipad
174
    //     step (2)
217
    // (3) append the stream of data 'text' to the B byte string resulting
218
    //     from step (2)
219
    // (4) apply H to the stream generated in step (3)
175
    // (4) apply H to the stream generated in step (3)
220
    for (int i = 0; i < blockSize; i++)
176
    for (int i = 0; i < blockSize; i++)
221
      {
177
      ipad[i] = (byte)(K[i] ^ IPAD_BYTE);
222
        //         underlyingHash.update((byte)(K[i] ^ IPAD_BYTE));
223
        ipad[i] = (byte) (K[i] ^ IPAD_BYTE);
224
      }
225
    for (int i = 0; i < blockSize; i++)
178
    for (int i = 0; i < blockSize; i++)
226
      {
179
      opadHash.update((byte)(K[i] ^ OPAD_BYTE));
227
        opadHash.update((byte) (K[i] ^ OPAD_BYTE));
228
      }
229
230
    underlyingHash.update(ipad, 0, blockSize);
180
    underlyingHash.update(ipad, 0, blockSize);
231
    ipadHash = (IMessageDigest) underlyingHash.clone();
181
    ipadHash = (IMessageDigest) underlyingHash.clone();
232
    K = null;
182
    K = null;
Lines 245-272 Link Here
245
  public byte[] digest()
195
  public byte[] digest()
246
  {
196
  {
247
    if (ipadHash == null)
197
    if (ipadHash == null)
248
      {
198
      throw new IllegalStateException("HMAC not initialised");
249
        throw new IllegalStateException("HMAC not initialised");
250
      }
251
252
    byte[] out = underlyingHash.digest();
199
    byte[] out = underlyingHash.digest();
253
    // (5) XOR (bitwise exclusive-OR) the B byte string computed in
200
    // (5) XOR (bitwise exclusive-OR) the B byte string computed in step (1)
254
    //     step (1) with opad
201
    //     with opad
255
    underlyingHash = (IMessageDigest) opadHash.clone();
202
    underlyingHash = (IMessageDigest) opadHash.clone();
256
    // (6) append the H result from step (4) to the B byte string
203
    // (6) append the H result from step (4) to the B byte string resulting from
257
    //     resulting from step (5)
204
    //     step (5)
258
    underlyingHash.update(out, 0, macSize);
205
    underlyingHash.update(out, 0, macSize);
259
    // (7) apply H to the stream generated in step (6) and output
206
    // (7) apply H to the stream generated in step (6) and output the result
260
    //     the result
261
    out = underlyingHash.digest(); // which also resets the underlying hash
207
    out = underlyingHash.digest(); // which also resets the underlying hash
262
263
    // truncate and return
208
    // truncate and return
264
    if (truncatedSize == macSize)
209
    if (truncatedSize == macSize)
265
      return out;
210
      return out;
266
267
    byte[] result = new byte[truncatedSize];
211
    byte[] result = new byte[truncatedSize];
268
    System.arraycopy(out, 0, result, 0, truncatedSize);
212
    System.arraycopy(out, 0, result, 0, truncatedSize);
269
270
    return result;
213
    return result;
271
  }
214
  }
272
215
Lines 279-309 Link Here
279
            IMac mac = new HMac(new MD5()); // use rfc-2104 test vectors
222
            IMac mac = new HMac(new MD5()); // use rfc-2104 test vectors
280
            String tv1 = "9294727A3638BB1C13F48EF8158BFC9D";
223
            String tv1 = "9294727A3638BB1C13F48EF8158BFC9D";
281
            String tv3 = "56BE34521D144C88DBB8C733F0E8B3F6";
224
            String tv3 = "56BE34521D144C88DBB8C733F0E8B3F6";
282
            byte[] k1 = new byte[] { 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
225
            byte[] k1 = new byte[] {
283
                                    0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
226
                0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
284
                                    0x0B, 0x0B };
227
                0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B };
285
            byte[] k3 = new byte[] { (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
228
            byte[] k3 = new byte[] {
286
                                    (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
229
                (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
287
                                    (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
230
                (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
288
                                    (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
231
                (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
289
                                    (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
232
                (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA };
290
                                    (byte) 0xAA };
291
            byte[] data = new byte[50];
233
            byte[] data = new byte[50];
292
            for (int i = 0; i < 50;)
234
            for (int i = 0; i < 50;)
293
              {
235
              data[i++] = (byte) 0xDD;
294
                data[i++] = (byte) 0xDD;
295
              }
296
236
297
            HashMap map = new HashMap();
237
            HashMap map = new HashMap();
298
299
            // test vector #1
238
            // test vector #1
300
            map.put(MAC_KEY_MATERIAL, k1);
239
            map.put(MAC_KEY_MATERIAL, k1);
301
            mac.init(map);
240
            mac.init(map);
302
            mac.update("Hi There".getBytes("ASCII"), 0, 8);
241
            mac.update("Hi There".getBytes("ASCII"), 0, 8);
303
            if (!tv1.equals(Util.toString(mac.digest())))
242
            if (! tv1.equals(Util.toString(mac.digest())))
304
              {
243
              valid = Boolean.FALSE;
305
                valid = Boolean.FALSE;
306
              }
307
244
308
            // test #2 is not used since it causes a "Key too short" exception
245
            // test #2 is not used since it causes a "Key too short" exception
309
246
Lines 311-320 Link Here
311
            map.put(MAC_KEY_MATERIAL, k3);
248
            map.put(MAC_KEY_MATERIAL, k3);
312
            mac.init(map);
249
            mac.init(map);
313
            mac.update(data, 0, 50);
250
            mac.update(data, 0, 50);
314
            if (!tv3.equals(Util.toString(mac.digest())))
251
            if (! tv3.equals(Util.toString(mac.digest())))
315
              {
252
              valid = Boolean.FALSE;
316
                valid = Boolean.FALSE;
317
              }
318
            valid = Boolean.TRUE;
253
            valid = Boolean.TRUE;
319
          }
254
          }
320
        catch (Exception x)
255
        catch (Exception x)
(-)HMacFactory.java (-41 / +24 lines)
Lines 47-114 Link Here
47
import java.util.Set;
47
import java.util.Set;
48
48
49
/**
49
/**
50
 * <p>A <i>Factory</i> to instantiate Keyed-Hash Message Authentication Code
50
 * A <i>Factory</i> to instantiate Keyed-Hash Message Authentication Code
51
 * (HMAC) algorithm instances.</p>
51
 * (HMAC) algorithm instances.
52
 */
52
 */
53
public class HMacFactory implements Registry
53
public class HMacFactory
54
    implements Registry
54
{
55
{
55
56
  // Constants and variables
57
  // -------------------------------------------------------------------------
58
59
  // Constructor(s)
60
  // -------------------------------------------------------------------------
61
62
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
56
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
63
  private HMacFactory()
57
  private HMacFactory()
64
  {
58
  {
65
    super();
59
    super();
66
  }
60
  }
67
61
68
  // Class methods
69
  // -------------------------------------------------------------------------
70
71
  /**
62
  /**
72
   * <p>Return an instance of a <i>HMAC</i> algorithm given the name of its
63
   * Return an instance of a <i>HMAC</i> algorithm given the name of its
73
   * underlying hash function, prefixed with the literal defined in
64
   * underlying hash function, prefixed with the literal defined in
74
   * {@link Registry#HMAC_NAME_PREFIX}.</p>
65
   * {@link Registry#HMAC_NAME_PREFIX}.
75
   *
66
   * 
76
   * @param name the fully qualified name of the underlying algorithm: composed
67
   * @param name the fully qualified name of the underlying algorithm: composed
77
   * as the concatenation of a literal prefix (see {@link Registry#HMAC_NAME_PREFIX})
68
   *          as the concatenation of a literal prefix (see
78
   * and the name of the underlying hash algorithm.
69
   *          {@link Registry#HMAC_NAME_PREFIX}) and the name of the underlying
79
   * @return an instance of the <i>HMAC</i> algorithm, or <code>null</code> if
70
   *          hash algorithm.
80
   * none can be constructed.
71
   * @return an instance of the <i>HMAC</i> algorithm, or <code>null</code>
72
   *         if none can be constructed.
81
   * @exception InternalError if the implementation does not pass its self-test.
73
   * @exception InternalError if the implementation does not pass its self-test.
82
   */
74
   */
83
  public static IMac getInstance(String name)
75
  public static IMac getInstance(String name)
84
  {
76
  {
85
    if (name == null)
77
    if (name == null)
86
      {
78
      return null;
87
        return null;
88
      }
89
79
90
    name = name.trim();
80
    name = name.trim();
91
    name = name.toLowerCase();
81
    name = name.toLowerCase();
92
    if (!name.startsWith(HMAC_NAME_PREFIX))
82
    if (! name.startsWith(HMAC_NAME_PREFIX))
93
      {
83
      return null;
94
        return null;
95
      }
96
84
97
    // strip the prefix
85
    // strip the prefix
98
    name = name.substring(HMAC_NAME_PREFIX.length()).trim();
86
    name = name.substring(HMAC_NAME_PREFIX.length()).trim();
99
    IMac result = new HMac(HashFactory.getInstance(name));
87
    IMac result = new HMac(HashFactory.getInstance(name));
100
    if (result != null && !result.selfTest())
88
    if (result != null && ! result.selfTest())
101
      {
89
      throw new InternalError(result.name());
102
        throw new InternalError(result.name());
103
      }
104
90
105
    return result;
91
    return result;
106
  }
92
  }
107
93
108
  /**
94
  /**
109
   * <p>Returns a {@link java.util.Set} of names of <i>HMAC</i> algorithms
95
   * <p>
110
   * supported by this <i>Factory</i>.</p>
96
   * Returns a {@link java.util.Set} of names of <i>HMAC</i> algorithms
111
   *
97
   * supported by this <i>Factory</i>.
98
   * </p>
99
   * 
112
   * @return a {@link java.util.Set} of HMAC algorithm names (Strings).
100
   * @return a {@link java.util.Set} of HMAC algorithm names (Strings).
113
   */
101
   */
114
  public static final Set getNames()
102
  public static final Set getNames()
Lines 116-128 Link Here
116
    Set hashNames = HashFactory.getNames();
104
    Set hashNames = HashFactory.getNames();
117
    HashSet hs = new HashSet();
105
    HashSet hs = new HashSet();
118
    for (Iterator it = hashNames.iterator(); it.hasNext();)
106
    for (Iterator it = hashNames.iterator(); it.hasNext();)
119
      {
107
      hs.add(HMAC_NAME_PREFIX + ((String) it.next()));
120
        hs.add(HMAC_NAME_PREFIX + ((String) it.next()));
121
      }
122
108
123
    return Collections.unmodifiableSet(hs);
109
    return Collections.unmodifiableSet(hs);
124
  }
110
  }
125
111
}
126
  // Instance methods
127
  // -------------------------------------------------------------------------
128
}
(-)IMac.java (-85 / +69 lines)
Lines 38-145 Link Here
38
38
39
package gnu.javax.crypto.mac;
39
package gnu.javax.crypto.mac;
40
40
41
import java.util.Map;
42
import java.security.InvalidKeyException;
41
import java.security.InvalidKeyException;
42
import java.util.Map;
43
43
44
/**
44
/**
45
 * <p>The basic visible methods of any MAC (Message Authentication Code)
45
 * The basic visible methods of any MAC (Message Authentication Code) algorithm.
46
 * algorithm.</p>
46
 * <p>
47
 *
47
 * A <i>MAC</i> provides a way to check the integrity of information
48
 * <p>A <i>MAC</i> provides a way to check the integrity of information
49
 * transmitted over, or stored in, an unreliable medium, based on a secret key.
48
 * transmitted over, or stored in, an unreliable medium, based on a secret key.
50
 * Typically, <i>MAC</i>s are used between two parties, that share a common
49
 * Typically, <i>MAC</i>s are used between two parties, that share a common
51
 * secret key, in order to validate information transmitted between them.</p>
50
 * secret key, in order to validate information transmitted between them.
52
 *
51
 * <p>
53
 * <p>When a <i>MAC</i> algorithm is based on a cryptographic hash function, it
52
 * When a <i>MAC</i> algorithm is based on a cryptographic hash function, it is
54
 * is then called to a <i>HMAC</i> (Hashed Message Authentication Code) --see
53
 * then called to a <i>HMAC</i> (Hashed Message Authentication Code) --see <a
55
 * <a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC-2104</a>.</p>
54
 * href="http://www.ietf.org/rfc/rfc-2104.txt">RFC-2104</a>.
56
 *
55
 * <p>
57
 * Another type of <i>MAC</i> algorithms exist: UMAC or <i>Universal Message
56
 * Another type of <i>MAC</i> algorithms exist: UMAC or <i>Universal Message
58
 * Authentication Code</i>, described in
57
 * Authentication Code</i>, described in <a
59
 * <a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
58
 * href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
60
 * draft-krovetz-umac-01.txt</a>.</p>
59
 * draft-krovetz-umac-01.txt</a>.
61
 *
60
 * <p>
62
 * <p>With <i>UMAC</i>s, the sender and receiver share a common secret key (the
61
 * With <i>UMAC</i>s, the sender and receiver share a common secret key (the
63
 * <i>MAC</i> key) which determines:</p>
62
 * <i>MAC</i> key) which determines:
64
 *
65
 * <ul>
63
 * <ul>
66
 *    <li>The key for a <i>universal hash function</i>. This hash function is
64
 * <li>The key for a <i>universal hash function</i>. This hash function is
67
 *    <i>non-cryptographic</i>, in the sense that it does not need to have any
65
 * <i>non-cryptographic</i>, in the sense that it does not need to have any
68
 *    cryptographic <i>hardness</i> property. Rather, it needs to satisfy some
66
 * cryptographic <i>hardness</i> property. Rather, it needs to satisfy some
69
 *    combinatorial property, which can be proven to hold without relying on
67
 * combinatorial property, which can be proven to hold without relying on
70
 *    unproven hardness assumptions.</li>
68
 * unproven hardness assumptions.</li>
71
 *
69
 * <li>The key for a <i>pseudorandom function</i>. This is where one needs a
72
 *    <li>The key for a <i>pseudorandom function</i>. This is where one needs a
70
 * cryptographic hardness assumption. The pseudorandom function may be obtained
73
 *    cryptographic hardness assumption. The pseudorandom function may be
71
 * from a <i>block cipher</i> or a <i>cryptographic hash function</i>. </li>
74
 *    obtained from a <i>block cipher</i> or a <i>cryptographic hash function</i>.
75
 *    </li>
76
 * </ul>
72
 * </ul>
77
 *
73
 * <p>
78
 * <p>References:</p>
74
 * References:
79
 *
80
 * <ol>
75
 * <ol>
81
 *    <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
76
 * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
82
 *    Keyed-Hashing for Message Authentication.<br>
77
 * Keyed-Hashing for Message Authentication.<br>
83
 *    H. Krawczyk, M. Bellare, and R. Canetti.</li>
78
 * H. Krawczyk, M. Bellare, and R. Canetti.</li>
84
 *
79
 * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
85
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
80
 * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
86
 *    UMAC</a>: Message Authentication Code using Universal Hashing.<br>
81
 * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
87
 *    T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
88
 * </ol>
82
 * </ol>
89
 */
83
 */
90
public interface IMac
84
public interface IMac
91
{
85
{
92
93
  // Constants
94
  // -------------------------------------------------------------------------
95
96
  /**
86
  /**
97
   * Property name of the user-supplied key material. The value associated to
87
   * Property name of the user-supplied key material. The value associated to
98
   * this property name is taken to be a byte array.
88
   * this property name is taken to be a byte array.
99
   */
89
   */
100
  String MAC_KEY_MATERIAL = "gnu.crypto.mac.key.material";
90
  String MAC_KEY_MATERIAL = "gnu.crypto.mac.key.material";
101
102
  /**
91
  /**
103
   * <p>Property name of the desired truncated output size in bytes. The value
92
   * Property name of the desired truncated output size in bytes. The value
104
   * associated to this property name is taken to be an integer. If no value
93
   * associated to this property name is taken to be an integer. If no value is
105
   * is specified in the attributes map at initialisation time, then all bytes
94
   * specified in the attributes map at initialisation time, then all bytes of
106
   * of the underlying hash algorithm's output are emitted.</p>
95
   * the underlying hash algorithm's output are emitted.
107
   *
96
   * <p>
108
   * <p>This implementation, follows the recommendation of the <i>RFC 2104</i>
97
   * This implementation, follows the recommendation of the <i>RFC 2104</i>
109
   * authors; specifically:</p>
98
   * authors; specifically:
110
   *
111
   * <pre>
99
   * <pre>
112
   *    We recommend that the output length t be not less than half the
100
   *     We recommend that the output length t be not less than half the
113
   *    length of the hash output (to match the birthday attack bound)
101
   *     length of the hash output (to match the birthday attack bound)
114
   *    and not less than 80 bits (a suitable lower bound on the number
102
   *     and not less than 80 bits (a suitable lower bound on the number
115
   *    of bits that need to be predicted by an attacker).
103
   *     of bits that need to be predicted by an attacker).
116
   * </pre>
104
   * </pre>
117
   */
105
   */
118
  String TRUNCATED_SIZE = "gnu.crypto.mac.truncated.size";
106
  String TRUNCATED_SIZE = "gnu.crypto.mac.truncated.size";
119
107
120
  // Methods
121
  // -------------------------------------------------------------------------
122
123
  /**
108
  /**
124
   * <p>Returns the canonical name of this algorithm.</p>
109
   * Returns the canonical name of this algorithm.
125
   *
110
   * 
126
   * @return the canonical name of this algorithm.
111
   * @return the canonical name of this algorithm.
127
   */
112
   */
128
  String name();
113
  String name();
129
114
130
  /**
115
  /**
131
   * <p>Returns the output length in bytes of this <i>MAC</i> algorithm.</p>
116
   * Returns the output length in bytes of this <i>MAC</i> algorithm.
132
   *
117
   * 
133
   * @return the output length in bytes of this <i>MAC</i> algorithm.
118
   * @return the output length in bytes of this <i>MAC</i> algorithm.
134
   */
119
   */
135
  int macSize();
120
  int macSize();
136
121
137
  /**
122
  /**
138
   * <p>Initialises the algorithm with designated attributes. Permissible names
123
   * Initialises the algorithm with designated attributes. Permissible names and
139
   * and values are described in the class documentation above.</p>
124
   * values are described in the class documentation above.
140
   *
125
   * 
141
   * @param attributes a set of name-value pairs that describe the desired
126
   * @param attributes a set of name-value pairs that describe the desired
142
   * future instance behaviour.
127
   *          future instance behaviour.
143
   * @exception InvalidKeyException if the key data is invalid.
128
   * @exception InvalidKeyException if the key data is invalid.
144
   * @exception IllegalStateException if the instance is already initialised.
129
   * @exception IllegalStateException if the instance is already initialised.
145
   * @see #MAC_KEY_MATERIAL
130
   * @see #MAC_KEY_MATERIAL
Lines 147-164 Link Here
147
  void init(Map attributes) throws InvalidKeyException, IllegalStateException;
132
  void init(Map attributes) throws InvalidKeyException, IllegalStateException;
148
133
149
  /**
134
  /**
150
   * <p>Continues a <i>MAC</i> operation using the input byte.</p>
135
   * Continues a <i>MAC</i> operation using the input byte.
151
   *
136
   * 
152
   * @param b the input byte to digest.
137
   * @param b the input byte to digest.
153
   */
138
   */
154
  void update(byte b);
139
  void update(byte b);
155
140
156
  /**
141
  /**
157
   * <p>Continues a <i>MAC</i> operation, by filling the buffer, processing
142
   * Continues a <i>MAC</i> operation, by filling the buffer, processing data
158
   * data in the algorithm's MAC_SIZE-bit block(s), updating the context and
143
   * in the algorithm's MAC_SIZE-bit block(s), updating the context and count,
159
   * count, and buffering the remaining bytes in buffer for the next
144
   * and buffering the remaining bytes in buffer for the next operation.
160
   * operation.</p>
145
   * 
161
   *
162
   * @param in the input block.
146
   * @param in the input block.
163
   * @param offset start of meaningful bytes in input block.
147
   * @param offset start of meaningful bytes in input block.
164
   * @param length number of bytes, in input block, to consider.
148
   * @param length number of bytes, in input block, to consider.
Lines 166-197 Link Here
166
  void update(byte[] in, int offset, int length);
150
  void update(byte[] in, int offset, int length);
167
151
168
  /**
152
  /**
169
   * <p>Completes the <i>MAC</i> by performing final operations such as
153
   * Completes the <i>MAC</i> by performing final operations such as padding
170
   * padding and resetting the instance.</p>
154
   * and resetting the instance.
171
   *
155
   * 
172
   * @return the array of bytes representing the <i>MAC</i> value.
156
   * @return the array of bytes representing the <i>MAC</i> value.
173
   */
157
   */
174
  byte[] digest();
158
  byte[] digest();
175
159
176
  /**
160
  /**
177
   * <p>Resets the algorithm instance for re-initialisation and use with other
161
   * Resets the algorithm instance for re-initialisation and use with other
178
   * characteristics. This method always succeeds.</p>
162
   * characteristics. This method always succeeds.
179
   */
163
   */
180
  void reset();
164
  void reset();
181
165
182
  /**
166
  /**
183
   * <p>A basic test. Ensures that the MAC of a pre-determined message is equal
167
   * A basic test. Ensures that the MAC of a pre-determined message is equal to
184
   * to a known pre-computed value.</p>
168
   * a known pre-computed value.
185
   *
169
   * 
186
   * @return <code>true</code> if the implementation passes a basic self-test.
170
   * @return <code>true</code> if the implementation passes a basic self-test.
187
   * Returns <code>false</code> otherwise.
171
   *         Returns <code>false</code> otherwise.
188
   */
172
   */
189
  boolean selfTest();
173
  boolean selfTest();
190
174
191
  /**
175
  /**
192
   * <p>Returns a clone copy of this instance.</p>
176
   * Returns a clone copy of this instance.
193
   *
177
   * 
194
   * @return a clone copy of this instance.
178
   * @return a clone copy of this instance.
195
   */
179
   */
196
  Object clone() throws CloneNotSupportedException;
180
  Object clone() throws CloneNotSupportedException;
197
}
181
}
(-)MacFactory.java (-56 / +22 lines)
Lines 48-64 Link Here
48
import java.util.Set;
48
import java.util.Set;
49
49
50
/**
50
/**
51
 * <p>A <i>Factory</i> that instantiates instances of every supported Message
51
 * A <i>Factory</i> that instantiates instances of every supported Message
52
 * Authentication Code algorithms, including all <i>HMAC</i> algorithms.</p>
52
 * Authentication Code algorithms, including all <i>HMAC</i> algorithms.
53
 */
53
 */
54
public class MacFactory implements Registry
54
public class MacFactory
55
    implements Registry
55
{
56
{
56
57
  private static Set names;
57
  // Constants and variables
58
  // -------------------------------------------------------------------------
59
60
  // Constructor(s)
61
  // -------------------------------------------------------------------------
62
58
63
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
59
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
64
  private MacFactory()
60
  private MacFactory()
Lines 66-137 Link Here
66
    super();
62
    super();
67
  }
63
  }
68
64
69
  // Class methods
70
  // -------------------------------------------------------------------------
71
72
  /**
65
  /**
73
   * <p>Returns an instance of a <i>MAC</i> algorithm given its name.</p>
66
   * Returns an instance of a <i>MAC</i> algorithm given its name.
74
   *
67
   * 
75
   * @param name the name of the MAC algorithm.
68
   * @param name the name of the MAC algorithm.
76
   * @return an instance of the <i>MAC</i> algorithm, or <code>null</code> if
69
   * @return an instance of the <i>MAC</i> algorithm, or <code>null</code> if
77
   * none can be constructed.
70
   *         none can be constructed.
78
   * @exception InternalError if the implementation does not pass its self-test.
71
   * @exception InternalError if the implementation does not pass its self-test.
79
   */
72
   */
80
  public static IMac getInstance(String name)
73
  public static IMac getInstance(String name)
81
  {
74
  {
82
    if (name == null)
75
    if (name == null)
83
      {
76
      return null;
84
        return null;
85
      }
86
77
87
    name = name.trim();
78
    name = name.trim();
88
    name = name.toLowerCase();
79
    name = name.toLowerCase();
89
    if (name.startsWith(HMAC_NAME_PREFIX))
80
    if (name.startsWith(HMAC_NAME_PREFIX))
90
      {
81
      return HMacFactory.getInstance(name);
91
        return HMacFactory.getInstance(name);
92
      }
93
82
94
    if (name.startsWith(OMAC_PREFIX))
83
    if (name.startsWith(OMAC_PREFIX))
95
      {
84
      {
96
        name = name.substring(OMAC_PREFIX.length());
85
        name = name.substring(OMAC_PREFIX.length());
97
        IBlockCipher cipher = CipherFactory.getInstance(name);
86
        IBlockCipher cipher = CipherFactory.getInstance(name);
98
        if (cipher == null)
87
        if (cipher == null)
99
          {
88
          return null;
100
            return null;
101
          }
102
        return new OMAC(cipher);
89
        return new OMAC(cipher);
103
      }
90
      }
104
105
    IMac result = null;
91
    IMac result = null;
106
    if (name.equalsIgnoreCase(UHASH32))
92
    if (name.equalsIgnoreCase(UHASH32))
107
      {
93
      result = new UHash32();
108
        result = new UHash32();
109
      }
110
    else if (name.equalsIgnoreCase(UMAC32))
94
    else if (name.equalsIgnoreCase(UMAC32))
111
      {
95
      result = new UMac32();
112
        result = new UMac32();
113
      }
114
    else if (name.equalsIgnoreCase(TMMH16))
96
    else if (name.equalsIgnoreCase(TMMH16))
115
      {
97
      result = new TMMH16();
116
        result = new TMMH16();
117
      }
118
    //      else if (name.equalsIgnoreCase(TMMH32)) {
119
    //         result = new TMMH32();
120
    //      }
121
98
122
    if (result != null && !result.selfTest())
99
    if (result != null && ! result.selfTest())
123
      {
100
      throw new InternalError(result.name());
124
        throw new InternalError(result.name());
125
      }
126
101
127
    return result;
102
    return result;
128
  }
103
  }
129
104
130
  /**
105
  /**
131
   * <p>Returns a {@link java.util.Set} of names of <i>MAC</i> algorithms
106
   * Returns a {@link Set} of names of <i>MAC</i> algorithms supported by this
132
   * supported by this <i>Factory</i>.</p>
107
   * <i>Factory</i>.
133
   *
108
   * 
134
   * @return a {@link java.util.Set} of MAC names (Strings).
109
   * @return a {@link Set} of MAC names (Strings).
135
   */
110
   */
136
  public static final Set getNames()
111
  public static final Set getNames()
137
  {
112
  {
Lines 144-164 Link Here
144
            hs.add(UHASH32);
119
            hs.add(UHASH32);
145
            hs.add(UMAC32);
120
            hs.add(UMAC32);
146
            hs.add(TMMH16);
121
            hs.add(TMMH16);
147
            //      hs.add(TMMH32);
148
149
            for (Iterator it = CipherFactory.getNames().iterator(); it.hasNext();)
122
            for (Iterator it = CipherFactory.getNames().iterator(); it.hasNext();)
150
              {
123
              hs.add(OMAC_PREFIX + it.next());
151
                hs.add(OMAC_PREFIX + it.next());
152
              }
153
124
154
            names = Collections.unmodifiableSet(hs);
125
            names = Collections.unmodifiableSet(hs);
155
          }
126
          }
156
      }
127
      }
157
    return names;
128
    return names;
158
  }
129
  }
159
130
}
160
  private static Set names;
161
162
  // Instance methods
163
  // -------------------------------------------------------------------------
164
}
(-)MacInputStream.java (-28 / +14 lines)
Lines 46-75 Link Here
46
 * A filtering input stream that computes a MAC (message authentication code)
46
 * A filtering input stream that computes a MAC (message authentication code)
47
 * over all data read from the stream.
47
 * over all data read from the stream.
48
 */
48
 */
49
public class MacInputStream extends FilterInputStream
49
public class MacInputStream
50
    extends FilterInputStream
50
{
51
{
51
52
  /** The digesting state. The MAC is updated only if this flag is true. */
52
  // Field.
53
  // ------------------------------------------------------------------------
54
55
  /**
56
   * The digesting state. The MAC is updated only if this flag is true.
57
   */
58
  private boolean digesting;
53
  private boolean digesting;
59
54
  /** The MAC being updated. */
60
  /**
61
   * The MAC being updated.
62
   */
63
  private IMac mac;
55
  private IMac mac;
64
56
65
  // Constructor.
66
  // ------------------------------------------------------------------------
67
68
  /**
57
  /**
69
   * Creates a new MacInputStream. The stream is initially set to digest
58
   * Creates a new MacInputStream. The stream is initially set to digest data
70
   * data written, the <i>mac</i> argument must have already been initialized,
59
   * written, the <i>mac</i> argument must have already been initialized, and
71
   * and the <i>mac</i> argument is <b>not</b> cloned.
60
   * the <i>mac</i> argument is <b>not</b> cloned.
72
   *
61
   * 
73
   * @param in The underlying input stream.
62
   * @param in The underlying input stream.
74
   * @param mac The mac instance to use.
63
   * @param mac The mac instance to use.
75
   */
64
   */
Lines 82-93 Link Here
82
    digesting = true;
71
    digesting = true;
83
  }
72
  }
84
73
85
  // Instance methods.
86
  // ------------------------------------------------------------------------
87
88
  /**
74
  /**
89
   * Returns the MAC this stream is updating.
75
   * Returns the MAC this stream is updating.
90
   *
76
   * 
91
   * @return The MAC.
77
   * @return The MAC.
92
   */
78
   */
93
  public IMac getMac()
79
  public IMac getMac()
Lines 98-104 Link Here
98
  /**
84
  /**
99
   * Sets the MAC this stream is updating, which must have already been
85
   * Sets the MAC this stream is updating, which must have already been
100
   * initialized. The argument is not cloned by this method.
86
   * initialized. The argument is not cloned by this method.
101
   *
87
   * 
102
   * @param mac The new MAC.
88
   * @param mac The new MAC.
103
   * @throws NullPointerException If the argument is null.
89
   * @throws NullPointerException If the argument is null.
104
   */
90
   */
Lines 110-118 Link Here
110
  }
96
  }
111
97
112
  /**
98
  /**
113
   * Turns the digesting state on or off. When off, the MAC will not be
99
   * Turns the digesting state on or off. When off, the MAC will not be updated
114
   * updated when data is written to the stream.
100
   * when data is written to the stream.
115
   *
101
   * 
116
   * @param flag The new digesting state.
102
   * @param flag The new digesting state.
117
   */
103
   */
118
  public void on(boolean flag)
104
  public void on(boolean flag)
Lines 135-138 Link Here
135
      mac.update(buf, off, i);
121
      mac.update(buf, off, i);
136
    return i;
122
    return i;
137
  }
123
  }
138
}
124
}
(-)MacOutputStream.java (-38 / +21 lines)
Lines 43-71 Link Here
43
import java.io.OutputStream;
43
import java.io.OutputStream;
44
44
45
/**
45
/**
46
 * <p>A filtering output stream that computes a MAC (message authentication
46
 * A filtering output stream that computes a MAC (message authentication code)
47
 * code) over all data written to the stream.</p>
47
 * over all data written to the stream.
48
 */
48
 */
49
public class MacOutputStream extends FilterOutputStream
49
public class MacOutputStream
50
    extends FilterOutputStream
50
{
51
{
51
52
  // Constants and variables
53
  // -------------------------------------------------------------------------
54
55
  /** The digesting state. The MAC is updated only if this flag is true. */
52
  /** The digesting state. The MAC is updated only if this flag is true. */
56
  private boolean digesting;
53
  private boolean digesting;
57
58
  /** The MAC being updated. */
54
  /** The MAC being updated. */
59
  private IMac mac;
55
  private IMac mac;
60
56
61
  // Constructor(s)
62
  // -------------------------------------------------------------------------
63
64
  /**
57
  /**
65
   * <p>Creates a new <code>MacOutputStream</code>. The stream is initially set
58
   * Creates a new <code>MacOutputStream</code>. The stream is initially set
66
   * to digest data written, the <code>mac</code> argument must have already
59
   * to digest data written, the <code>mac</code> argument must have already
67
   * been initialized, and the <code>mac</code> argument is <b>not</b> cloned.</p>
60
   * been initialized, and the <code>mac</code> argument is <b>not</b>
68
   *
61
   * cloned.
62
   * 
69
   * @param out The underlying output stream.
63
   * @param out The underlying output stream.
70
   * @param mac The mac instance to use.
64
   * @param mac The mac instance to use.
71
   */
65
   */
Lines 73-91 Link Here
73
  {
67
  {
74
    super(out);
68
    super(out);
75
    if (mac == null)
69
    if (mac == null)
76
      {
70
      throw new NullPointerException();
77
        throw new NullPointerException();
78
      }
79
    this.mac = mac;
71
    this.mac = mac;
80
    digesting = true;
72
    digesting = true;
81
  }
73
  }
82
74
83
  // Instance methods
84
  // -------------------------------------------------------------------------
85
86
  /**
75
  /**
87
   * <p>Returns the MAC this stream is updating.</p>
76
   * Returns the MAC this stream is updating.
88
   *
77
   * 
89
   * @return The MAC.
78
   * @return The MAC.
90
   */
79
   */
91
  public IMac getMac()
80
  public IMac getMac()
Lines 94-118 Link Here
94
  }
83
  }
95
84
96
  /**
85
  /**
97
   * <p>Sets the MAC this stream is updating, which must have already been
86
   * Sets the MAC this stream is updating, which must have already been
98
   * initialized. The argument is not cloned by this method.</p>
87
   * initialized. The argument is not cloned by this method.
99
   *
88
   * 
100
   * @param mac The non-null new MAC.
89
   * @param mac The non-null new MAC.
101
   * @throws NullPointerException If the argument is null.
90
   * @throws NullPointerException If the argument is null.
102
   */
91
   */
103
  public void setMac(IMac mac)
92
  public void setMac(IMac mac)
104
  {
93
  {
105
    if (mac == null)
94
    if (mac == null)
106
      {
95
      throw new NullPointerException();
107
        throw new NullPointerException();
108
      }
109
    this.mac = mac;
96
    this.mac = mac;
110
  }
97
  }
111
98
112
  /**
99
  /**
113
   * <p>Turns the digesting state on or off. When off, the MAC will not be
100
   * Turns the digesting state on or off. When off, the MAC will not be updated
114
   * updated when data is written to the stream.</p>
101
   * when data is written to the stream.
115
   *
102
   * 
116
   * @param flag The new digesting state.
103
   * @param flag The new digesting state.
117
   */
104
   */
118
  public void on(boolean flag)
105
  public void on(boolean flag)
Lines 123-140 Link Here
123
  public void write(int b) throws IOException
110
  public void write(int b) throws IOException
124
  {
111
  {
125
    if (digesting)
112
    if (digesting)
126
      {
113
      mac.update((byte) b);
127
        mac.update((byte) b);
128
      }
129
    out.write(b);
114
    out.write(b);
130
  }
115
  }
131
116
132
  public void write(byte[] buf, int off, int len) throws IOException
117
  public void write(byte[] buf, int off, int len) throws IOException
133
  {
118
  {
134
    if (digesting)
119
    if (digesting)
135
      {
120
      mac.update(buf, off, len);
136
        mac.update(buf, off, len);
137
      }
138
    out.write(buf, off, len);
121
    out.write(buf, off, len);
139
  }
122
  }
140
}
123
}
(-)OMAC.java (-125 / +47 lines)
Lines 52-114 Link Here
52
import java.util.logging.Logger;
52
import java.util.logging.Logger;
53
53
54
/**
54
/**
55
 * <p>The One-Key CBC MAC, OMAC. This message authentication code is based on
55
 * The One-Key CBC MAC, OMAC. This message authentication code is based on a
56
 * a block cipher in CBC mode.</p>
56
 * block cipher in CBC mode.
57
 *
57
 * <p>
58
 * <p>References:</p>
58
 * References:
59
 * <ol>
59
 * <ol>
60
 * <li>Tetsu Iwata and Kaoru Kurosawa, <i><a
60
 * <li>Tetsu Iwata and Kaoru Kurosawa, <i><a
61
 * href="http://crypt.cis.ibaraki.ac.jp/omac/docs/omac.pdf">OMAC: One-Key CBC
61
 * href="http://crypt.cis.ibaraki.ac.jp/omac/docs/omac.pdf">OMAC: One-Key CBC
62
 * MAC</a></i>.</li>
62
 * MAC</a></i>.</li>
63
 * </ol>
63
 * </ol>
64
 */
64
 */
65
public class OMAC implements IMac
65
public class OMAC
66
    implements IMac
66
{
67
{
67
  private static final Logger log = Logger.getLogger(OMAC.class.getName());
68
  private static final Logger log = Logger.getLogger(OMAC.class.getName());
68
  private static final byte C1 = (byte) 0x87;
69
  private static final byte C1 = (byte) 0x87;
69
70
  private static final byte C2 = 0x1b;
70
  private static final byte C2 = 0x1b;
71
72
  // Test key for OMAC-AES-128
71
  // Test key for OMAC-AES-128
73
  private static final byte[] KEY0 = Util.toBytesFromString("2b7e151628aed2a6abf7158809cf4f3c");
72
  private static final byte[] KEY0 =
74
73
      Util.toBytesFromString("2b7e151628aed2a6abf7158809cf4f3c");
75
  // Test MAC for zero-length input.
74
  // Test MAC for zero-length input.
76
  private static final byte[] DIGEST0 = Util.toBytesFromString("bb1d6929e95937287fa37d129b756746");
75
  private static final byte[] DIGEST0 =
77
76
      Util.toBytesFromString("bb1d6929e95937287fa37d129b756746");
78
  private static Boolean valid;
77
  private static Boolean valid;
79
80
  private final IBlockCipher cipher;
78
  private final IBlockCipher cipher;
81
82
  private final String name;
79
  private final String name;
83
84
  private IMode mode;
80
  private IMode mode;
85
86
  private int blockSize;
81
  private int blockSize;
87
88
  private int outputSize;
82
  private int outputSize;
89
90
  private byte[] Lu, Lu2;
83
  private byte[] Lu, Lu2;
91
92
  private byte[] M;
84
  private byte[] M;
93
94
  private byte[] Y;
85
  private byte[] Y;
95
96
  private boolean init;
86
  private boolean init;
97
98
  private int index;
87
  private int index;
99
88
100
  // Constructor.
101
  // ------------------------------------------------------------------------
102
103
  public OMAC(IBlockCipher cipher)
89
  public OMAC(IBlockCipher cipher)
104
  {
90
  {
105
    this.cipher = cipher;
91
    this.cipher = cipher;
106
    this.name = "OMAC-" + cipher.name();
92
    this.name = "OMAC-" + cipher.name();
107
  }
93
  }
108
94
109
  // Instance methods.
110
  // ------------------------------------------------------------------------
111
112
  public Object clone()
95
  public Object clone()
113
  {
96
  {
114
    return new OMAC(cipher);
97
    return new OMAC(cipher);
Lines 130-150 Link Here
130
    attrib2.put(IBlockCipher.KEY_MATERIAL, attrib.get(MAC_KEY_MATERIAL));
113
    attrib2.put(IBlockCipher.KEY_MATERIAL, attrib.get(MAC_KEY_MATERIAL));
131
    cipher.reset();
114
    cipher.reset();
132
    cipher.init(attrib2);
115
    cipher.init(attrib2);
133
134
    blockSize = cipher.currentBlockSize();
116
    blockSize = cipher.currentBlockSize();
135
    Integer os = (Integer) attrib.get(TRUNCATED_SIZE);
117
    Integer os = (Integer) attrib.get(TRUNCATED_SIZE);
136
    if (os != null)
118
    if (os != null)
137
      {
119
      {
138
        outputSize = os.intValue();
120
        outputSize = os.intValue();
139
        if (outputSize < 0 || outputSize > blockSize)
121
        if (outputSize < 0 || outputSize > blockSize)
140
          {
122
          throw new IllegalArgumentException("truncated size out of range");
141
            throw new IllegalArgumentException("truncated size out of range");
142
          }
143
      }
123
      }
144
    else
124
    else
145
      {
125
      outputSize = blockSize;
146
        outputSize = blockSize;
147
      }
148
126
149
    byte[] L = new byte[blockSize];
127
    byte[] L = new byte[blockSize];
150
    cipher.encryptBlock(L, 0, L, 0);
128
    cipher.encryptBlock(L, 0, L, 0);
Lines 154-227 Link Here
154
      {
132
      {
155
        Arrays.fill(Lu, (byte) 0);
133
        Arrays.fill(Lu, (byte) 0);
156
        if (Lu.length != blockSize)
134
        if (Lu.length != blockSize)
157
          {
135
          Lu = new byte[blockSize];
158
            Lu = new byte[blockSize];
159
          }
160
      }
136
      }
161
    else
137
    else
162
      {
138
      Lu = new byte[blockSize];
163
        Lu = new byte[blockSize];
164
      }
165
    if (Lu2 != null)
139
    if (Lu2 != null)
166
      {
140
      {
167
        Arrays.fill(Lu2, (byte) 0);
141
        Arrays.fill(Lu2, (byte) 0);
168
        if (Lu2.length != blockSize)
142
        if (Lu2.length != blockSize)
169
          {
143
          Lu2 = new byte[blockSize];
170
            Lu2 = new byte[blockSize];
171
          }
172
      }
144
      }
173
    else
145
    else
174
      {
146
      Lu2 = new byte[blockSize];
175
        Lu2 = new byte[blockSize];
176
      }
177
147
178
    boolean msb = (L[0] & 0x80) != 0;
148
    boolean msb = (L[0] & 0x80) != 0;
179
    for (int i = 0; i < blockSize; i++)
149
    for (int i = 0; i < blockSize; i++)
180
      {
150
      {
181
        Lu[i] = (byte) (L[i] << 1 & 0xFF);
151
        Lu[i] = (byte)(L[i] << 1 & 0xFF);
182
        if (i + 1 < blockSize)
152
        if (i + 1 < blockSize)
183
          {
153
          Lu[i] |= (byte)((L[i + 1] & 0x80) >> 7);
184
            Lu[i] |= (byte) ((L[i + 1] & 0x80) >> 7);
185
          }
186
      }
154
      }
187
    if (msb)
155
    if (msb)
188
      {
156
      {
189
        if (blockSize == 16)
157
        if (blockSize == 16)
190
          {
158
          Lu[Lu.length - 1] ^= C1;
191
            Lu[Lu.length - 1] ^= C1;
192
          }
193
        else if (blockSize == 8)
159
        else if (blockSize == 8)
194
          {
160
          Lu[Lu.length - 1] ^= C2;
195
            Lu[Lu.length - 1] ^= C2;
196
          }
197
        else
161
        else
198
          {
162
          throw new IllegalArgumentException("unsupported cipher block size: "
199
            throw new IllegalArgumentException(
163
                                             + blockSize);
200
                                               "unsupported cipher block size: "
201
                                                   + blockSize);
202
          }
203
      }
164
      }
204
    if (Configuration.DEBUG)
165
    if (Configuration.DEBUG)
205
      log.fine("Lu = " + Util.toString(Lu).toLowerCase());
166
      log.fine("Lu = " + Util.toString(Lu).toLowerCase());
206
    msb = (Lu[0] & 0x80) != 0;
167
    msb = (Lu[0] & 0x80) != 0;
207
    for (int i = 0; i < blockSize; i++)
168
    for (int i = 0; i < blockSize; i++)
208
      {
169
      {
209
        Lu2[i] = (byte) (Lu[i] << 1 & 0xFF);
170
        Lu2[i] = (byte)(Lu[i] << 1 & 0xFF);
210
        if (i + 1 < blockSize)
171
        if (i + 1 < blockSize)
211
          {
172
          Lu2[i] |= (byte)((Lu[i + 1] & 0x80) >> 7);
212
            Lu2[i] |= (byte) ((Lu[i + 1] & 0x80) >> 7);
213
          }
214
      }
173
      }
215
    if (msb)
174
    if (msb)
216
      {
175
      {
217
        if (blockSize == 16)
176
        if (blockSize == 16)
218
          {
177
          Lu2[Lu2.length - 1] ^= C1;
219
            Lu2[Lu2.length - 1] ^= C1;
220
          }
221
        else
178
        else
222
          {
179
          Lu2[Lu2.length - 1] ^= C2;
223
            Lu2[Lu2.length - 1] ^= C2;
224
          }
225
      }
180
      }
226
    if (Configuration.DEBUG)
181
    if (Configuration.DEBUG)
227
      log.fine("Lu2 = " + Util.toString(Lu2).toLowerCase());
182
      log.fine("Lu2 = " + Util.toString(Lu2).toLowerCase());
Lines 229-254 Link Here
229
      {
184
      {
230
        Arrays.fill(M, (byte) 0);
185
        Arrays.fill(M, (byte) 0);
231
        if (M.length != blockSize)
186
        if (M.length != blockSize)
232
          {
187
          M = new byte[blockSize];
233
            M = new byte[blockSize];
234
          }
235
      }
188
      }
236
    else
189
    else
237
      {
190
      M = new byte[blockSize];
238
        M = new byte[blockSize];
239
      }
240
    if (Y != null)
191
    if (Y != null)
241
      {
192
      {
242
        Arrays.fill(Y, (byte) 0);
193
        Arrays.fill(Y, (byte) 0);
243
        if (Y.length != blockSize)
194
        if (Y.length != blockSize)
244
          {
195
          Y = new byte[blockSize];
245
            Y = new byte[blockSize];
246
          }
247
      }
196
      }
248
    else
197
    else
249
      {
198
      Y = new byte[blockSize];
250
        Y = new byte[blockSize];
251
      }
252
199
253
    index = 0;
200
    index = 0;
254
    init = true;
201
    init = true;
Lines 256-265 Link Here
256
203
257
  public void update(byte b)
204
  public void update(byte b)
258
  {
205
  {
259
    if (!init)
206
    if (! init)
260
      {
207
      throw new IllegalStateException("not initialized");
261
        throw new IllegalStateException("not initialized");
262
      }
263
    if (index == M.length)
208
    if (index == M.length)
264
      {
209
      {
265
        process();
210
        process();
Lines 270-284 Link Here
270
215
271
  public void update(byte[] buf, int off, int len)
216
  public void update(byte[] buf, int off, int len)
272
  {
217
  {
273
    if (!init)
218
    if (! init)
274
      {
219
      throw new IllegalStateException("not initialized");
275
        throw new IllegalStateException("not initialized");
276
      }
277
    if (off < 0 || len < 0 || off + len > buf.length)
220
    if (off < 0 || len < 0 || off + len > buf.length)
278
      {
221
      throw new IndexOutOfBoundsException("size=" + buf.length + "; off=" + off
279
        throw new IndexOutOfBoundsException("size=" + buf.length + "; off="
222
                                          + "; len=" + len);
280
                                            + off + "; len=" + len);
281
      }
282
    for (int i = 0; i < len;)
223
    for (int i = 0; i < len;)
283
      {
224
      {
284
        if (index == blockSize)
225
        if (index == blockSize)
Lines 302-331 Link Here
302
243
303
  public void digest(byte[] out, int off)
244
  public void digest(byte[] out, int off)
304
  {
245
  {
305
    if (!init)
246
    if (! init)
306
      {
247
      throw new IllegalStateException("not initialized");
307
        throw new IllegalStateException("not initialized");
308
      }
309
    if (off < 0 || off + outputSize > out.length)
248
    if (off < 0 || off + outputSize > out.length)
310
      {
249
      throw new IndexOutOfBoundsException("size=" + out.length + "; off=" + off
311
        throw new IndexOutOfBoundsException("size=" + out.length + "; off="
250
                                          + "; len=" + outputSize);
312
                                            + off + "; len=" + outputSize);
313
      }
314
    byte[] T = new byte[blockSize];
251
    byte[] T = new byte[blockSize];
315
    byte[] L = Lu;
252
    byte[] L = Lu;
316
    if (index < blockSize)
253
    if (index < blockSize)
317
      {
254
      {
318
        M[index++] = (byte) 0x80;
255
        M[index++] = (byte) 0x80;
319
        while (index < blockSize)
256
        while (index < blockSize)
320
          {
257
          M[index++] = 0;
321
            M[index++] = 0;
322
          }
323
        L = Lu2;
258
        L = Lu2;
324
      }
259
      }
325
    for (int i = 0; i < blockSize; i++)
260
    for (int i = 0; i < blockSize; i++)
326
      {
261
      T[i] = (byte)(M[i] ^ Y[i] ^ L[i]);
327
        T[i] = (byte) (M[i] ^ Y[i] ^ L[i]);
328
      }
329
    cipher.encryptBlock(T, 0, T, 0);
262
    cipher.encryptBlock(T, 0, T, 0);
330
    System.arraycopy(T, 0, out, off, outputSize);
263
    System.arraycopy(T, 0, out, off, outputSize);
331
    reset();
264
    reset();
Lines 335-347 Link Here
335
  {
268
  {
336
    index = 0;
269
    index = 0;
337
    if (Y != null)
270
    if (Y != null)
338
      {
271
      Arrays.fill(Y, (byte) 0);
339
        Arrays.fill(Y, (byte) 0);
340
      }
341
    if (M != null)
272
    if (M != null)
342
      {
273
      Arrays.fill(M, (byte) 0);
343
        Arrays.fill(M, (byte) 0);
344
      }
345
  }
274
  }
346
275
347
  public boolean selfTest()
276
  public boolean selfTest()
Lines 361-381 Link Here
361
        return false;
290
        return false;
362
      }
291
      }
363
    if (digest == null)
292
    if (digest == null)
364
      {
293
      return false;
365
        return false;
366
      }
367
    return Arrays.equals(DIGEST0, digest);
294
    return Arrays.equals(DIGEST0, digest);
368
  }
295
  }
369
296
370
  // Own methods.
371
  // ------------------------------------------------------------------------
372
373
  private void process()
297
  private void process()
374
  {
298
  {
375
    for (int i = 0; i < blockSize; i++)
299
    for (int i = 0; i < blockSize; i++)
376
      {
300
      M[i] = (byte)(M[i] ^ Y[i]);
377
        M[i] = (byte) (M[i] ^ Y[i]);
378
      }
379
    cipher.encryptBlock(M, 0, Y, 0);
301
    cipher.encryptBlock(M, 0, Y, 0);
380
  }
302
  }
381
}
303
}
(-)TMMH16.java (-129 / +66 lines)
Lines 46-136 Link Here
46
import java.util.Map;
46
import java.util.Map;
47
47
48
/**
48
/**
49
 * <p><i>TMMH</i> is a <i>universal</i> hash function suitable for message
49
 * <i>TMMH</i> is a <i>universal</i> hash function suitable for message
50
 * authentication in the Wegman-Carter paradigm, as in the Stream Cipher
50
 * authentication in the Wegman-Carter paradigm, as in the Stream Cipher
51
 * Security Transform. It is simple, quick, and especially appropriate for
51
 * Security Transform. It is simple, quick, and especially appropriate for
52
 * Digital Signal Processors and other processors with a fast multiply
52
 * Digital Signal Processors and other processors with a fast multiply
53
 * operation, though a straightforward implementation requires storage equal in
53
 * operation, though a straightforward implementation requires storage equal in
54
 * length to the largest message to be hashed.</p>
54
 * length to the largest message to be hashed.
55
 *
55
 * <p>
56
 * <p><i>TMMH</i> is a simple hash function which maps a key and a message to a
56
 * <i>TMMH</i> is a simple hash function which maps a key and a message to a
57
 * hash value. There are two versions of TMMH: TMMH/16 and TMMH/32. <i>TMMH</i>
57
 * hash value. There are two versions of TMMH: TMMH/16 and TMMH/32. <i>TMMH</i>
58
 * can be used as a message authentication code, as described in Section 5 (see
58
 * can be used as a message authentication code, as described in Section 5 (see
59
 * References).</p>
59
 * References).
60
 *
60
 * <p>
61
 * <p>The key, message, and hash value are all octet strings, and the lengths of
61
 * The key, message, and hash value are all octet strings, and the lengths of
62
 * these quantities are denoted as <code>KEY_LENGTH</code>,
62
 * these quantities are denoted as <code>KEY_LENGTH</code>,
63
 * <code>MESSAGE_LENGTH</code>, and <code>TAG_LENGTH</code>, respectively. The
63
 * <code>MESSAGE_LENGTH</code>, and <code>TAG_LENGTH</code>, respectively.
64
 * values of <code>KEY_LENGTH</code> and <code>TAG_LENGTH</code>
64
 * The values of <code>KEY_LENGTH</code> and <code>TAG_LENGTH</code>
65
 * <bold>MUST</bold> be fixed for any particular fixed value of the key, and
65
 * <bold>MUST</bold> be fixed for any particular fixed value of the key, and
66
 * must obey the alignment restrictions described below.</p>
66
 * must obey the alignment restrictions described below.
67
 *
67
 * <p>
68
 * <p>The parameter <code>MAX_HASH_LENGTH</code>, which denotes the maximum
68
 * The parameter <code>MAX_HASH_LENGTH</code>, which denotes the maximum
69
 * value which <code>MESSAGE_LENGTH</code> may take, is equal to
69
 * value which <code>MESSAGE_LENGTH</code> may take, is equal to
70
 * <code>KEY_LENGTH - TAG_LENGTH</code>.</p>
70
 * <code>KEY_LENGTH - TAG_LENGTH</code>.
71
 *
71
 * <p>
72
 * <p>References:</p>
72
 * References:
73
 *
74
 * <ol>
73
 * <ol>
75
 *    <li><a
74
 * <li><a
76
 href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-tmmh-01.txt">
75
 * href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-tmmh-01.txt"> The
77
 *    The Truncated Multi-Modular Hash Function (TMMH)</a>, David A. McGrew.</li>
76
 * Truncated Multi-Modular Hash Function (TMMH)</a>, David A. McGrew.</li>
78
 * </ol>
77
 * </ol>
79
 */
78
 */
80
public class TMMH16 extends BaseMac implements Cloneable
79
public class TMMH16
80
    extends BaseMac
81
    implements Cloneable
81
{
82
{
82
83
  // Constants and variables
84
  // -------------------------------------------------------------------------
85
86
  public static final String TAG_LENGTH = "gnu.crypto.mac.tmmh.tag.length";
83
  public static final String TAG_LENGTH = "gnu.crypto.mac.tmmh.tag.length";
87
88
  public static final String KEYSTREAM = "gnu.crypto.mac.tmmh.keystream";
84
  public static final String KEYSTREAM = "gnu.crypto.mac.tmmh.keystream";
89
90
  public static final String PREFIX = "gnu.crypto.mac.tmmh.prefix";
85
  public static final String PREFIX = "gnu.crypto.mac.tmmh.prefix";
91
92
  private static final int P = (1 << 16) + 1; // the TMMH/16 prime
86
  private static final int P = (1 << 16) + 1; // the TMMH/16 prime
93
94
  /** caches the result of the correctness test, once executed. */
87
  /** caches the result of the correctness test, once executed. */
95
  private static Boolean valid;
88
  private static Boolean valid;
96
97
  private int tagWords = 0; // the tagLength expressed in words
89
  private int tagWords = 0; // the tagLength expressed in words
98
99
  private IRandom keystream = null; // the keystream generator
90
  private IRandom keystream = null; // the keystream generator
100
101
  private byte[] prefix; // mask to use when operating as an authentication f.
91
  private byte[] prefix; // mask to use when operating as an authentication f.
102
103
  private long keyWords; // key words counter
92
  private long keyWords; // key words counter
104
105
  private long msgLength; // in bytes
93
  private long msgLength; // in bytes
106
107
  private long msgWords; // should be = msgLength * WORD_LENGTH
94
  private long msgWords; // should be = msgLength * WORD_LENGTH
108
109
  private int[] context; // the tmmh running context; length == TAG_WORDS
95
  private int[] context; // the tmmh running context; length == TAG_WORDS
110
111
  private int[] K0; // the first TAG_WORDS words of the keystream
96
  private int[] K0; // the first TAG_WORDS words of the keystream
112
113
  private int[] Ki; // the sliding TAG_WORDS words of the keystream
97
  private int[] Ki; // the sliding TAG_WORDS words of the keystream
114
115
  private int Mi; // current message word being constructed
98
  private int Mi; // current message word being constructed
116
99
117
  // Constructor(s)
118
  // -------------------------------------------------------------------------
119
120
  /** Trivial 0-arguments constructor. */
100
  /** Trivial 0-arguments constructor. */
121
  public TMMH16()
101
  public TMMH16()
122
  {
102
  {
123
    super(Registry.TMMH16);
103
    super(Registry.TMMH16);
124
  }
104
  }
125
105
126
  // Class methods
127
  // -------------------------------------------------------------------------
128
129
  // Instance methods
130
  // -------------------------------------------------------------------------
131
132
  // gnu.crypto.mac.IMac interface implementation ----------------------------
133
134
  public int macSize()
106
  public int macSize()
135
  {
107
  {
136
    return tagWords * 2;
108
    return tagWords * 2;
Lines 143-164 Link Here
143
    Integer tagLength = (Integer) attributes.get(TAG_LENGTH); // get tag length
115
    Integer tagLength = (Integer) attributes.get(TAG_LENGTH); // get tag length
144
    if (tagLength == null)
116
    if (tagLength == null)
145
      {
117
      {
146
        if (tagWords == 0)
118
        if (tagWords == 0) // was never set
147
          { // was never set
119
          throw new IllegalArgumentException(TAG_LENGTH);
148
            throw new IllegalArgumentException(TAG_LENGTH);
120
        // else re-use
149
          } // else re-use
150
      }
121
      }
151
    else
122
    else // check if positive and is divisible by WORD_LENGTH
152
      { // check if positive and is divisible by WORD_LENGTH
123
      {
153
        wantTagLength = tagLength.intValue();
124
        wantTagLength = tagLength.intValue();
154
        if (wantTagLength < 2 || (wantTagLength % 2 != 0))
125
        if (wantTagLength < 2 || (wantTagLength % 2 != 0))
155
          {
126
          throw new IllegalArgumentException(TAG_LENGTH);
156
            throw new IllegalArgumentException(TAG_LENGTH);
127
        else if (wantTagLength > (512 / 8)) // 512-bits is our maximum
157
          }
128
          throw new IllegalArgumentException(TAG_LENGTH);
158
        else if (wantTagLength > (512 / 8))
159
          { // 512-bits is our maximum
160
            throw new IllegalArgumentException(TAG_LENGTH);
161
          }
162
129
163
        tagWords = wantTagLength / 2; // init local vars
130
        tagWords = wantTagLength / 2; // init local vars
164
        K0 = new int[tagWords];
131
        K0 = new int[tagWords];
Lines 167-202 Link Here
167
      }
134
      }
168
135
169
    prefix = (byte[]) attributes.get(PREFIX);
136
    prefix = (byte[]) attributes.get(PREFIX);
170
    if (prefix == null)
137
    if (prefix == null) // default to all-zeroes
171
      { // default to all-zeroes
138
      prefix = new byte[tagWords * 2];
172
        prefix = new byte[tagWords * 2];
139
    else // ensure it's as long as it should
173
      }
140
      {
174
    else
175
      { // ensure it's as long as it should
176
        if (prefix.length != tagWords * 2)
141
        if (prefix.length != tagWords * 2)
177
          {
142
          throw new IllegalArgumentException(PREFIX);
178
            throw new IllegalArgumentException(PREFIX);
179
          }
180
      }
143
      }
181
144
182
    IRandom prng = (IRandom) attributes.get(KEYSTREAM); // get keystream
145
    IRandom prng = (IRandom) attributes.get(KEYSTREAM); // get keystream
183
    if (prng == null)
146
    if (prng == null)
184
      {
147
      {
185
        if (keystream == null)
148
        if (keystream == null)
186
          {
149
          throw new IllegalArgumentException(KEYSTREAM);
187
            throw new IllegalArgumentException(KEYSTREAM);
150
        // else reuse
188
          } // else reuse
189
      }
151
      }
190
    else
152
    else
191
      {
153
      keystream = prng;
192
        keystream = prng;
193
      }
194
154
195
    reset(); // reset context variables
155
    reset(); // reset context variables
196
    for (int i = 0; i < tagWords; i++)
156
    for (int i = 0; i < tagWords; i++) // init starting key words
197
      { // init starting key words
157
      Ki[i] = K0[i] = getNextKeyWord(keystream);
198
        Ki[i] = K0[i] = getNextKeyWord(keystream);
199
      }
200
  }
158
  }
201
159
202
  // The words of the key are denoted as K[1], K[2], ..., K[KEY_WORDS], and the
160
  // The words of the key are denoted as K[1], K[2], ..., K[KEY_WORDS], and the
Lines 206-217 Link Here
206
  //
164
  //
207
  // If MESSAGE_LENGTH is greater than MAX_HASH_LENGTH, then the value of
165
  // If MESSAGE_LENGTH is greater than MAX_HASH_LENGTH, then the value of
208
  // TMMH/16 is undefined. Implementations MUST indicate an error if asked to
166
  // TMMH/16 is undefined. Implementations MUST indicate an error if asked to
209
  // hash a message with such a length.  Otherwise, the hash value is defined
167
  // hash a message with such a length. Otherwise, the hash value is defined
210
  // to be the length TAG_WORDS sequence of words in which the j-th word in the
168
  // to be the length TAG_WORDS sequence of words in which the j-th word in the
211
  // sequence is defined as
169
  // sequence is defined as
212
  //
170
  //
213
  // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
171
  // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
214
  //   +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
172
  // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
215
  //
173
  //
216
  // where j ranges from 1 to TAG_WORDS.
174
  // where j ranges from 1 to TAG_WORDS.
217
  public void update(byte b)
175
  public void update(byte b)
Lines 222-244 Link Here
222
  public void update(byte[] b, int offset, int len)
180
  public void update(byte[] b, int offset, int len)
223
  {
181
  {
224
    for (int i = 0; i < len; i++)
182
    for (int i = 0; i < len; i++)
225
      {
183
      this.update(b[offset + i], keystream);
226
        this.update(b[offset + i], keystream);
227
      }
228
  }
184
  }
229
185
230
  // For TMMH/16, KEY_LENGTH and TAG_LENGTH MUST be a multiple of two. The key,
186
  // For TMMH/16, KEY_LENGTH and TAG_LENGTH MUST be a multiple of two. The key,
231
  // message, and hash value are treated as a sequence of unsigned sixteen bit
187
  // message, and hash value are treated as a sequence of unsigned sixteen bit
232
  // integers in network byte order.  (In this section, we call such an integer
188
  // integers in network byte order. (In this section, we call such an integer
233
  // a word.)  If MESSAGE_LENGTH is odd, then a zero byte is appended to the
189
  // a word.) If MESSAGE_LENGTH is odd, then a zero byte is appended to the
234
  // message to align it on a word boundary, though this process does not
190
  // message to align it on a word boundary, though this process does not
235
  // change the value of MESSAGE_LENGTH.
191
  // change the value of MESSAGE_LENGTH.
236
  //
192
  //
237
  // ...  Otherwise, the hash value is defined to be the length TAG_WORDS
193
  // ... Otherwise, the hash value is defined to be the length TAG_WORDS
238
  // sequence of words in which the j-th word in the sequence is defined as
194
  // sequence of words in which the j-th word in the sequence is defined as
239
  //
195
  //
240
  // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
196
  // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
241
  //   +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
197
  // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
242
  //
198
  //
243
  // where j ranges from 1 to TAG_WORDS.
199
  // where j ranges from 1 to TAG_WORDS.
244
  //
200
  //
Lines 255-263 Link Here
255
    msgLength = msgWords = keyWords = 0L;
211
    msgLength = msgWords = keyWords = 0L;
256
    Mi = 0;
212
    Mi = 0;
257
    for (int i = 0; i < tagWords; i++)
213
    for (int i = 0; i < tagWords; i++)
258
      {
214
      context[i] = 0;
259
        context[i] = 0;
260
      }
261
  }
215
  }
262
216
263
  public boolean selfTest()
217
  public boolean selfTest()
Lines 265-306 Link Here
265
    if (valid == null)
219
    if (valid == null)
266
      {
220
      {
267
        // TODO: compute and test equality with one known vector
221
        // TODO: compute and test equality with one known vector
268
269
        valid = Boolean.TRUE;
222
        valid = Boolean.TRUE;
270
      }
223
      }
271
    return valid.booleanValue();
224
    return valid.booleanValue();
272
  }
225
  }
273
226
274
  // Cloneable interface implementation ---------------------------------------
275
276
  public Object clone() throws CloneNotSupportedException
227
  public Object clone() throws CloneNotSupportedException
277
  {
228
  {
278
    TMMH16 result = (TMMH16) super.clone();
229
    TMMH16 result = (TMMH16) super.clone();
279
280
    if (this.keystream != null)
230
    if (this.keystream != null)
281
      result.keystream = (IRandom) this.keystream.clone();
231
      result.keystream = (IRandom) this.keystream.clone();
282
283
    if (this.prefix != null)
232
    if (this.prefix != null)
284
      result.prefix = (byte[]) this.prefix.clone();
233
      result.prefix = (byte[]) this.prefix.clone();
285
286
    if (this.context != null)
234
    if (this.context != null)
287
      result.context = (int[]) this.context.clone();
235
      result.context = (int[]) this.context.clone();
288
289
    if (this.K0 != null)
236
    if (this.K0 != null)
290
      result.K0 = (int[]) this.K0.clone();
237
      result.K0 = (int[]) this.K0.clone();
291
292
    if (this.Ki != null)
238
    if (this.Ki != null)
293
      result.Ki = (int[]) this.Ki.clone();
239
      result.Ki = (int[]) this.Ki.clone();
294
295
    return result;
240
    return result;
296
  }
241
  }
297
242
298
  // own methods -------------------------------------------------------------
299
300
  /**
243
  /**
301
   * <p>Similar to the same method with one argument, but uses the designated
244
   * Similar to the same method with one argument, but uses the designated
302
   * random number generator to compute needed keying material.</p>
245
   * random number generator to compute needed keying material.
303
   *
246
   * 
304
   * @param b the byte to process.
247
   * @param b the byte to process.
305
   * @param prng the source of randomness to use.
248
   * @param prng the source of randomness to use.
306
   */
249
   */
Lines 309-322 Link Here
309
    Mi <<= 8; // update message buffer
252
    Mi <<= 8; // update message buffer
310
    Mi |= b & 0xFF;
253
    Mi |= b & 0xFF;
311
    msgLength++; // update message length (bytes)
254
    msgLength++; // update message length (bytes)
312
    if (msgLength % 2 == 0)
255
    if (msgLength % 2 == 0) // got a full word
313
      { // got a full word
256
      {
314
        msgWords++; // update message words counter
257
        msgWords++; // update message words counter
315
        System.arraycopy(Ki, 1, Ki, 0, tagWords - 1); // 1. shift Ki up by 1
258
        System.arraycopy(Ki, 1, Ki, 0, tagWords - 1); // 1. shift Ki up by 1
316
        Ki[tagWords - 1] = getNextKeyWord(prng); // 2. fill last box of Ki
259
        Ki[tagWords - 1] = getNextKeyWord(prng); // 2. fill last box of Ki
317
        long t; // temp var to allow working in modulo 2^32
260
        long t; // temp var to allow working in modulo 2^32
318
        for (int i = 0; i < tagWords; i++)
261
        for (int i = 0; i < tagWords; i++) // 3. update context
319
          { // 3. update context
262
          {
320
            t = context[i] & 0xFFFFFFFFL;
263
            t = context[i] & 0xFFFFFFFFL;
321
            t += Ki[i] * Mi;
264
            t += Ki[i] * Mi;
322
            context[i] = (int) t;
265
            context[i] = (int) t;
Lines 326-353 Link Here
326
  }
269
  }
327
270
328
  /**
271
  /**
329
   * <p>Similar to the same method with three arguments, but uses the
272
   * Similar to the same method with three arguments, but uses the designated
330
   * designated random number generator to compute needed keying material.</p>
273
   * random number generator to compute needed keying material.
331
   *
274
   * 
332
   * @param b the byte array to process.
275
   * @param b the byte array to process.
333
   * @param offset the starting offset in <code>b</code> to start considering
276
   * @param offset the starting offset in <code>b</code> to start considering
334
   * the bytes to process.
277
   *          the bytes to process.
335
   * @param len the number of bytes in <code>b</code> starting from
278
   * @param len the number of bytes in <code>b</code> starting from
336
   * <code>offset</code> to process.
279
   *          <code>offset</code> to process.
337
   * @param prng the source of randomness to use.
280
   * @param prng the source of randomness to use.
338
   */
281
   */
339
  public void update(byte[] b, int offset, int len, IRandom prng)
282
  public void update(byte[] b, int offset, int len, IRandom prng)
340
  {
283
  {
341
    for (int i = 0; i < len; i++)
284
    for (int i = 0; i < len; i++)
342
      {
285
      this.update(b[offset + i], prng);
343
        this.update(b[offset + i], prng);
344
      }
345
  }
286
  }
346
287
347
  /**
288
  /**
348
   * <p>Similar to the same method with no arguments, but uses the designated
289
   * Similar to the same method with no arguments, but uses the designated
349
   * random number generator to compute needed keying material.</p>
290
   * random number generator to compute needed keying material.
350
   *
291
   * 
351
   * @param prng the source of randomness to use.
292
   * @param prng the source of randomness to use.
352
   * @return the final result of the algorithm.
293
   * @return the final result of the algorithm.
353
   */
294
   */
Lines 357-368 Link Here
357
    byte[] result = new byte[tagWords * 2];
298
    byte[] result = new byte[tagWords * 2];
358
    for (int i = 0, j = 0; i < tagWords; i++)
299
    for (int i = 0, j = 0; i < tagWords; i++)
359
      {
300
      {
360
        result[j] = (byte) ((context[i] >>> 8) ^ prefix[j]);
301
        result[j] = (byte)((context[i] >>> 8) ^ prefix[j]);
361
        j++;
302
        j++;
362
        result[j] = (byte) (context[i] ^ prefix[j]);
303
        result[j] = (byte)(context[i] ^ prefix[j]);
363
        j++;
304
        j++;
364
      }
305
      }
365
366
    reset();
306
    reset();
367
    return result;
307
    return result;
368
  }
308
  }
Lines 378-384 Link Here
378
      {
318
      {
379
        throw new RuntimeException(String.valueOf(x));
319
        throw new RuntimeException(String.valueOf(x));
380
      }
320
      }
381
382
    keyWords++; // update key words counter
321
    keyWords++; // update key words counter
383
    return result;
322
    return result;
384
  }
323
  }
Lines 387-395 Link Here
387
  {
326
  {
388
    long limit = msgLength; // formula works on real message length
327
    long limit = msgLength; // formula works on real message length
389
    while (msgLength % 2 != 0)
328
    while (msgLength % 2 != 0)
390
      {
329
      update((byte) 0x00, prng);
391
        update((byte) 0x00, prng);
392
      }
393
    long t;
330
    long t;
394
    for (int i = 0; i < tagWords; i++)
331
    for (int i = 0; i < tagWords; i++)
395
      {
332
      {
(-)UHash32.java (-346 / +147 lines)
Lines 40-46 Link Here
40
40
41
import gnu.java.security.prng.IRandom;
41
import gnu.java.security.prng.IRandom;
42
import gnu.java.security.prng.LimitReachedException;
42
import gnu.java.security.prng.LimitReachedException;
43
44
import gnu.javax.crypto.cipher.IBlockCipher;
43
import gnu.javax.crypto.cipher.IBlockCipher;
45
import gnu.javax.crypto.prng.UMacGenerator;
44
import gnu.javax.crypto.prng.UMacGenerator;
46
45
Lines 51-153 Link Here
51
import java.util.Map;
50
import java.util.Map;
52
51
53
/**
52
/**
54
 * <p><i>UHASH</i> is a keyed hash function, which takes as input a string of
53
 * <i>UHASH</i> is a keyed hash function, which takes as input a string of
55
 * arbitrary length, and produces as output a string of fixed length (such as 8
54
 * arbitrary length, and produces as output a string of fixed length (such as 8
56
 * bytes). The actual output length depends on the parameter UMAC-OUTPUT-LEN.</p>
55
 * bytes). The actual output length depends on the parameter UMAC-OUTPUT-LEN.
57
 *
56
 * <p>
58
 * <p><i>UHASH</i> has been shown to be <i>epsilon-ASU</i> ("Almost Strongly
57
 * <i>UHASH</i> has been shown to be <i>epsilon-ASU</i> ("Almost Strongly
59
 * Universal"), where epsilon is a small (parameter-dependent) real number.
58
 * Universal"), where epsilon is a small (parameter-dependent) real number.
60
 * Informally, saying that a keyed hash function is <i>epsilon-ASU</i> means
59
 * Informally, saying that a keyed hash function is <i>epsilon-ASU</i> means
61
 * that for any two distinct fixed input strings, the two outputs of the hash
60
 * that for any two distinct fixed input strings, the two outputs of the hash
62
 * function with a random key "look almost like a pair of random strings". The
61
 * function with a random key "look almost like a pair of random strings". The
63
 * number epsilon measures how non-random the output strings may be.</p>
62
 * number epsilon measures how non-random the output strings may be.
64
 *
63
 * <p>
65
 * <i>UHASH</i> has been designed to be fast by exploiting several architectural
64
 * <i>UHASH</i> has been designed to be fast by exploiting several
66
 * features of modern commodity processors. It was specifically designed for use
65
 * architectural features of modern commodity processors. It was specifically
67
 * in <i>UMAC</i>. But <i>UHASH</i> is useful beyond that domain, and can be
66
 * designed for use in <i>UMAC</i>. But <i>UHASH</i> is useful beyond that
68
 * easily adopted for other purposes.</p>
67
 * domain, and can be easily adopted for other purposes.
69
 *
68
 * <p>
70
 * <i>UHASH</i> does its work in three layers. First, a hash function called
69
 * <i>UHASH</i> does its work in three layers. First, a hash function called
71
 * <code>NH</code> is used to compress input messages into strings which are
70
 * <code>NH</code> is used to compress input messages into strings which are
72
 * typically many times smaller than the input message. Second, the compressed
71
 * typically many times smaller than the input message. Second, the compressed
73
 * message is hashed with an optimized <i>polynomial hash function</i> into a
72
 * message is hashed with an optimized <i>polynomial hash function</i> into a
74
 * fixed-length 16-byte string. Finally, the 16-byte string is hashed using an
73
 * fixed-length 16-byte string. Finally, the 16-byte string is hashed using an
75
 * <i>inner-product hash</i> into a string of length WORD-LEN bytes. These three
74
 * <i>inner-product hash</i> into a string of length WORD-LEN bytes. These
76
 * layers are repeated (with a modified key) until the outputs total
75
 * three layers are repeated (with a modified key) until the outputs total
77
 * UMAC-OUTPUT-LEN bytes.</p>
76
 * UMAC-OUTPUT-LEN bytes.
78
 *
77
 * <p>
79
 * <p>References:</p>
78
 * References:
80
 *
81
 * <ol>
79
 * <ol>
82
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
80
 * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
83
 *    UMAC</a>: Message Authentication Code using Universal Hashing.<br>
81
 * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
84
 *    T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
82
 * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
85
 * </ol>
83
 * </ol>
86
 */
84
 */
87
public class UHash32 extends BaseMac
85
public class UHash32
86
    extends BaseMac
88
{
87
{
89
90
  // Constants and variables
91
  // -------------------------------------------------------------------------
92
93
  // UMAC prime values
88
  // UMAC prime values
94
  private static final BigInteger PRIME_19 = BigInteger.valueOf(0x7FFFFL);
89
  private static final BigInteger PRIME_19 = BigInteger.valueOf(0x7FFFFL);
95
96
  private static final BigInteger PRIME_32 = BigInteger.valueOf(0xFFFFFFFBL);
90
  private static final BigInteger PRIME_32 = BigInteger.valueOf(0xFFFFFFFBL);
97
98
  private static final BigInteger PRIME_36 = BigInteger.valueOf(0xFFFFFFFFBL);
91
  private static final BigInteger PRIME_36 = BigInteger.valueOf(0xFFFFFFFFBL);
99
92
  private static final BigInteger PRIME_64 = new BigInteger(1, new byte[] {
100
  private static final BigInteger PRIME_64 = new BigInteger(
93
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
101
                                                            1,
94
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xC5 });
102
                                                            new byte[] {
95
  private static final BigInteger PRIME_128 = new BigInteger(1, new byte[] {
103
                                                                        (byte) 0xFF,
96
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
104
                                                                        (byte) 0xFF,
97
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
105
                                                                        (byte) 0xFF,
98
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
106
                                                                        (byte) 0xFF,
99
      (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x61 });
107
                                                                        (byte) 0xFF,
108
                                                                        (byte) 0xFF,
109
                                                                        (byte) 0xFF,
110
                                                                        (byte) 0xC5 });
111
112
  private static final BigInteger PRIME_128 = new BigInteger(
113
                                                             1,
114
                                                             new byte[] {
115
                                                                         (byte) 0xFF,
116
                                                                         (byte) 0xFF,
117
                                                                         (byte) 0xFF,
118
                                                                         (byte) 0xFF,
119
                                                                         (byte) 0xFF,
120
                                                                         (byte) 0xFF,
121
                                                                         (byte) 0xFF,
122
                                                                         (byte) 0xFF,
123
                                                                         (byte) 0xFF,
124
                                                                         (byte) 0xFF,
125
                                                                         (byte) 0xFF,
126
                                                                         (byte) 0xFF,
127
                                                                         (byte) 0xFF,
128
                                                                         (byte) 0xFF,
129
                                                                         (byte) 0xFF,
130
                                                                         (byte) 0x61 });
131
132
  static final BigInteger TWO = BigInteger.valueOf(2L);
100
  static final BigInteger TWO = BigInteger.valueOf(2L);
133
134
  static final long BOUNDARY = TWO.shiftLeft(17).longValue();
101
  static final long BOUNDARY = TWO.shiftLeft(17).longValue();
135
136
  // 2**64 - 2**32
102
  // 2**64 - 2**32
137
  static final BigInteger LOWER_RANGE = TWO.pow(64).subtract(TWO.pow(32));
103
  static final BigInteger LOWER_RANGE = TWO.pow(64).subtract(TWO.pow(32));
138
139
  // 2**128 - 2**96
104
  // 2**128 - 2**96
140
  static final BigInteger UPPER_RANGE = TWO.pow(128).subtract(TWO.pow(96));
105
  static final BigInteger UPPER_RANGE = TWO.pow(128).subtract(TWO.pow(96));
141
142
  static final byte[] ALL_ZEROES = new byte[32];
106
  static final byte[] ALL_ZEROES = new byte[32];
143
144
  int streams;
107
  int streams;
145
146
  L1Hash32[] l1hash;
108
  L1Hash32[] l1hash;
147
109
148
  // Constructor(s)
149
  // -------------------------------------------------------------------------
150
151
  /** Trivial 0-arguments constructor. */
110
  /** Trivial 0-arguments constructor. */
152
  public UHash32()
111
  public UHash32()
153
  {
112
  {
Lines 155-161 Link Here
155
  }
114
  }
156
115
157
  /**
116
  /**
158
   * <p>Private constructor for cloning purposes.</p>
117
   * Private constructor for cloning purposes.
159
   *
118
   *
160
   * @param that the instance to clone.
119
   * @param that the instance to clone.
161
   */
120
   */
Lines 166-189 Link Here
166
    this.streams = that.streams;
125
    this.streams = that.streams;
167
    if (that.l1hash != null)
126
    if (that.l1hash != null)
168
      {
127
      {
169
        //         this.l1hash = new L1Hash32[that.l1hash.length];
170
        this.l1hash = new L1Hash32[that.streams];
128
        this.l1hash = new L1Hash32[that.streams];
171
        //         for (int i = 0; i < that.l1hash.length; i++) {
172
        for (int i = 0; i < that.streams; i++)
129
        for (int i = 0; i < that.streams; i++)
173
          {
130
          if (that.l1hash[i] != null)
174
            if (that.l1hash[i] != null)
131
            this.l1hash[i] = (L1Hash32) that.l1hash[i].clone();
175
              {
176
                this.l1hash[i] = (L1Hash32) that.l1hash[i].clone();
177
              }
178
          }
179
      }
132
      }
180
  }
133
  }
181
134
182
  // Class methods
183
  // -------------------------------------------------------------------------
184
185
  /**
135
  /**
186
   * <p>The prime numbers used in UMAC are:</p>
136
   * The prime numbers used in UMAC are:
187
   * <pre>
137
   * <pre>
188
   *   +-----+--------------------+---------------------------------------+
138
   *   +-----+--------------------+---------------------------------------+
189
   *   |  x  | prime(x) [Decimal] | prime(x) [Hexadecimal]                |
139
   *   |  x  | prime(x) [Decimal] | prime(x) [Hexadecimal]                |
Lines 219-236 Link Here
219
      }
169
      }
220
  }
170
  }
221
171
222
  // Instance methods
223
  // -------------------------------------------------------------------------
224
225
  // java.lang.Cloneable interface implementation ----------------------------
226
227
  public Object clone()
172
  public Object clone()
228
  {
173
  {
229
    return new UHash32(this);
174
    return new UHash32(this);
230
  }
175
  }
231
176
232
  // gnu.crypto.mac.IMac interface implementation ----------------------------
233
234
  public int macSize()
177
  public int macSize()
235
  {
178
  {
236
    return UMac32.OUTPUT_LEN;
179
    return UMac32.OUTPUT_LEN;
Lines 241-258 Link Here
241
  {
184
  {
242
    byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
185
    byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
243
    if (K == null)
186
    if (K == null)
244
      {
187
      throw new InvalidKeyException("Null Key");
245
        throw new InvalidKeyException("Null Key");
246
      }
247
    if (K.length != UMac32.KEY_LEN)
188
    if (K.length != UMac32.KEY_LEN)
248
      {
189
      throw new InvalidKeyException("Invalid Key length: "
249
        throw new InvalidKeyException("Invalid Key length: "
190
                                    + String.valueOf(K.length));
250
                                      + String.valueOf(K.length));
251
      }
252
253
    // Calculate iterations needed to make UMAC-OUTPUT-LEN bytes
191
    // Calculate iterations needed to make UMAC-OUTPUT-LEN bytes
254
    streams = (UMac32.OUTPUT_LEN + 3) / 4;
192
    streams = (UMac32.OUTPUT_LEN + 3) / 4;
255
256
    // Define total key needed for all iterations using UMacGenerator.
193
    // Define total key needed for all iterations using UMacGenerator.
257
    // L1Key and L3Key1 both reuse most key between iterations.
194
    // L1Key and L3Key1 both reuse most key between iterations.
258
    IRandom kdf1 = new UMacGenerator();
195
    IRandom kdf1 = new UMacGenerator();
Lines 269-275 Link Here
269
    kdf3.init(map);
206
    kdf3.init(map);
270
    map.put(UMacGenerator.INDEX, Integer.valueOf(3));
207
    map.put(UMacGenerator.INDEX, Integer.valueOf(3));
271
    kdf4.init(map);
208
    kdf4.init(map);
272
273
    // need to generate all bytes for use later in a Toepliz construction
209
    // need to generate all bytes for use later in a Toepliz construction
274
    byte[] L1Key = new byte[UMac32.L1_KEY_LEN + (streams - 1) * 16];
210
    byte[] L1Key = new byte[UMac32.L1_KEY_LEN + (streams - 1) * 16];
275
    try
211
    try
Lines 297-303 Link Here
297
            x.printStackTrace(System.err);
233
            x.printStackTrace(System.err);
298
            throw new RuntimeException("KDF for L2Key reached limit");
234
            throw new RuntimeException("KDF for L2Key reached limit");
299
          }
235
          }
300
301
        byte[] k31 = new byte[64];
236
        byte[] k31 = new byte[64];
302
        try
237
        try
303
          {
238
          {
Lines 308-314 Link Here
308
            x.printStackTrace(System.err);
243
            x.printStackTrace(System.err);
309
            throw new RuntimeException("KDF for L3Key1 reached limit");
244
            throw new RuntimeException("KDF for L3Key1 reached limit");
310
          }
245
          }
311
312
        byte[] k32 = new byte[4];
246
        byte[] k32 = new byte[4];
313
        try
247
        try
314
          {
248
          {
Lines 319-325 Link Here
319
            x.printStackTrace(System.err);
253
            x.printStackTrace(System.err);
320
            throw new RuntimeException("KDF for L3Key2 reached limit");
254
            throw new RuntimeException("KDF for L3Key2 reached limit");
321
          }
255
          }
322
323
        L1Hash32 mac = new L1Hash32();
256
        L1Hash32 mac = new L1Hash32();
324
        mac.init(k1, k2, k31, k32);
257
        mac.init(k1, k2, k31, k32);
325
        l1hash[i] = mac;
258
        l1hash[i] = mac;
Lines 329-345 Link Here
329
  public void update(byte b)
262
  public void update(byte b)
330
  {
263
  {
331
    for (int i = 0; i < streams; i++)
264
    for (int i = 0; i < streams; i++)
332
      {
265
      l1hash[i].update(b);
333
        l1hash[i].update(b);
334
      }
335
  }
266
  }
336
267
337
  public void update(byte[] b, int offset, int len)
268
  public void update(byte[] b, int offset, int len)
338
  {
269
  {
339
    for (int i = 0; i < len; i++)
270
    for (int i = 0; i < len; i++)
340
      {
271
      this.update(b[offset + i]);
341
        this.update(b[offset + i]);
342
      }
343
  }
272
  }
344
273
345
  public byte[] digest()
274
  public byte[] digest()
Lines 357-365 Link Here
357
  public void reset()
286
  public void reset()
358
  {
287
  {
359
    for (int i = 0; i < streams; i++)
288
    for (int i = 0; i < streams; i++)
360
      {
289
      l1hash[i].reset();
361
        l1hash[i].reset();
362
      }
363
  }
290
  }
364
291
365
  public boolean selfTest()
292
  public boolean selfTest()
Lines 367-404 Link Here
367
    return true;
294
    return true;
368
  }
295
  }
369
296
370
  // helper methods ----------------------------------------------------------
371
372
  // Inner classes
373
  // =========================================================================
374
375
  /**
297
  /**
376
   * First hash stage of the UHash32 algorithm.
298
   * First hash stage of the UHash32 algorithm.
377
   */
299
   */
378
  class L1Hash32 implements Cloneable
300
  class L1Hash32
301
      implements Cloneable
379
  {
302
  {
380
381
    // Constants and variables
382
    // ----------------------------------------------------------------------
383
384
    private int[] key; // key material as an array of 32-bit ints
303
    private int[] key; // key material as an array of 32-bit ints
385
386
    private byte[] buffer; // work buffer L1_KEY_LEN long
304
    private byte[] buffer; // work buffer L1_KEY_LEN long
387
388
    private int count; // meaningful bytes in buffer
305
    private int count; // meaningful bytes in buffer
389
390
    private ByteArrayOutputStream Y;
306
    private ByteArrayOutputStream Y;
391
392
    //      private byte[] y;
393
    private long totalCount;
307
    private long totalCount;
394
395
    private L2Hash32 l2hash;
308
    private L2Hash32 l2hash;
396
397
    private L3Hash32 l3hash;
309
    private L3Hash32 l3hash;
398
310
399
    // Constructor(s)
400
    // ----------------------------------------------------------------------
401
402
    /** Trivial 0-arguments constructor. */
311
    /** Trivial 0-arguments constructor. */
403
    L1Hash32()
312
    L1Hash32()
404
    {
313
    {
Lines 412-418 Link Here
412
    }
321
    }
413
322
414
    /**
323
    /**
415
     * <p>Private constructor for cloning purposes.</p>
324
     * Private constructor for cloning purposes.
416
     *
325
     *
417
     * @param that the instance to clone.
326
     * @param that the instance to clone.
418
     */
327
     */
Lines 427-464 Link Here
427
      this.Y.write(otherY, 0, otherY.length);
336
      this.Y.write(otherY, 0, otherY.length);
428
      this.totalCount = that.totalCount;
337
      this.totalCount = that.totalCount;
429
      if (that.l2hash != null)
338
      if (that.l2hash != null)
430
        {
339
        this.l2hash = (L2Hash32) that.l2hash.clone();
431
          this.l2hash = (L2Hash32) that.l2hash.clone();
432
        }
433
      if (that.l3hash != null)
340
      if (that.l3hash != null)
434
        {
341
        this.l3hash = (L3Hash32) that.l3hash.clone();
435
          this.l3hash = (L3Hash32) that.l3hash.clone();
436
        }
437
    }
342
    }
438
343
439
    // Class methods
440
    // ----------------------------------------------------------------------
441
442
    // Instance methods
443
    // ----------------------------------------------------------------------
444
445
    // java.lang.Cloneable interface implementation -------------------------
446
447
    public Object clone()
344
    public Object clone()
448
    {
345
    {
449
      return new L1Hash32(this);
346
      return new L1Hash32(this);
450
    }
347
    }
451
348
452
    // other instance methods -----------------------------------------------
453
454
    public void init(byte[] k1, byte[] k2, byte[] k31, byte[] k32)
349
    public void init(byte[] k1, byte[] k2, byte[] k31, byte[] k32)
455
    {
350
    {
456
      for (int i = 0, j = 0; i < (UMac32.L1_KEY_LEN / 4); i++)
351
      for (int i = 0, j = 0; i < (UMac32.L1_KEY_LEN / 4); i++)
457
        {
352
        key[i] =  k1[j++]         << 24
458
          key[i] = k1[j++] << 24 | (k1[j++] & 0xFF) << 16
353
               | (k1[j++] & 0xFF) << 16
459
                   | (k1[j++] & 0xFF) << 8 | (k1[j++] & 0xFF);
354
               | (k1[j++] & 0xFF) << 8
460
        }
355
               | (k1[j++] & 0xFF);
461
462
      l2hash = new L2Hash32(k2);
356
      l2hash = new L2Hash32(k2);
463
      l3hash = new L3Hash32(k31, k32);
357
      l3hash = new L3Hash32(k31, k32);
464
    }
358
    }
Lines 484-491 Link Here
484
378
485
          // For each iteration, extract key and three-layer hash.
379
          // For each iteration, extract key and three-layer hash.
486
          // If length(M) <= L1_KEY_LEN, then skip L2-HASH.
380
          // If length(M) <= L1_KEY_LEN, then skip L2-HASH.
487
          if (Y.size() == 16)
381
          if (Y.size() == 16) // we already hashed twice L1_KEY_LEN
488
            { // we already hashed twice L1_KEY_LEN
382
            {
489
              byte[] A = Y.toByteArray();
383
              byte[] A = Y.toByteArray();
490
              Y.reset();
384
              Y.reset();
491
              l2hash.update(A, 0, 16);
385
              l2hash.update(A, 0, 16);
Lines 508-526 Link Here
508
          byte[] y = nh32(count);
402
          byte[] y = nh32(count);
509
          Y.write(y, 0, 8);
403
          Y.write(y, 0, 8);
510
        }
404
        }
511
512
      byte[] A = Y.toByteArray();
405
      byte[] A = Y.toByteArray();
513
      Y.reset();
406
      Y.reset();
514
      byte[] B;
407
      byte[] B;
515
      if (totalCount <= UMac32.L1_KEY_LEN)
408
      if (totalCount <= UMac32.L1_KEY_LEN)
516
        {
409
        {
517
          // we might have 'update'd the bytes already. check
410
          // we might have 'update'd the bytes already. check
518
          if (A.length == 0)
411
          if (A.length == 0) // we did
519
            { // we did
412
            B = l2hash.digest();
520
              B = l2hash.digest();
413
          else // did not
521
            }
414
            {
522
          else
523
            { // did not
524
              B = new byte[16];
415
              B = new byte[16];
525
              System.arraycopy(A, 0, B, 8, 8);
416
              System.arraycopy(A, 0, B, 8, 8);
526
            }
417
            }
Lines 528-539 Link Here
528
      else
419
      else
529
        {
420
        {
530
          if (A.length != 0)
421
          if (A.length != 0)
531
            {
422
            l2hash.update(A, 0, A.length);
532
              l2hash.update(A, 0, A.length);
533
            }
534
          B = l2hash.digest();
423
          B = l2hash.digest();
535
        }
424
        }
536
537
      byte[] result = l3hash.digest(B);
425
      byte[] result = l3hash.digest(B);
538
      reset();
426
      reset();
539
      return result;
427
      return result;
Lines 545-557 Link Here
545
      Y.reset();
433
      Y.reset();
546
      totalCount = 0L;
434
      totalCount = 0L;
547
      if (l2hash != null)
435
      if (l2hash != null)
548
        {
436
        l2hash.reset();
549
          l2hash.reset();
550
        }
551
    }
437
    }
552
438
553
    // helper methods -------------------------------------------------------
554
555
    /**
439
    /**
556
     * 5.1  NH-32: NH hashing with a 32-bit word size.
440
     * 5.1  NH-32: NH hashing with a 32-bit word size.
557
     *
441
     *
Lines 562-677 Link Here
562
    {
446
    {
563
      // Break M and K into 4-byte chunks
447
      // Break M and K into 4-byte chunks
564
      int t = len / 4;
448
      int t = len / 4;
565
566
      // Let M_1, M_2, ..., M_t be 4-byte strings
449
      // Let M_1, M_2, ..., M_t be 4-byte strings
567
      // so that M = M_1 || M_2 || .. || M_t.
450
      // so that M = M_1 || M_2 || .. || M_t.
568
      // Let K_1, K_2, ..., K_t be 4-byte strings
451
      // Let K_1, K_2, ..., K_t be 4-byte strings
569
      // so that K_1 || K_2 || .. || K_t  is a prefix of K.
452
      // so that K_1 || K_2 || .. || K_t  is a prefix of K.
570
      int[] m = new int[t];
453
      int[] m = new int[t];
571
572
      int i;
454
      int i;
573
      int j = 0;
455
      int j = 0;
574
      for (i = 0, j = 0; i < t; i++)
456
      for (i = 0, j = 0; i < t; i++)
575
        {
457
        m[i] =  buffer[j++]         << 24
576
          m[i] = buffer[j++] << 24 | (buffer[j++] & 0xFF) << 16
458
             | (buffer[j++] & 0xFF) << 16
577
                 | (buffer[j++] & 0xFF) << 8 | (buffer[j++] & 0xFF);
459
             | (buffer[j++] & 0xFF) << 8
578
        }
460
             | (buffer[j++] & 0xFF);
579
580
      // Perform NH hash on the chunks, pairing words for multiplication
461
      // Perform NH hash on the chunks, pairing words for multiplication
581
      // which are 4 apart to accommodate vector-parallelism.
462
      // which are 4 apart to accommodate vector-parallelism.
582
      long result = len * 8L;
463
      long result = len * 8L;
583
      for (i = 0; i < t; i += 8)
464
      for (i = 0; i < t; i += 8)
584
        {
465
        {
585
          result += ((m[i + 0] + key[i + 0]) & 0xFFFFFFFFL)
466
          result += ((m[i + 0] + key[i + 0]) & 0xFFFFFFFFL)
586
                    * ((m[i + 4] + key[i + 4]) & 0xFFFFFFFFL);
467
                  * ((m[i + 4] + key[i + 4]) & 0xFFFFFFFFL);
587
          result += ((m[i + 1] + key[i + 1]) & 0xFFFFFFFFL)
468
          result += ((m[i + 1] + key[i + 1]) & 0xFFFFFFFFL)
588
                    * ((m[i + 5] + key[i + 5]) & 0xFFFFFFFFL);
469
                  * ((m[i + 5] + key[i + 5]) & 0xFFFFFFFFL);
589
          result += ((m[i + 2] + key[i + 2]) & 0xFFFFFFFFL)
470
          result += ((m[i + 2] + key[i + 2]) & 0xFFFFFFFFL)
590
                    * ((m[i + 6] + key[i + 6]) & 0xFFFFFFFFL);
471
                  * ((m[i + 6] + key[i + 6]) & 0xFFFFFFFFL);
591
          result += ((m[i + 3] + key[i + 3]) & 0xFFFFFFFFL)
472
          result += ((m[i + 3] + key[i + 3]) & 0xFFFFFFFFL)
592
                    * ((m[i + 7] + key[i + 7]) & 0xFFFFFFFFL);
473
                  * ((m[i + 7] + key[i + 7]) & 0xFFFFFFFFL);
593
        }
474
        }
594
475
      return new byte[] {
595
      return new byte[] { (byte) (result >>> 56), (byte) (result >>> 48),
476
          (byte)(result >>> 56), (byte)(result >>> 48),
596
                         (byte) (result >>> 40), (byte) (result >>> 32),
477
          (byte)(result >>> 40), (byte)(result >>> 32),
597
                         (byte) (result >>> 24), (byte) (result >>> 16),
478
          (byte)(result >>> 24), (byte)(result >>> 16),
598
                         (byte) (result >>> 8), (byte) result };
479
          (byte)(result >>>  8), (byte) result };
599
    }
480
    }
600
  }
481
  }
601
482
602
  // =========================================================================
603
604
  /**
483
  /**
605
   * <p>Second hash stage of the UHash32 algorithm.</p>
484
   * Second hash stage of the UHash32 algorithm.
606
   *
485
   * <p>
607
   * 5.4  L2-HASH-32: Second-layer hash.<p>
486
   * 5.4 L2-HASH-32: Second-layer hash.
608
   * <ul>
487
   * <ul>
609
   *    <li>Input:<br>
488
   * <li>Input:<br>
610
   *       K string of length 24 bytes.<br>
489
   * K string of length 24 bytes.<br>
611
   *       M string of length less than 2^64 bytes.</li>
490
   * M string of length less than 2^64 bytes.</li>
612
   *    <li>Returns:<br>
491
   * <li>Returns:<br>
613
   *       Y, string of length 16 bytes.</li>
492
   * Y, string of length 16 bytes.</li>
614
   * </ul>
493
   * </ul>
615
   */
494
   */
616
  class L2Hash32 implements Cloneable
495
  class L2Hash32
496
      implements Cloneable
617
  {
497
  {
618
619
    // Constants and variables
620
    // ----------------------------------------------------------------------
621
622
    private BigInteger k64, k128;
498
    private BigInteger k64, k128;
623
624
    private BigInteger y;
499
    private BigInteger y;
625
626
    private boolean highBound;
500
    private boolean highBound;
627
628
    private long bytesSoFar;
501
    private long bytesSoFar;
629
630
    private ByteArrayOutputStream buffer;
502
    private ByteArrayOutputStream buffer;
631
503
632
    // Constructor(s)
633
    // ----------------------------------------------------------------------
634
635
    L2Hash32(byte[] K)
504
    L2Hash32(byte[] K)
636
    {
505
    {
637
      super();
506
      super();
638
507
639
      if (K.length != 24)
508
      if (K.length != 24)
640
        {
509
        throw new ExceptionInInitializerError("K length is not 24");
641
          throw new ExceptionInInitializerError("K length is not 24");
642
        }
643
644
      //  Extract keys and restrict to special key-sets
510
      //  Extract keys and restrict to special key-sets
645
      //         Mask64  = uint2str(0x01FFFFFF01FFFFFF, 8);
511
      //         Mask64  = uint2str(0x01FFFFFF01FFFFFF, 8);
646
      //         Mask128 = uint2str(0x01FFFFFF01FFFFFF01FFFFFF01FFFFFF, 16);
512
      //         Mask128 = uint2str(0x01FFFFFF01FFFFFF01FFFFFF01FFFFFF, 16);
647
      //         k64    = str2uint(K[1..8]  and Mask64);
513
      //         k64    = str2uint(K[1..8]  and Mask64);
648
      //         k128   = str2uint(K[9..24] and Mask128);
514
      //         k128   = str2uint(K[9..24] and Mask128);
649
      int i = 0;
515
      int i = 0;
650
      k64 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01),
516
      k64 = new BigInteger(1, new byte[] {
651
                                          (byte) (K[i++] & 0xFF),
517
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
652
                                          (byte) (K[i++] & 0xFF),
518
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF),
653
                                          (byte) (K[i++] & 0xFF),
519
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
654
                                          (byte) (K[i++] & 0x01),
520
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF) });
655
                                          (byte) (K[i++] & 0xFF),
521
      k128 = new BigInteger(1, new byte[] {
656
                                          (byte) (K[i++] & 0xFF),
522
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
657
                                          (byte) (K[i++] & 0xFF) });
523
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF),
658
      k128 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01),
524
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
659
                                           (byte) (K[i++] & 0xFF),
525
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF),
660
                                           (byte) (K[i++] & 0xFF),
526
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
661
                                           (byte) (K[i++] & 0xFF),
527
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF),
662
                                           (byte) (K[i++] & 0x01),
528
          (byte)(K[i++] & 0x01), (byte)(K[i++] & 0xFF),
663
                                           (byte) (K[i++] & 0xFF),
529
          (byte)(K[i++] & 0xFF), (byte)(K[i++] & 0xFF) });
664
                                           (byte) (K[i++] & 0xFF),
665
                                           (byte) (K[i++] & 0xFF),
666
                                           (byte) (K[i++] & 0x01),
667
                                           (byte) (K[i++] & 0xFF),
668
                                           (byte) (K[i++] & 0xFF),
669
                                           (byte) (K[i++] & 0xFF),
670
                                           (byte) (K[i++] & 0x01),
671
                                           (byte) (K[i++] & 0xFF),
672
                                           (byte) (K[i++] & 0xFF),
673
                                           (byte) (K[i++] & 0xFF) });
674
675
      y = BigInteger.ONE;
530
      y = BigInteger.ONE;
676
      highBound = false;
531
      highBound = false;
677
      bytesSoFar = 0L;
532
      bytesSoFar = 0L;
Lines 694-729 Link Here
694
        }
549
        }
695
    }
550
    }
696
551
697
    // Class methods
698
    // ----------------------------------------------------------------------
699
700
    // Instance methods
701
    // ----------------------------------------------------------------------
702
703
    // java.lang.Cloneable interface implementation -------------------------
704
705
    public Object clone()
552
    public Object clone()
706
    {
553
    {
707
      return new L2Hash32(this);
554
      return new L2Hash32(this);
708
    }
555
    }
709
556
710
    // other instance methods -----------------------------------------------
711
712
    // this is called with either 8-bytes or 16-bytes
557
    // this is called with either 8-bytes or 16-bytes
713
    void update(byte[] b, int offset, int len)
558
    void update(byte[] b, int offset, int len)
714
    {
559
    {
715
      if (len == 0)
560
      if (len == 0)
716
        {
561
        return;
717
          return;
718
        }
719
562
720
      if (!highBound)
563
      if (! highBound) // do the first (only?) 8-bytes
721
        { // do the first (only?) 8-bytes
564
        {
722
          poly(64, LOWER_RANGE, k64, b, offset, 8);
565
          poly(64, LOWER_RANGE, k64, b, offset, 8);
723
          bytesSoFar += 8L;
566
          bytesSoFar += 8L;
724
          highBound = (bytesSoFar > BOUNDARY);
567
          highBound = (bytesSoFar > BOUNDARY);
725
          if (highBound)
568
          if (highBound) // if we just crossed the limit then process y
726
            { // if we just crossed the limit then process y
569
            {
727
              poly(128, UPPER_RANGE, k128, yTo16bytes(), 0, 16);
570
              poly(128, UPPER_RANGE, k128, yTo16bytes(), 0, 16);
728
              buffer = new ByteArrayOutputStream();
571
              buffer = new ByteArrayOutputStream();
729
            }
572
            }
Lines 739-747 Link Here
739
              byte[] bb = buffer.toByteArray();
582
              byte[] bb = buffer.toByteArray();
740
              poly(128, UPPER_RANGE, k128, bb, 0, 16);
583
              poly(128, UPPER_RANGE, k128, bb, 0, 16);
741
              if (bb.length > 16)
584
              if (bb.length > 16)
742
                {
585
                buffer.write(bb, 16, bb.length - 16);
743
                  buffer.write(bb, 16, bb.length - 16);
744
                }
745
            }
586
            }
746
        }
587
        }
747
    }
588
    }
Lines 751-769 Link Here
751
      // If M no more than 2^17 bytes, hash under 64-bit prime,
592
      // If M no more than 2^17 bytes, hash under 64-bit prime,
752
      // otherwise, hash first 2^17 bytes under 64-bit prime and
593
      // otherwise, hash first 2^17 bytes under 64-bit prime and
753
      // remainder under 128-bit prime.
594
      // remainder under 128-bit prime.
754
      if (!highBound)
595
      if (! highBound) // y is up-to-date
755
        { // y is up-to-date
596
        {
756
          // do nothing
597
          // do nothing
757
        }
598
        }
758
      else
599
      else // we may have some bytes in buffer
759
        { // we may have some bytes in buffer
600
        {
760
          byte[] bb = buffer.toByteArray();
601
          byte[] bb = buffer.toByteArray();
761
          byte[] lastBlock = new byte[16];
602
          byte[] lastBlock = new byte[16];
762
          System.arraycopy(bb, 0, lastBlock, 0, bb.length);
603
          System.arraycopy(bb, 0, lastBlock, 0, bb.length);
763
          lastBlock[bb.length] = (byte) 0x80;
604
          lastBlock[bb.length] = (byte) 0x80;
764
          poly(128, UPPER_RANGE, k128, lastBlock, 0, 16);
605
          poly(128, UPPER_RANGE, k128, lastBlock, 0, 16);
765
        }
606
        }
766
767
      byte[] result = yTo16bytes();
607
      byte[] result = yTo16bytes();
768
      reset();
608
      reset();
769
      return result;
609
      return result;
Lines 775-812 Link Here
775
      highBound = false;
615
      highBound = false;
776
      bytesSoFar = 0L;
616
      bytesSoFar = 0L;
777
      if (buffer != null)
617
      if (buffer != null)
778
        {
618
        buffer.reset();
779
          buffer.reset();
780
        }
781
    }
619
    }
782
620
783
    // helper methods -------------------------------------------------------
784
785
    private byte[] yTo16bytes()
621
    private byte[] yTo16bytes()
786
    {
622
    {
787
      byte[] yy = y.toByteArray();
623
      byte[] yy = y.toByteArray();
788
      byte[] result = new byte[16];
624
      byte[] result = new byte[16];
789
      if (yy.length > 16)
625
      if (yy.length > 16)
790
        {
626
        System.arraycopy(yy, yy.length - 16, result, 0, 16);
791
          System.arraycopy(yy, yy.length - 16, result, 0, 16);
792
        }
793
      else
627
      else
794
        {
628
        System.arraycopy(yy, 0, result, 16 - yy.length, yy.length);
795
          System.arraycopy(yy, 0, result, 16 - yy.length, yy.length);
796
        }
797
629
798
      return result;
630
      return result;
799
    }
631
    }
800
632
801
    /**
633
    /**
802
     * 5.3  POLY: Polynomial hash
634
     * 5.3 POLY: Polynomial hash Function Name: POLY
803
     * Function Name: POLY
635
     * 
804
     *
805
     * @param wordbits positive integer divisible by 8: called with 64 or 128.
636
     * @param wordbits positive integer divisible by 8: called with 64 or 128.
806
     * @param maxwordrange positive integer less than 2**wordbits.
637
     * @param maxwordrange positive integer less than 2**wordbits.
807
     * @param k integer in the range 0 .. prime(wordbits) - 1.
638
     * @param k integer in the range 0 .. prime(wordbits) - 1.
808
     * @param M string with length divisible by (wordbits / 8) bytes.
639
     * @param M string with length divisible by (wordbits / 8) bytes. return y,
809
     * return y, integer in the range 0 .. prime(wordbits) - 1.
640
     *          integer in the range 0 .. prime(wordbits) - 1.
810
     */
641
     */
811
    private void poly(int wordbits, BigInteger maxwordrange, BigInteger k,
642
    private void poly(int wordbits, BigInteger maxwordrange, BigInteger k,
812
                      byte[] M, int off, int len)
643
                      byte[] M, int off, int len)
Lines 814-825 Link Here
814
      byte[] mag = new byte[len];
645
      byte[] mag = new byte[len];
815
      System.arraycopy(M, off, mag, 0, len);
646
      System.arraycopy(M, off, mag, 0, len);
816
      // Define constants used for fixing out-of-range words
647
      // Define constants used for fixing out-of-range words
817
      //         int wordbytes = wordbits / 8;
818
819
      BigInteger p = prime(wordbits);
648
      BigInteger p = prime(wordbits);
820
      BigInteger offset = TWO.pow(wordbits).subtract(p); // 2^wordbits - p;
649
      BigInteger offset = TWO.pow(wordbits).subtract(p); // 2^wordbits - p;
821
      BigInteger marker = p.subtract(BigInteger.ONE);
650
      BigInteger marker = p.subtract(BigInteger.ONE);
822
823
      // Break M into chunks of length wordbytes bytes
651
      // Break M into chunks of length wordbytes bytes
824
      //         long n = M.length / wordbytes;
652
      //         long n = M.length / wordbytes;
825
      // Let M_1, M_2, ..., M_n be strings of length wordbytes bytes
653
      // Let M_1, M_2, ..., M_n be strings of length wordbytes bytes
Lines 829-876 Link Here
829
      // then hash the words 'marker' and (m - offset), both in range.
657
      // then hash the words 'marker' and (m - offset), both in range.
830
      //         for (int i = 0; i < n; i++) {
658
      //         for (int i = 0; i < n; i++) {
831
      BigInteger m = new BigInteger(1, mag);
659
      BigInteger m = new BigInteger(1, mag);
832
      if (m.compareTo(maxwordrange) >= 0)
660
      if (m.compareTo(maxwordrange) >= 0) // m >= maxwordrange
833
        { // m >= maxwordrange
661
        {
834
          y = y.multiply(k).add(marker).mod(p); // (k * y + marker) % p;
662
          y = y.multiply(k).add(marker).mod(p); // (k * y + marker) % p;
835
          y = y.multiply(k).add(m.subtract(offset)).mod(p); // (k * y + (m - offset)) % p;
663
          y = y.multiply(k).add(m.subtract(offset)).mod(p); // (k * y + (m - offset)) % p;
836
        }
664
        }
837
      else
665
      else
838
        {
666
        y = y.multiply(k).add(m).mod(p); // (k * y + m) % p;
839
          y = y.multiply(k).add(m).mod(p); // (k * y + m) % p;
840
        }
841
      //         }
842
843
      //         return y;
844
    }
667
    }
845
  }
668
  }
846
669
847
  // =========================================================================
848
849
  /**
670
  /**
850
   * Third hash stage of the UHash32 algorithm.
671
   * Third hash stage of the UHash32 algorithm.
851
   *
672
   * <ul>
852
   * Input:
673
   * <li>Input:<br/>
853
   *    K1 string of length 64 bytes.
674
   * K1 string of length 64 bytes.<br/>
854
   *    K2 string of length 4 bytes.
675
   * K2 string of length 4 bytes.<br/>
855
   *    M string of length 16 bytes.
676
   * M string of length 16 bytes.</li>
856
   * Returns:
677
   * <li>Returns:<br/>
857
   *    Y, string of length 4 bytes.
678
   * Y, string of length 4 bytes.</li>
679
   * </ul>
858
   */
680
   */
859
  class L3Hash32 implements Cloneable
681
  class L3Hash32
682
      implements Cloneable
860
  {
683
  {
861
862
    // Constants and variables
863
    // ----------------------------------------------------------------------
864
865
    private static final long PRIME_36 = 0x0000000FFFFFFFFBL;
684
    private static final long PRIME_36 = 0x0000000FFFFFFFFBL;
866
867
    private int[] k = new int[9];
685
    private int[] k = new int[9];
868
686
869
    // Constructor(s)
870
    // ----------------------------------------------------------------------
871
872
    /**
687
    /**
873
     *
874
     * @param K1 string of length 64 bytes.
688
     * @param K1 string of length 64 bytes.
875
     * @param K2 string of length 4 bytes.
689
     * @param K2 string of length 4 bytes.
876
     */
690
     */
Lines 880-908 Link Here
880
694
881
      // pre-conditions
695
      // pre-conditions
882
      if (K1.length != 64)
696
      if (K1.length != 64)
883
        {
697
        throw new ExceptionInInitializerError("K1 length is not 64");
884
          throw new ExceptionInInitializerError("K1 length is not 64");
885
        }
886
      if (K2.length != 4)
698
      if (K2.length != 4)
887
        {
699
        throw new ExceptionInInitializerError("K2 length is not 4");
888
          throw new ExceptionInInitializerError("K2 length is not 4");
889
        }
890
891
      // Break K1 into 8 chunks and convert to integers
700
      // Break K1 into 8 chunks and convert to integers
892
      //         int i = 0;
893
      //         for (int j = 0; i < 8; ) {
894
      for (int i = 0, j = 0; i < 8; i++)
701
      for (int i = 0, j = 0; i < 8; i++)
895
        {
702
        {
896
          long kk = (K1[j++] & 0xFFL) << 56 | (K1[j++] & 0xFFL) << 48
703
          long kk = (K1[j++] & 0xFFL) << 56
897
                    | (K1[j++] & 0xFFL) << 40 | (K1[j++] & 0xFFL) << 32
704
                  | (K1[j++] & 0xFFL) << 48
898
                    | (K1[j++] & 0xFFL) << 24 | (K1[j++] & 0xFFL) << 16
705
                  | (K1[j++] & 0xFFL) << 40
899
                    | (K1[j++] & 0xFFL) << 8 | (K1[j++] & 0xFFL);
706
                  | (K1[j++] & 0xFFL) << 32
900
          //            k[i++] = (int)(kk % PRIME_36);
707
                  | (K1[j++] & 0xFFL) << 24
901
          k[i] = (int) (kk % PRIME_36);
708
                  | (K1[j++] & 0xFFL) << 16
902
        }
709
                  | (K1[j++] & 0xFFL) <<  8
903
      //         k[i] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8 | (K2[3] & 0xFF);
710
                  | (K1[j++] & 0xFFL);
904
      k[8] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8
711
          k[i] = (int)(kk % PRIME_36);
905
             | (K2[3] & 0xFF);
712
        }
713
      k[8] =  K2[0]         << 24
714
           | (K2[1] & 0xFF) << 16
715
           | (K2[2] & 0xFF) << 8
716
           | (K2[3] & 0xFF);
906
    }
717
    }
907
718
908
    private L3Hash32(int[] k)
719
    private L3Hash32(int[] k)
Lines 912-932 Link Here
912
      this.k = k;
723
      this.k = k;
913
    }
724
    }
914
725
915
    // Class methods
916
    // ----------------------------------------------------------------------
917
918
    // Instance methods
919
    // ----------------------------------------------------------------------
920
921
    // java.lang.Cloneable interface implementation -------------------------
922
923
    public Object clone()
726
    public Object clone()
924
    {
727
    {
925
      return new L3Hash32((int[]) k.clone());
728
      return new L3Hash32((int[]) k.clone());
926
    }
729
    }
927
730
928
    // other instance methods -----------------------------------------------
929
930
    /**
731
    /**
931
     * @param M string of length 16 bytes.
732
     * @param M string of length 16 bytes.
932
     * @return Y, string of length 4 bytes.
733
     * @return Y, string of length 4 bytes.
Lines 934-957 Link Here
934
    byte[] digest(byte[] M)
735
    byte[] digest(byte[] M)
935
    {
736
    {
936
      if (M.length != 16)
737
      if (M.length != 16)
937
        {
738
        throw new IllegalArgumentException("M length is not 16");
938
          throw new IllegalArgumentException("M length is not 16");
939
        }
940
739
941
      long m, y = 0L;
740
      long m, y = 0L;
942
      for (int i = 0, j = 0; i < 8; i++)
741
      for (int i = 0, j = 0; i < 8; i++)
943
        {
742
        {
944
          // Break M into 8 chunks and convert to integers
743
          // Break M into 8 chunks and convert to integers
945
          m = (M[j++] & 0xFFL) << 8 | (M[j++] & 0xFFL);
744
          m = (M[j++] & 0xFFL) << 8 | (M[j++] & 0xFFL);
946
947
          // Inner-product hash, extract last 32 bits and affine-translate
745
          // Inner-product hash, extract last 32 bits and affine-translate
948
          //            y = (m_1 * k_1 + ... + m_8 * k_8) mod prime(36);
746
          //            y = (m_1 * k_1 + ... + m_8 * k_8) mod prime(36);
949
          //            y = y mod 2^32;
747
          //            y = y mod 2^32;
950
          y += (m * (k[i] & 0xFFFFFFFFL)) % PRIME_36;
748
          y += (m * (k[i] & 0xFFFFFFFFL)) % PRIME_36;
951
        }
749
        }
952
      int Y = ((int) y) ^ k[8];
750
      int Y = ((int) y) ^ k[8];
953
      return new byte[] { (byte) (Y >>> 24), (byte) (Y >>> 16),
751
      return new byte[] {
954
                         (byte) (Y >>> 8), (byte) Y };
752
          (byte)(Y >>> 24),
753
          (byte)(Y >>> 16),
754
          (byte)(Y >>> 8),
755
          (byte) Y };
955
    }
756
    }
956
  }
757
  }
957
}
758
}
(-)UMac32.java (-179 / +106 lines)
Lines 53-175 Link Here
53
import java.util.Map;
53
import java.util.Map;
54
54
55
/**
55
/**
56
 * <p>The implementation of the <i>UMAC</i> (Universal Message Authentication
56
 * The implementation of the <i>UMAC</i> (Universal Message Authentication
57
 * Code).</p>
57
 * Code).
58
 *
58
 * <p>
59
 * <p>The <i>UMAC</i> algorithms described are <i>parameterized</i>. This means
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
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
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
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
63
 * a given message, key, and nonce) becomes fully-defined. In this document we
64
 * we provide two collections of parameter settings, and have named the sets
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 on
65
 * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based
66
 * experimentation and provide good performance on a wide variety of processors.
66
 * on experimentation and provide good performance on a wide variety of
67
 * <i>UMAC16</i> is designed to excel on processors which provide small-scale
67
 * processors. <i>UMAC16</i> is designed to excel on processors which provide
68
 * SIMD parallelism of the type found in Intel's MMX and Motorola's AltiVec
68
 * small-scale SIMD parallelism of the type found in Intel's MMX and Motorola's
69
 * instruction sets, while <i>UMAC32</i> is designed to do well on processors
69
 * AltiVec instruction sets, while <i>UMAC32</i> is designed to do well on
70
 * with good 32- and 64- bit support. <i>UMAC32</i> may take advantage of SIMD
70
 * processors with good 32- and 64- bit support. <i>UMAC32</i> may take
71
 * parallelism in future processors.</p>
71
 * advantage of SIMD parallelism in future processors.
72
 *
72
 * <p>
73
 * <p><i>UMAC</i> has been designed to allow implementations which accommodate
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
74
 * <i>on-line</i> authentication. This means that pieces of the message may be
75
 * be presented to <i>UMAC</i> at different times (but in correct order) and an
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
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
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
78
 * simplicity, the algorithms in this specification are presented as if the
79
 * entire message being authenticated were available at once.</p>
79
 * entire message being authenticated were available at once.
80
 *
80
 * <p>
81
 * <p>To authenticate a message, <code>Msg</code>, one first applies the
81
 * To authenticate a message, <code>Msg</code>, one first applies the
82
 * universal hash function, resulting in a string which is typically much
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
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
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
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
86
 * output from the pseudorandom function. Thus, an authentication tag is
87
 * generated as</p>
87
 * generated as
88
 *
89
 * <pre>
88
 * <pre>
90
 *    AuthTag = f(Nonce) xor h(Msg)
89
 *     AuthTag = f(Nonce) xor h(Msg)
91
 * </pre>
90
 * </pre>
92
 *
91
 * <p>
93
 * <p>Here <code>f</code> is the pseudorandom function shared between the sender
92
 * Here <code>f</code> is the pseudorandom function shared between the sender
94
 * and the receiver, and h is a universal hash function shared by the sender and
93
 * and the receiver, and h is a universal hash function shared by the sender and
95
 * the receiver. In <i>UMAC</i>, a shared key is used to key the pseudorandom
94
 * the receiver. In <i>UMAC</i>, a shared key is used to key the pseudorandom
96
 * function <code>f</code>, and then <code>f</code> is used for both tag
95
 * function <code>f</code>, and then <code>f</code> is used for both tag
97
 * generation and internally to generate all of the bits needed by the universal
96
 * generation and internally to generate all of the bits needed by the universal
98
 * hash function.</p>
97
 * hash function.
99
 *
98
 * <p>
100
 * <p>The universal hash function that we use is called <code>UHASH</code>. It
99
 * The universal hash function that we use is called <code>UHASH</code>. It
101
 * combines several software-optimized algorithms into a multi-layered
100
 * combines several software-optimized algorithms into a multi-layered
102
 * structure. The algorithm is moderately complex. Some of this complexity comes
101
 * structure. The algorithm is moderately complex. Some of this complexity comes
103
 * from extensive speed optimizations.</p>
102
 * from extensive speed optimizations.
104
 *
103
 * <p>
105
 * <p>For the pseudorandom function we use the block cipher of the <i>Advanced
104
 * For the pseudorandom function we use the block cipher of the <i>Advanced
106
 * Encryption Standard</i> (AES).</p>
105
 * Encryption Standard</i> (AES).
107
 *
106
 * <p>
108
 * <p>The UMAC32 parameters, considered in this implementation are:</p>
107
 * The UMAC32 parameters, considered in this implementation are:
109
 * <pre>
108
 * <pre>
110
 *                                   UMAC32
109
 *                                    UMAC32
111
 *                                   ------
110
 *                                    ------
112
 *        WORD-LEN                        4
111
 *         WORD-LEN                        4
113
 *        UMAC-OUTPUT-LEN                 8
112
 *         UMAC-OUTPUT-LEN                 8
114
 *        L1-KEY-LEN                   1024
113
 *         L1-KEY-LEN                   1024
115
 *        UMAC-KEY-LEN                   16
114
 *         UMAC-KEY-LEN                   16
116
 *        ENDIAN-FAVORITE               BIG *
115
 *         ENDIAN-FAVORITE               BIG *
117
 *        L1-OPERATIONS-SIGN       UNSIGNED
116
 *         L1-OPERATIONS-SIGN       UNSIGNED
118
 * </pre>
117
 * </pre>
119
 *
118
 * <p>
120
 * <p>Please note that this UMAC32 differs from the one described in the paper
119
 * Please note that this UMAC32 differs from the one described in the paper by
121
 * by the <i>ENDIAN-FAVORITE</i> value.</p>
120
 * the <i>ENDIAN-FAVORITE</i> value.
122
 *
121
 * <p>
123
 * <p>References:</p>
122
 * References:
124
 *
125
 * <ol>
123
 * <ol>
126
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
124
 * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
127
 *    UMAC</a>: Message Authentication Code using Universal Hashing.<br>
125
 * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
128
 *    T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
126
 * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
129
 * </ol>
127
 * </ol>
130
 */
128
 */
131
public class UMac32 extends BaseMac
129
public class UMac32
130
    extends BaseMac
132
{
131
{
133
134
  // Constants and variables
135
  // -------------------------------------------------------------------------
136
137
  /**
132
  /**
138
   * Property name of the user-supplied <i>Nonce</i>. The value associated to
133
   * Property name of the user-supplied <i>Nonce</i>. The value associated to
139
   * this property name is taken to be a byte array.
134
   * this property name is taken to be a byte array.
140
   */
135
   */
141
  public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material";
136
  public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material";
142
143
  /** Known test vector. */
137
  /** Known test vector. */
144
  //   private static final String TV1 = "3E5A0E09198B0F94";
138
  // private static final String TV1 = "3E5A0E09198B0F94";
145
  //   private static final String TV1 = "5FD764A6D3A9FD9D";
139
  // private static final String TV1 = "5FD764A6D3A9FD9D";
146
  //   private static final String TV1 = "48658DE1D9A70304";
140
  // private static final String TV1 = "48658DE1D9A70304";
147
  private static final String TV1 = "455ED214A6909F20";
141
  private static final String TV1 = "455ED214A6909F20";
148
149
  private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8);
142
  private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8);
150
151
  // UMAC32 parameters
143
  // UMAC32 parameters
152
  static final int OUTPUT_LEN = 8;
144
  static final int OUTPUT_LEN = 8;
153
154
  static final int L1_KEY_LEN = 1024;
145
  static final int L1_KEY_LEN = 1024;
155
156
  static final int KEY_LEN = 16;
146
  static final int KEY_LEN = 16;
157
158
  /** caches the result of the correctness test, once executed. */
147
  /** caches the result of the correctness test, once executed. */
159
  private static Boolean valid;
148
  private static Boolean valid;
160
161
  private byte[] nonce;
149
  private byte[] nonce;
162
163
  private UHash32 uhash32;
150
  private UHash32 uhash32;
164
165
  private BigInteger nonceReuseCount;
151
  private BigInteger nonceReuseCount;
166
167
  /** The authentication key for this instance. */
152
  /** The authentication key for this instance. */
168
  private transient byte[] K;
153
  private transient byte[] K;
169
154
170
  // Constructor(s)
171
  // -------------------------------------------------------------------------
172
173
  /** Trivial 0-arguments constructor. */
155
  /** Trivial 0-arguments constructor. */
174
  public UMac32()
156
  public UMac32()
175
  {
157
  {
Lines 177-184 Link Here
177
  }
159
  }
178
160
179
  /**
161
  /**
180
   * <p>Private constructor for cloning purposes.</p>
162
   * Private constructor for cloning purposes.
181
   *
163
   * 
182
   * @param that the instance to clone.
164
   * @param that the instance to clone.
183
   */
165
   */
184
  private UMac32(UMac32 that)
166
  private UMac32(UMac32 that)
Lines 186-321 Link Here
186
    this();
168
    this();
187
169
188
    if (that.K != null)
170
    if (that.K != null)
189
      {
171
      this.K = (byte[]) that.K.clone();
190
        this.K = (byte[]) that.K.clone();
191
      }
192
    if (that.nonce != null)
172
    if (that.nonce != null)
193
      {
173
      this.nonce = (byte[]) that.nonce.clone();
194
        this.nonce = (byte[]) that.nonce.clone();
195
      }
196
    if (that.uhash32 != null)
174
    if (that.uhash32 != null)
197
      {
175
      this.uhash32 = (UHash32) that.uhash32.clone();
198
        this.uhash32 = (UHash32) that.uhash32.clone();
199
      }
200
    this.nonceReuseCount = that.nonceReuseCount;
176
    this.nonceReuseCount = that.nonceReuseCount;
201
  }
177
  }
202
178
203
  // Class methods
204
  // -------------------------------------------------------------------------
205
206
  // Instance methods
207
  // -------------------------------------------------------------------------
208
209
  // java.lang.Cloneable interface implementation ----------------------------
210
211
  public Object clone()
179
  public Object clone()
212
  {
180
  {
213
    return new UMac32(this);
181
    return new UMac32(this);
214
  }
182
  }
215
183
216
  // gnu.crypto.mac.IMac interface implementation ----------------------------
217
218
  public int macSize()
184
  public int macSize()
219
  {
185
  {
220
    return OUTPUT_LEN;
186
    return OUTPUT_LEN;
221
  }
187
  }
222
188
223
  /**
189
  /**
224
   * <p>Initialising a <i>UMAC</i> instance consists of defining values for
190
   * Initialising a <i>UMAC</i> instance consists of defining values for the
225
   * the following parameters:</p>
191
   * following parameters:
226
   *
227
   * <ol>
192
   * <ol>
228
   *    <li>Key Material: as the value of the attribute entry keyed by
193
   * <li>Key Material: as the value of the attribute entry keyed by
229
   *    {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array
194
   * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array
230
   *    containing the user-specified key material. The length of this array,
195
   * containing the user-specified key material. The length of this array,
231
   *    if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li>
196
   * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li>
232
   *
197
   * <li>Nonce Material: as the value of the attribute entry keyed by
233
   *    <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
234
   *    {@link #NONCE_MATERIAL}. The value is taken to be a byte array
199
   * the user-specified nonce material. The length of this array, if/when
235
   *    containing the user-specified nonce material. The length of this array,
200
   * defined SHOULD be (a) greater than zero, and (b) less or equal to 16 (the
236
   *    if/when defined SHOULD be (a) greater than zero, and (b) less or equal
201
   * size of the AES block).</li>
237
   *    to 16 (the size of the AES block).</li>
238
   * </ol>
202
   * </ol>
239
   *
203
   * <p>
240
   * <p>For convenience, this implementation accepts that not both parameters
204
   * For convenience, this implementation accepts that not both parameters be
241
   * be always specified.</p>
205
   * always specified.
242
   *
243
   * <ul>
206
   * <ul>
244
   *    <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i>
207
   * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i>
245
   *    is not, then this implementation, re-uses the previously set <i>Nonce
208
   * is not, then this implementation, re-uses the previously set <i>Nonce
246
   *    Material</i> after (a) converting the bytes to an unsigned integer,
209
   * Material</i> after (a) converting the bytes to an unsigned integer, (b)
247
   *    (b) incrementing the number by one, and (c) converting it back to 16
210
   * incrementing the number by one, and (c) converting it back to 16 bytes.</li>
248
   *    bytes.</li>
211
   * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i>
249
   *
212
   * is not, then this implementation re-uses the previously set <i>Key Material</i>.
250
   *    <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i>
213
   * </li>
251
   *    is not, then this implementation re-uses the previously set <i>Key
252
   *    Material</i>.</li>
253
   * </ul>
214
   * </ul>
254
   *
215
   * <p>
255
   * <p>This method throws an exception if no <i>Key Material</i> is specified
216
   * This method throws an exception if no <i>Key Material</i> is specified in
256
   * in the input map, and there is no previously set/defined <i>Key Material</i>
217
   * the input map, and there is no previously set/defined <i>Key Material</i>
257
   * (from an earlier invocation of this method). If a <i>Key Material</i> can
218
   * (from an earlier invocation of this method). If a <i>Key Material</i> can
258
   * be used, but no <i>Nonce Material</i> is defined or previously set/defined,
219
   * be used, but no <i>Nonce Material</i> is defined or previously
259
   * then a default value of all-zeroes shall be used.</p>
220
   * set/defined, then a default value of all-zeroes shall be used.
260
   *
221
   * 
261
   * @param attributes one or both of required parameters.
222
   * @param attributes one or both of required parameters.
262
   * @throws InvalidKeyException the key material specified is not of the
223
   * @throws InvalidKeyException the key material specified is not of the
263
   * correct length.
224
   *           correct length.
264
   */
225
   */
265
  public void init(Map attributes) throws InvalidKeyException,
226
  public void init(Map attributes) throws InvalidKeyException,
266
      IllegalStateException
227
      IllegalStateException
267
  {
228
  {
268
    byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL);
229
    byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL);
269
    byte[] n = (byte[]) attributes.get(NONCE_MATERIAL);
230
    byte[] n = (byte[]) attributes.get(NONCE_MATERIAL);
270
271
    boolean newKey = (key != null);
231
    boolean newKey = (key != null);
272
    boolean newNonce = (n != null);
232
    boolean newNonce = (n != null);
273
274
    if (newKey)
233
    if (newKey)
275
      {
234
      {
276
        if (key.length != KEY_LEN)
235
        if (key.length != KEY_LEN)
277
          {
236
          throw new InvalidKeyException("Key length: "
278
            throw new InvalidKeyException("Key length: "
237
                                        + String.valueOf(key.length));
279
                                          + String.valueOf(key.length));
280
          }
281
        K = key;
238
        K = key;
282
      }
239
      }
283
    else
240
    else
284
      {
241
      {
285
        if (K == null)
242
        if (K == null)
286
          {
243
          throw new InvalidKeyException("Null Key");
287
            throw new InvalidKeyException("Null Key");
288
          }
289
      }
244
      }
290
291
    if (newNonce)
245
    if (newNonce)
292
      {
246
      {
293
        if (n.length < 1 || n.length > 16)
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
294
          {
251
          {
295
            throw new IllegalArgumentException("Invalid Nonce length: "
296
                                               + String.valueOf(n.length));
297
          }
298
299
        if (n.length < 16)
300
          { // pad with zeroes
301
            byte[] newN = new byte[16];
252
            byte[] newN = new byte[16];
302
            System.arraycopy(n, 0, newN, 0, n.length);
253
            System.arraycopy(n, 0, newN, 0, n.length);
303
            nonce = newN;
254
            nonce = newN;
304
          }
255
          }
305
        else
256
        else
306
          {
257
          nonce = n;
307
            nonce = n;
308
          }
309
258
310
        nonceReuseCount = BigInteger.ZERO;
259
        nonceReuseCount = BigInteger.ZERO;
311
      }
260
      }
312
    else if (nonce == null)
261
    else if (nonce == null) // use all-0 nonce if 1st time
313
      { // use all-0 nonce if 1st time
262
      {
314
        nonce = new byte[16];
263
        nonce = new byte[16];
315
        nonceReuseCount = BigInteger.ZERO;
264
        nonceReuseCount = BigInteger.ZERO;
316
      }
265
      }
317
    else if (!newKey)
266
    else if (! newKey) // increment nonce if still below max count
318
      { // increment nonce if still below max count
267
      {
319
        nonceReuseCount = nonceReuseCount.add(BigInteger.ONE);
268
        nonceReuseCount = nonceReuseCount.add(BigInteger.ONE);
320
        if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0)
269
        if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0)
321
          {
270
          {
Lines 326-334 Link Here
326
        N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS);
275
        N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS);
327
        n = N.toByteArray();
276
        n = N.toByteArray();
328
        if (n.length == 16)
277
        if (n.length == 16)
329
          {
278
          nonce = n;
330
            nonce = n;
331
          }
332
        else if (n.length < 16)
279
        else if (n.length < 16)
333
          {
280
          {
334
            nonce = new byte[16];
281
            nonce = new byte[16];
Lines 340-354 Link Here
340
            System.arraycopy(n, n.length - 16, nonce, 0, 16);
287
            System.arraycopy(n, n.length - 16, nonce, 0, 16);
341
          }
288
          }
342
      }
289
      }
343
    else
290
    else // do nothing, re-use old nonce value
344
      { // do nothing, re-use old nonce value
291
      nonceReuseCount = BigInteger.ZERO;
345
        nonceReuseCount = BigInteger.ZERO;
346
      }
347
292
348
    if (uhash32 == null)
293
    if (uhash32 == null)
349
      {
294
      uhash32 = new UHash32();
350
        uhash32 = new UHash32();
351
      }
352
295
353
    Map map = new HashMap();
296
    Map map = new HashMap();
354
    map.put(MAC_KEY_MATERIAL, K);
297
    map.put(MAC_KEY_MATERIAL, K);
Lines 370-378 Link Here
370
    byte[] result = uhash32.digest();
313
    byte[] result = uhash32.digest();
371
    byte[] pad = pdf(); // pdf(K, nonce);
314
    byte[] pad = pdf(); // pdf(K, nonce);
372
    for (int i = 0; i < OUTPUT_LEN; i++)
315
    for (int i = 0; i < OUTPUT_LEN; i++)
373
      {
316
      result[i] = (byte)(result[i] ^ pad[i]);
374
        result[i] = (byte) (result[i] ^ pad[i]);
375
      }
376
317
377
    return result;
318
    return result;
378
  }
319
  }
Lines 380-388 Link Here
380
  public void reset()
321
  public void reset()
381
  {
322
  {
382
    if (uhash32 != null)
323
    if (uhash32 != null)
383
      {
324
      uhash32.reset();
384
        uhash32.reset();
385
      }
386
  }
325
  }
387
326
388
  public boolean selfTest()
327
  public boolean selfTest()
Lines 412-454 Link Here
412
            x.printStackTrace(System.err);
351
            x.printStackTrace(System.err);
413
            return false;
352
            return false;
414
          }
353
          }
415
416
        byte[] data = new byte[128];
354
        byte[] data = new byte[128];
417
        data[0] = (byte) 0x80;
355
        data[0] = (byte) 0x80;
418
419
        mac.update(data, 0, 128);
356
        mac.update(data, 0, 128);
420
        byte[] result = mac.digest();
357
        byte[] result = mac.digest();
421
        //         System.out.println("UMAC test vector: "+Util.toString(result));
422
        valid = Boolean.valueOf(TV1.equals(Util.toString(result)));
358
        valid = Boolean.valueOf(TV1.equals(Util.toString(result)));
423
      }
359
      }
424
    return valid.booleanValue();
360
    return valid.booleanValue();
425
  }
361
  }
426
362
427
  // helper methods ----------------------------------------------------------
428
429
  /**
363
  /**
430
   *
431
   * @return byte array of length 8 (or OUTPUT_LEN) bytes.
364
   * @return byte array of length 8 (or OUTPUT_LEN) bytes.
432
   */
365
   */
433
  private byte[] pdf()
366
  private byte[] pdf()
434
  {
367
  {
435
    // Make Nonce 16 bytes by prepending zeroes. done (see init())
368
    // Make Nonce 16 bytes by prepending zeroes. done (see init())
436
437
    // one AES invocation is enough for more than one PDF invocation
369
    // one AES invocation is enough for more than one PDF invocation
438
    // number of index bits needed = 1
370
    // number of index bits needed = 1
439
440
    // Extract index bits and zero low bits of Nonce
371
    // Extract index bits and zero low bits of Nonce
441
    BigInteger Nonce = new BigInteger(1, nonce);
372
    BigInteger Nonce = new BigInteger(1, nonce);
442
    int nlowbitsnum = Nonce.testBit(0) ? 1 : 0;
373
    int nlowbitsnum = Nonce.testBit(0) ? 1 : 0;
443
    Nonce = Nonce.clearBit(0);
374
    Nonce = Nonce.clearBit(0);
444
445
    // Generate subkey, AES and extract indexed substring
375
    // Generate subkey, AES and extract indexed substring
446
    IRandom kdf = new UMacGenerator();
376
    IRandom kdf = new UMacGenerator();
447
    Map map = new HashMap();
377
    Map map = new HashMap();
448
    map.put(IBlockCipher.KEY_MATERIAL, K);
378
    map.put(IBlockCipher.KEY_MATERIAL, K);
449
    //      map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(128/8));
450
    map.put(UMacGenerator.INDEX, Integer.valueOf(128));
379
    map.put(UMacGenerator.INDEX, Integer.valueOf(128));
451
    //      map.put(UMacGenerator.CIPHER, Registry.AES_CIPHER);
452
    kdf.init(map);
380
    kdf.init(map);
453
    byte[] Kp = new byte[KEY_LEN];
381
    byte[] Kp = new byte[KEY_LEN];
454
    try
382
    try
Lines 485-491 Link Here
485
    aes.encryptBlock(nonce, 0, T, 0);
413
    aes.encryptBlock(nonce, 0, T, 0);
486
    byte[] result = new byte[OUTPUT_LEN];
414
    byte[] result = new byte[OUTPUT_LEN];
487
    System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN);
415
    System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN);
488
489
    return result;
416
    return result;
490
  }
417
  }
491
}
418
}

Return to bug 26067