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

Collapse All | Expand All

(-)BaseMode.java (-100 / +41 lines)
Lines 49-94 Link Here
49
import java.util.Map;
49
import java.util.Map;
50
50
51
/**
51
/**
52
 * <p>A basic abstract class to facilitate implementing block cipher modes of
52
 * A basic abstract class to facilitate implementing block cipher modes of
53
 * operations.</p>
53
 * operations.
54
 */
54
 */
55
public abstract class BaseMode implements IMode
55
public abstract class BaseMode
56
    implements IMode
56
{
57
{
57
58
  // Constants and variables
59
  // -------------------------------------------------------------------------
60
61
  /** The canonical name prefix of this mode. */
58
  /** The canonical name prefix of this mode. */
62
  protected String name;
59
  protected String name;
63
64
  /** The state indicator of this instance. */
60
  /** The state indicator of this instance. */
65
  protected int state;
61
  protected int state;
66
67
  /** The underlying block cipher implementation. */
62
  /** The underlying block cipher implementation. */
68
  protected IBlockCipher cipher;
63
  protected IBlockCipher cipher;
69
70
  /** The block size, in bytes, to operate the underlying block cipher in. */
64
  /** The block size, in bytes, to operate the underlying block cipher in. */
71
  protected int cipherBlockSize;
65
  protected int cipherBlockSize;
72
73
  /** The block size, in bytes, in which to operate the mode instance. */
66
  /** The block size, in bytes, in which to operate the mode instance. */
74
  protected int modeBlockSize;
67
  protected int modeBlockSize;
75
76
  /** The initialisation vector value. */
68
  /** The initialisation vector value. */
77
  protected byte[] iv;
69
  protected byte[] iv;
78
79
  /** The instance lock. */
70
  /** The instance lock. */
80
  protected Object lock = new Object();
71
  protected Object lock = new Object();
81
72
82
  // Constructor(s)
83
  // -------------------------------------------------------------------------
84
85
  /**
73
  /**
86
   * <p>Trivial constructor for use by concrete subclasses.</p>
74
   * Trivial constructor for use by concrete subclasses.
87
   *
75
   * 
88
   * @param name the canonical name prefix of this mode.
76
   * @param name the canonical name prefix of this mode.
89
   * @param underlyingCipher the implementation of the underlying cipher.
77
   * @param underlyingCipher the implementation of the underlying cipher.
90
   * @param cipherBlockSize the block size, in bytes, in which to operate the
78
   * @param cipherBlockSize the block size, in bytes, in which to operate the
91
   * underlying cipher.
79
   *          underlying cipher.
92
   */
80
   */
93
  protected BaseMode(String name, IBlockCipher underlyingCipher,
81
  protected BaseMode(String name, IBlockCipher underlyingCipher,
94
                     int cipherBlockSize)
82
                     int cipherBlockSize)
Lines 101-114 Link Here
101
    state = -1;
89
    state = -1;
102
  }
90
  }
103
91
104
  // Class methods
105
  // -------------------------------------------------------------------------
106
107
  // Instance methods
108
  // -------------------------------------------------------------------------
109
110
  // IMode interface implementation ------------------------------------------
111
112
  public void update(byte[] in, int inOffset, byte[] out, int outOffset)
92
  public void update(byte[] in, int inOffset, byte[] out, int outOffset)
113
      throws IllegalStateException
93
      throws IllegalStateException
114
  {
94
  {
Lines 128-150 Link Here
128
      }
108
      }
129
  }
109
  }
130
110
131
  // IBlockCipher interface implementation -----------------------------------
132
133
  public String name()
111
  public String name()
134
  {
112
  {
135
    return new StringBuffer().append(name).append('(').append(cipher.name()).append(
113
    return new StringBuffer(name).append('(').append(cipher.name()).append(')')
136
                                                                                    ')').toString();
114
        .toString();
137
  }
115
  }
138
116
139
  /**
117
  /**
140
   * <p>Returns the default value, in bytes, of the mode's block size. This
118
   * Returns the default value, in bytes, of the mode's block size. This value
141
   * value is part of the construction arguments passed to the Factory methods
119
   * is part of the construction arguments passed to the Factory methods in
142
   * in {@link ModeFactory}. Unless changed by an invocation of any of the
120
   * {@link ModeFactory}. Unless changed by an invocation of any of the
143
   * <code>init()</code> methods, a <i>Mode</i> instance would operate with
121
   * <code>init()</code> methods, a <i>Mode</i> instance would operate with
144
   * the same block size as its underlying block cipher. As mentioned earlier,
122
   * the same block size as its underlying block cipher. As mentioned earlier,
145
   * the block size of the underlying block cipher itself is specified in one
123
   * the block size of the underlying block cipher itself is specified in one of
146
   * of the method(s) available in the factory class.</p>
124
   * the method(s) available in the factory class.
147
   *
125
   * 
148
   * @return the default value, in bytes, of the mode's block size.
126
   * @return the default value, in bytes, of the mode's block size.
149
   * @see ModeFactory
127
   * @see ModeFactory
150
   */
128
   */
Lines 154-162 Link Here
154
  }
132
  }
155
133
156
  /**
134
  /**
157
   * <p>Returns the default value, in bytes, of the underlying block cipher
135
   * Returns the default value, in bytes, of the underlying block cipher key
158
   * key size.</p>
136
   * size.
159
   *
137
   * 
160
   * @return the default value, in bytes, of the underlying cipher's key size.
138
   * @return the default value, in bytes, of the underlying cipher's key size.
161
   */
139
   */
162
  public int defaultKeySize()
140
  public int defaultKeySize()
Lines 165-193 Link Here
165
  }
143
  }
166
144
167
  /**
145
  /**
168
   * <p>Returns an {@link Iterator} over the supported block sizes. Each
146
   * Returns an {@link Iterator} over the supported block sizes. Each element
169
   * element returned by this object is an {@link Integer}.</p>
147
   * returned by this object is an {@link Integer}.
170
   *
148
   * <p>
171
   * <p>The default behaviour is to return an iterator with just one value,
149
   * The default behaviour is to return an iterator with just one value, which
172
   * which is that currently configured for the underlying block cipher.
150
   * is that currently configured for the underlying block cipher. Concrete
173
   * Concrete implementations may override this behaviour to signal their
151
   * implementations may override this behaviour to signal their ability to
174
   * ability to support other values.</p>
152
   * support other values.
175
   *
153
   * 
176
   * @return an {@link Iterator} over the supported block sizes.
154
   * @return an {@link Iterator} over the supported block sizes.
177
   */
155
   */
178
  public Iterator blockSizes()
156
  public Iterator blockSizes()
179
  {
157
  {
180
    ArrayList al = new ArrayList();
158
    ArrayList al = new ArrayList();
181
    al.add(Integer.valueOf(cipherBlockSize));
159
    al.add(Integer.valueOf(cipherBlockSize));
182
183
    return Collections.unmodifiableList(al).iterator();
160
    return Collections.unmodifiableList(al).iterator();
184
  }
161
  }
185
162
186
  /**
163
  /**
187
   * <p>Returns an {@link Iterator} over the supported underlying block cipher
164
   * Returns an {@link Iterator} over the supported underlying block cipher key
188
   * key sizes. Each element returned by this object is an instance of
165
   * sizes. Each element returned by this object is an instance of
189
   * {@link Integer}.</p>
166
   * {@link Integer}.
190
   *
167
   * 
191
   * @return an {@link Iterator} over the supported key sizes.
168
   * @return an {@link Iterator} over the supported key sizes.
192
   */
169
   */
193
  public Iterator keySizes()
170
  public Iterator keySizes()
Lines 201-210 Link Here
201
    synchronized (lock)
178
    synchronized (lock)
202
      {
179
      {
203
        if (state != -1)
180
        if (state != -1)
204
          {
181
          throw new IllegalStateException();
205
            throw new IllegalStateException();
206
          }
207
208
        Integer want = (Integer) attributes.get(STATE);
182
        Integer want = (Integer) attributes.get(STATE);
209
        if (want != null)
183
        if (want != null)
210
          {
184
          {
Lines 220-239 Link Here
220
                throw new IllegalArgumentException();
194
                throw new IllegalArgumentException();
221
              }
195
              }
222
          }
196
          }
223
224
        Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
197
        Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
225
        modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
198
        modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
226
227
        byte[] iv = (byte[]) attributes.get(IV);
199
        byte[] iv = (byte[]) attributes.get(IV);
228
        if (iv != null)
200
        if (iv != null)
229
          {
201
          this.iv = (byte[]) iv.clone();
230
            this.iv = (byte[]) iv.clone();
231
          }
232
        else
202
        else
233
          {
203
          this.iv = new byte[modeBlockSize];
234
            this.iv = new byte[modeBlockSize];
235
          }
236
237
        cipher.init(attributes);
204
        cipher.init(attributes);
238
        setup();
205
        setup();
239
      }
206
      }
Lines 242-250 Link Here
242
  public int currentBlockSize()
209
  public int currentBlockSize()
243
  {
210
  {
244
    if (state == -1)
211
    if (state == -1)
245
      {
212
      throw new IllegalStateException();
246
        throw new IllegalStateException();
247
      }
248
    return modeBlockSize;
213
    return modeBlockSize;
249
  }
214
  }
250
215
Lines 255-261 Link Here
255
        state = -1;
220
        state = -1;
256
        iv = null;
221
        iv = null;
257
        cipher.reset();
222
        cipher.reset();
258
259
        teardown();
223
        teardown();
260
      }
224
      }
261
  }
225
  }
Lines 268-286 Link Here
268
      {
232
      {
269
        ks = ((Integer) kit.next()).intValue();
233
        ks = ((Integer) kit.next()).intValue();
270
        for (bit = blockSizes(); bit.hasNext();)
234
        for (bit = blockSizes(); bit.hasNext();)
271
          {
235
          if (! testSymmetry(ks, ((Integer) bit.next()).intValue()))
272
            if (!testSymmetry(ks, ((Integer) bit.next()).intValue()))
236
            return false;
273
              {
274
                return false;
275
              }
276
          }
277
      }
237
      }
278
279
    return true;
238
    return true;
280
  }
239
  }
281
240
282
  // methods to be implemented by concrete subclasses ------------------------
283
284
  public abstract Object clone();
241
  public abstract Object clone();
285
242
286
  /** The initialisation phase of the concrete mode implementation. */
243
  /** The initialisation phase of the concrete mode implementation. */
Lines 293-300 Link Here
293
250
294
  public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
251
  public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
295
252
296
  // own methods -------------------------------------------------------------
297
298
  private boolean testSymmetry(int ks, int bs)
253
  private boolean testSymmetry(int ks, int bs)
299
  {
254
  {
300
    try
255
    try
Lines 304-347 Link Here
304
        byte[] k = new byte[ks];
259
        byte[] k = new byte[ks];
305
        int i;
260
        int i;
306
        for (i = 0; i < ks; i++)
261
        for (i = 0; i < ks; i++)
307
          {
262
          k[i] = (byte) i;
308
            k[i] = (byte) i;
309
          }
310
311
        int blockCount = 5;
263
        int blockCount = 5;
312
        int limit = blockCount * bs;
264
        int limit = blockCount * bs;
313
        byte[] pt = new byte[limit];
265
        byte[] pt = new byte[limit];
314
        for (i = 0; i < limit; i++)
266
        for (i = 0; i < limit; i++)
315
          {
267
          pt[i] = (byte) i;
316
            pt[i] = (byte) i;
317
          }
318
        byte[] ct = new byte[limit];
268
        byte[] ct = new byte[limit];
319
        byte[] cpt = new byte[limit];
269
        byte[] cpt = new byte[limit];
320
321
        Map map = new HashMap();
270
        Map map = new HashMap();
322
        map.put(KEY_MATERIAL, k);
271
        map.put(KEY_MATERIAL, k);
323
        map.put(CIPHER_BLOCK_SIZE, Integer.valueOf(cipherBlockSize));
272
        map.put(CIPHER_BLOCK_SIZE, Integer.valueOf(cipherBlockSize));
324
        map.put(STATE, Integer.valueOf(ENCRYPTION));
273
        map.put(STATE, Integer.valueOf(ENCRYPTION));
325
        map.put(IV, iv);
274
        map.put(IV, iv);
326
        map.put(MODE_BLOCK_SIZE, Integer.valueOf(bs));
275
        map.put(MODE_BLOCK_SIZE, Integer.valueOf(bs));
327
328
        mode.reset();
276
        mode.reset();
329
        mode.init(map);
277
        mode.init(map);
330
        for (i = 0; i < blockCount; i++)
278
        for (i = 0; i < blockCount; i++)
331
          {
279
          mode.update(pt, i * bs, ct, i * bs);
332
            mode.update(pt, i * bs, ct, i * bs);
333
          }
334
335
        mode.reset();
280
        mode.reset();
336
        map.put(STATE, Integer.valueOf(DECRYPTION));
281
        map.put(STATE, Integer.valueOf(DECRYPTION));
337
        mode.init(map);
282
        mode.init(map);
338
        for (i = 0; i < blockCount; i++)
283
        for (i = 0; i < blockCount; i++)
339
          {
284
          mode.update(ct, i * bs, cpt, i * bs);
340
            mode.update(ct, i * bs, cpt, i * bs);
341
          }
342
343
        return Arrays.equals(pt, cpt);
285
        return Arrays.equals(pt, cpt);
344
345
      }
286
      }
346
    catch (Exception x)
287
    catch (Exception x)
347
      {
288
      {
Lines 349-352 Link Here
349
        return false;
290
        return false;
350
      }
291
      }
351
  }
292
  }
352
}
293
}
(-)CBC.java (-41 / +21 lines)
Lines 42-77 Link Here
42
import gnu.javax.crypto.cipher.IBlockCipher;
42
import gnu.javax.crypto.cipher.IBlockCipher;
43
43
44
/**
44
/**
45
 * The Cipher Block Chaining mode. This mode introduces feedback into
45
 * The Cipher Block Chaining mode. This mode introduces feedback into the cipher
46
 * the cipher by XORing the previous ciphertext block with the plaintext
46
 * by XORing the previous ciphertext block with the plaintext block before
47
 * block before encipherment. That is, encrypting looks like this:</p>
47
 * encipherment. That is, encrypting looks like this:
48
 *
48
 * 
49
 * <blockquote><p>C<sub>i</sub> = E<sub>K</sub>(P<sub>i</sub> ^
49
 * <pre>
50
 * C<sub>i-1</sub></p></blockquote>
50
 *  C<sub>i</sub> = E<sub>K</sub>(P<sub>i</sub>&circ; C<sub>i-1</sub>)
51
 *
51
 * </pre>
52
 * <p>Similarly, decrypting is:</p>
52
 * <p>
53
 *
53
 * Similarly, decrypting is:
54
 * <blockquote><p>P<sub>i</sub> = C<sub>i-1</sub> ^
54
 * <pre>
55
 * D<sub>K</sub>(C<sub>i</sub>)</p></blockquote>
55
 *  P<sub>i</sub> = C<sub>i-1</sub> &circ; D<sub>K</sub>(C<sub>i</sub>)
56
 * </pre>
56
 */
57
 */
57
public class CBC extends BaseMode implements Cloneable
58
public class CBC
59
    extends BaseMode
60
    implements Cloneable
58
{
61
{
59
60
  // Constants and Variables
61
  //------------------------------------------------------------------
62
63
  /** The last (de|en)crypted block */
62
  /** The last (de|en)crypted block */
64
  private byte[] lastBlock;
63
  private byte[] lastBlock;
65
66
  /** An intermediate buffer. */
64
  /** An intermediate buffer. */
67
  private byte[] scratch;
65
  private byte[] scratch;
68
66
69
  // Constructors
70
  // -----------------------------------------------------------------
71
72
  /**
67
  /**
73
   * Package-private constructor for the factory class.
68
   * Package-private constructor for the factory class.
74
   *
69
   * 
75
   * @param underlyingCipher The cipher implementation.
70
   * @param underlyingCipher The cipher implementation.
76
   * @param cipherBlockSize The cipher's block size.
71
   * @param cipherBlockSize The cipher's block size.
77
   */
72
   */
Lines 86-116 Link Here
86
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
81
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
87
  }
82
  }
88
83
89
  // Cloneable interface implementation
90
  // -----------------------------------------------------------------
91
92
  public Object clone()
84
  public Object clone()
93
  {
85
  {
94
    return new CBC(this);
86
    return new CBC(this);
95
  }
87
  }
96
88
97
  // Implementation of abstract methods in BaseMode
98
  // -----------------------------------------------------------------
99
100
  public void setup()
89
  public void setup()
101
  {
90
  {
102
    if (modeBlockSize != cipherBlockSize)
91
    if (modeBlockSize != cipherBlockSize)
103
      {
92
      throw new IllegalArgumentException();
104
        throw new IllegalArgumentException();
105
      }
106
    scratch = new byte[cipherBlockSize];
93
    scratch = new byte[cipherBlockSize];
107
    lastBlock = new byte[cipherBlockSize];
94
    lastBlock = new byte[cipherBlockSize];
108
109
    // lastBlock gets initialized to the initialization vector.
95
    // lastBlock gets initialized to the initialization vector.
110
    for (int i = 0; i < lastBlock.length && i < iv.length; i++)
96
    for (int i = 0; i < lastBlock.length && i < iv.length; i++)
111
      {
97
      lastBlock[i] = iv[i];
112
        lastBlock[i] = iv[i];
113
      }
114
  }
98
  }
115
99
116
  public void teardown()
100
  public void teardown()
Lines 122-130 Link Here
122
  public void encryptBlock(byte[] in, int i, byte[] out, int o)
106
  public void encryptBlock(byte[] in, int i, byte[] out, int o)
123
  {
107
  {
124
    for (int k = 0; k < scratch.length; k++)
108
    for (int k = 0; k < scratch.length; k++)
125
      {
109
      scratch[k] = (byte)(lastBlock[k] ^ in[k + i]);
126
        scratch[k] = (byte) (lastBlock[k] ^ in[k + i]);
127
      }
128
    cipher.encryptBlock(scratch, 0, out, o);
110
    cipher.encryptBlock(scratch, 0, out, o);
129
    System.arraycopy(out, o, lastBlock, 0, cipherBlockSize);
111
    System.arraycopy(out, o, lastBlock, 0, cipherBlockSize);
130
  }
112
  }
Lines 135-143 Link Here
135
    System.arraycopy(in, i, buf, 0, cipherBlockSize);
117
    System.arraycopy(in, i, buf, 0, cipherBlockSize);
136
    cipher.decryptBlock(in, i, scratch, 0);
118
    cipher.decryptBlock(in, i, scratch, 0);
137
    for (int k = 0; k < scratch.length; k++)
119
    for (int k = 0; k < scratch.length; k++)
138
      {
120
      out[o + k] = (byte)(lastBlock[k] ^ scratch[k]);
139
        out[o + k] = (byte) (lastBlock[k] ^ scratch[k]);
140
      }
141
    System.arraycopy(buf, 0, lastBlock, 0, cipherBlockSize);
121
    System.arraycopy(buf, 0, lastBlock, 0, cipherBlockSize);
142
  }
122
  }
143
}
123
}
(-)CFB.java (-68 / +48 lines)
Lines 42-99 Link Here
42
import gnu.javax.crypto.cipher.IBlockCipher;
42
import gnu.javax.crypto.cipher.IBlockCipher;
43
43
44
/**
44
/**
45
 * The cipher feedback mode. CFB mode is a stream mode that operates on
45
 * The cipher feedback mode. CFB mode is a stream mode that operates on <i>s</i>
46
 * <i>s</i> bit blocks, where 1 &lt;= <i>s</i> &lt;= <i>b</i>, if
46
 * bit blocks, where 1 &lt;= <i>s</i> &lt;= <i>b</i>, if <i>b</i> is the
47
 * <i>b</i> is the underlying cipher's block size. Encryption is:
47
 * underlying cipher's block size. Encryption is:
48
 *
48
 * <pre>
49
 <pre>
49
 *  I[1] = IV
50
 I[1] = IV
50
 *  I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
51
 I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
51
 *  O[j] = CIPH(K, I[j])               for j = 1,2...n
52
 O[j] = CIPH(K, I[j])               for j = 1,2...n
52
 *  C[j] = P[j] &circ; MSB(s, O[j])         for j = 1,2...n
53
 C[j] = P[j] ^ MSB(s, O[j])         for j = 1,2...n
53
 * </pre>
54
 </pre>
54
 * <p>
55
 *
55
 * And decryption is:
56
 * <p>And decryption is:</p>
56
 * <pre>
57
 * 
57
 *  I[1] = IV
58
 <pre>
58
 *  I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
59
 I[1] = IV
59
 *  O[j] = CIPH(K, I[j])               for j = 1,2...n
60
 I[j] = LSB(b-s, I[j-1]) | C[j-1]   for j = 2...n
60
 *  P[j] = C[j] &circ; MSB(s, O[j])         for j = 1,2...n
61
 O[j] = CIPH(K, I[j])               for j = 1,2...n
61
 * </pre>
62
 P[j] = C[j] ^ MSB(s, O[j])         for j = 1,2...n
62
 * <p>
63
 </pre>
63
 * CFB mode requires an initialization vector, which need not be kept secret.
64
 *
64
 * <p>
65
 * <p>CFB mode requires an initialization vector, which need not be kept
65
 * References:
66
 * secret.</p>
67
 *
68
 * <p>References:</p>
69
 * <ol>
66
 * <ol>
70
 * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms,
67
 * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, and
71
 * and Source Code in C, Second Edition</i>. (1996 John Wiley and Sons)
68
 * Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) ISBN
72
 * ISBN 0-471-11709-9.</li>
69
 * 0-471-11709-9.</li>
73
 *
70
 * <li><a
74
 * <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
71
 * href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
75
 * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
72
 * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
76
 * Morris Dworkin.</li>
73
 * Morris Dworkin.</li>
77
 * </ol>
74
 * </ol>
78
 */
75
 */
79
public class CFB extends BaseMode
76
public class CFB
77
    extends BaseMode
80
{
78
{
81
82
  // Constants and variables.
83
  // -----------------------------------------------------------------------
84
85
  /** The shift register, the input block to the block cipher. */
79
  /** The shift register, the input block to the block cipher. */
86
  private byte[] shiftRegister;
80
  private byte[] shiftRegister;
87
88
  /** The output block from the block cipher. */
81
  /** The output block from the block cipher. */
89
  private byte[] scratch;
82
  private byte[] scratch;
90
83
91
  // Constructors.
92
  // -----------------------------------------------------------------------
93
94
  /**
84
  /**
95
   * Package-private constructor for the factory class.
85
   * Package-private constructor for the factory class.
96
   *
86
   * 
97
   * @param underlyingCipher The cipher implementation.
87
   * @param underlyingCipher The cipher implementation.
98
   * @param cipherBlockSize The cipher's block size.
88
   * @param cipherBlockSize The cipher's block size.
99
   */
89
   */
Lines 104-110 Link Here
104
94
105
  /**
95
  /**
106
   * Cloneing constructor.
96
   * Cloneing constructor.
107
   *
97
   * 
108
   * @param that The instance being cloned.
98
   * @param that The instance being cloned.
109
   */
99
   */
110
  private CFB(CFB that)
100
  private CFB(CFB that)
Lines 112-120 Link Here
112
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
102
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
113
  }
103
  }
114
104
115
  // Instance methods implementing BaseMode.
116
  // -----------------------------------------------------------------------
117
118
  public Object clone()
105
  public Object clone()
119
  {
106
  {
120
    return new CFB(this);
107
    return new CFB(this);
Lines 123-147 Link Here
123
  public void setup()
110
  public void setup()
124
  {
111
  {
125
    if (modeBlockSize > cipherBlockSize)
112
    if (modeBlockSize > cipherBlockSize)
126
      {
113
      throw new IllegalArgumentException(
127
        throw new IllegalArgumentException(
114
          "CFB block size cannot be larger than the cipher block size");
128
                                           "CFB block size cannot be larger than the cipher block size");
129
      }
130
    shiftRegister = new byte[cipherBlockSize];
115
    shiftRegister = new byte[cipherBlockSize];
131
    scratch = new byte[cipherBlockSize];
116
    scratch = new byte[cipherBlockSize];
132
    System.arraycopy(iv, 0, shiftRegister, 0, Math.min(iv.length,
117
    System.arraycopy(iv, 0,
133
                                                       cipherBlockSize));
118
                     shiftRegister, 0,
119
                     Math.min(iv.length, cipherBlockSize));
134
  }
120
  }
135
121
136
  public void teardown()
122
  public void teardown()
137
  {
123
  {
138
    if (shiftRegister != null)
124
    if (shiftRegister != null)
139
      {
125
      for (int i = 0; i < shiftRegister.length; i++)
140
        for (int i = 0; i < shiftRegister.length; i++)
126
        shiftRegister[i] = 0;
141
          {
142
            shiftRegister[i] = 0;
143
          }
144
      }
145
    shiftRegister = null;
127
    shiftRegister = null;
146
  }
128
  }
147
129
Lines 149-161 Link Here
149
  {
131
  {
150
    cipher.encryptBlock(shiftRegister, 0, scratch, 0);
132
    cipher.encryptBlock(shiftRegister, 0, scratch, 0);
151
    for (int i = 0; i < modeBlockSize; i++)
133
    for (int i = 0; i < modeBlockSize; i++)
152
      {
134
      out[outOffset + i] = (byte)(in[inOffset + i] ^ scratch[i]);
153
        out[outOffset + i] = (byte) (in[inOffset + i] ^ scratch[i]);
135
    System.arraycopy(shiftRegister, modeBlockSize,
154
      }
136
                     shiftRegister, 0,
155
    System.arraycopy(shiftRegister, modeBlockSize, shiftRegister, 0,
156
                     cipherBlockSize - modeBlockSize);
137
                     cipherBlockSize - modeBlockSize);
157
    System.arraycopy(out, outOffset, shiftRegister, cipherBlockSize
138
    System.arraycopy(out, outOffset,
158
                                                    - modeBlockSize,
139
                     shiftRegister, cipherBlockSize - modeBlockSize,
159
                     modeBlockSize);
140
                     modeBlockSize);
160
  }
141
  }
161
142
Lines 163-175 Link Here
163
  {
144
  {
164
    cipher.encryptBlock(shiftRegister, 0, scratch, 0);
145
    cipher.encryptBlock(shiftRegister, 0, scratch, 0);
165
    for (int i = 0; i < modeBlockSize; i++)
146
    for (int i = 0; i < modeBlockSize; i++)
166
      {
147
      out[outOffset + i] = (byte)(in[inOffset + i] ^ scratch[i]);
167
        out[outOffset + i] = (byte) (in[inOffset + i] ^ scratch[i]);
148
    System.arraycopy(shiftRegister, modeBlockSize,
168
      }
149
                     shiftRegister, 0,
169
    System.arraycopy(shiftRegister, modeBlockSize, shiftRegister, 0,
170
                     cipherBlockSize - modeBlockSize);
150
                     cipherBlockSize - modeBlockSize);
171
    System.arraycopy(in, inOffset, shiftRegister, cipherBlockSize
151
    System.arraycopy(in, inOffset,
172
                                                  - modeBlockSize,
152
                     shiftRegister, cipherBlockSize - modeBlockSize,
173
                     modeBlockSize);
153
                     modeBlockSize);
174
  }
154
  }
175
}
155
}
(-)CTR.java (-88 / +37 lines)
Lines 46-96 Link Here
46
import java.util.Iterator;
46
import java.util.Iterator;
47
47
48
/**
48
/**
49
 * <p>The implementation of the Counter Mode.</p>
49
 * The implementation of the Counter Mode.
50
 *
50
 * <p>
51
 * <p>The algorithm steps are formally described as follows:</p>
51
 * The algorithm steps are formally described as follows:
52
 *
52
 * 
53
 * <pre>
53
 * <pre>
54
 *    CTR Encryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
54
 *     CTR Encryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
55
 *                    C[j] = P[j] ^ O[j]; for j = 1, 2...n.
55
 *                     C[j] = P[j] &circ; O[j]; for j = 1, 2...n.
56
 *    CTR Decryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
56
 *     CTR Decryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
57
 *                    P[j] = C[j] ^ O[j]; for j = 1, 2...n.
57
 *                     P[j] = C[j] &circ; O[j]; for j = 1, 2...n.
58
 * </pre>
58
 * </pre>
59
 *
59
 * 
60
 * <p>where <code>P</code> is the plaintext, <code>C</code> is the ciphertext,
60
 * <p>
61
 * where <code>P</code> is the plaintext, <code>C</code> is the ciphertext,
61
 * <code>E(K)</code> is the underlying block cipher encryption function
62
 * <code>E(K)</code> is the underlying block cipher encryption function
62
 * parametrised with the session key <code>K</code>, and <code>T</code> is the
63
 * parametrised with the session key <code>K</code>, and <code>T</code> is
63
 * <i>Counter</i>.</p>
64
 * the <i>Counter</i>.
64
 *
65
 * <p>
65
 * <p>This implementation, uses a standard incrementing function with a step of
66
 * This implementation, uses a standard incrementing function with a step of 1,
66
 * 1, and an initial value similar to that described in the NIST document.</p>
67
 * and an initial value similar to that described in the NIST document.
67
 *
68
 * <p>
68
 * <p>References:</p>
69
 * References:
69
 *
70
 * <ol>
70
 * <ol>
71
 *    <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
71
 * <li><a
72
 *    Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
72
 * href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
73
 *    Morris Dworkin.</li>
73
 * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
74
 * Morris Dworkin.</li>
74
 * </ol>
75
 * </ol>
75
 */
76
 */
76
public class CTR extends BaseMode implements Cloneable
77
public class CTR
78
    extends BaseMode
79
    implements Cloneable
77
{
80
{
78
79
  // Constants and variables
80
  // -------------------------------------------------------------------------
81
82
  /** The current counter. */
83
  //    private BigInteger T;
84
  private int off;
81
  private int off;
85
86
  private byte[] counter, enc;
82
  private byte[] counter, enc;
87
83
88
  // Constructor(s)
89
  // -------------------------------------------------------------------------
90
91
  /**
84
  /**
92
   * <p>Trivial package-private constructor for use by the Factory class.</p>
85
   * Trivial package-private constructor for use by the Factory class.
93
   *
86
   * 
94
   * @param underlyingCipher the underlying cipher implementation.
87
   * @param underlyingCipher the underlying cipher implementation.
95
   * @param cipherBlockSize the underlying cipher block size to use.
88
   * @param cipherBlockSize the underlying cipher block size to use.
96
   */
89
   */
Lines 100-107 Link Here
100
  }
93
  }
101
94
102
  /**
95
  /**
103
   * <p>Private constructor for cloning purposes.</p>
96
   * Private constructor for cloning purposes.
104
   *
97
   * 
105
   * @param that the instance to clone.
98
   * @param that the instance to clone.
106
   */
99
   */
107
  private CTR(CTR that)
100
  private CTR(CTR that)
Lines 109-169 Link Here
109
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
102
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
110
  }
103
  }
111
104
112
  // Class methods
113
  // -------------------------------------------------------------------------
114
115
  // Cloneable interface implementation
116
  // -------------------------------------------------------------------------
117
118
  public Object clone()
105
  public Object clone()
119
  {
106
  {
120
    return new CTR(this);
107
    return new CTR(this);
121
  }
108
  }
122
109
123
  // Implementation of abstract methods in BaseMode
124
  // -------------------------------------------------------------------------
125
126
  public void setup()
110
  public void setup()
127
  {
111
  {
128
    if (modeBlockSize > cipherBlockSize)
112
    if (modeBlockSize > cipherBlockSize)
129
      {
113
      throw new IllegalArgumentException("mode size exceeds cipher block size");
130
        throw new IllegalArgumentException(
131
                                           "mode size exceeds cipher block size");
132
      }
133
    off = 0;
114
    off = 0;
134
    counter = new byte[cipherBlockSize];
115
    counter = new byte[cipherBlockSize];
135
    int i = cipherBlockSize - 1;
116
    int i = cipherBlockSize - 1;
136
    int j = iv.length - 1;
117
    int j = iv.length - 1;
137
    while (i >= 0 && j >= 0)
118
    while (i >= 0 && j >= 0)
138
      {
119
      counter[i--] = iv[j--];
139
        counter[i--] = iv[j--];
140
      }
141
    enc = new byte[cipherBlockSize];
120
    enc = new byte[cipherBlockSize];
142
    cipher.encryptBlock(counter, 0, enc, 0);
121
    cipher.encryptBlock(counter, 0, enc, 0);
143
    //       if (modeBlockSize != cipherBlockSize) {
144
    //          throw new IllegalArgumentException();
145
    //       }
146
147
    //       byte[] tBytes = new byte[modeBlockSize+1];
148
    //       tBytes[0] = (byte) 0x80;
149
    //       for (int i = 0; i < modeBlockSize; i++) {
150
    //          tBytes[i+1] = (byte)(256 - modeBlockSize + i);
151
    //       }
152
153
    //       T = new BigInteger(1, tBytes);
154
  }
122
  }
155
123
156
  public void teardown()
124
  public void teardown()
157
  {
125
  {
158
    if (counter != null)
126
    if (counter != null)
159
      {
127
      Arrays.fill(counter, (byte) 0);
160
        Arrays.fill(counter, (byte) 0);
161
      }
162
    if (enc != null)
128
    if (enc != null)
163
      {
129
      Arrays.fill(enc, (byte) 0);
164
        Arrays.fill(enc, (byte) 0);
165
      }
166
    //       T = null;
167
  }
130
  }
168
131
169
  public void encryptBlock(byte[] in, int i, byte[] out, int o)
132
  public void encryptBlock(byte[] in, int i, byte[] out, int o)
Lines 181-201 Link Here
181
    return new Sequence(1, cipherBlockSize).iterator();
144
    return new Sequence(1, cipherBlockSize).iterator();
182
  }
145
  }
183
146
184
  // own methods
185
  // -------------------------------------------------------------------------
186
187
  private void ctr(byte[] in, int inOffset, byte[] out, int outOffset)
147
  private void ctr(byte[] in, int inOffset, byte[] out, int outOffset)
188
  {
148
  {
189
    //       T = T.add(BigInteger.ONE);
190
    //       byte[] O = T.toByteArray();
191
    //       int ndx = O.length - modeBlockSize;
192
    //       cipher.encryptBlock(O, ndx, O, ndx);
193
    //       for (int i = 0; i < modeBlockSize; i++) {
194
    //          out[outOffset++] = (byte)(in[inOffset++] ^ O[ndx++]);
195
    //       }
196
    for (int i = 0; i < modeBlockSize; i++)
149
    for (int i = 0; i < modeBlockSize; i++)
197
      {
150
      {
198
        out[outOffset++] = (byte) (in[inOffset++] ^ enc[off++]);
151
        out[outOffset++] = (byte)(in[inOffset++] ^ enc[off++]);
199
        if (off == cipherBlockSize)
152
        if (off == cipherBlockSize)
200
          {
153
          {
201
            int j;
154
            int j;
Lines 203-219 Link Here
203
              {
156
              {
204
                counter[j]++;
157
                counter[j]++;
205
                if ((counter[j] & 0xFF) != 0)
158
                if ((counter[j] & 0xFF) != 0)
206
                  {
159
                  break;
207
                    break;
208
                  }
209
              }
160
              }
210
            if (j == 0)
161
            if (j == 0)
211
              {
162
              counter[cipherBlockSize - 1]++;
212
                counter[cipherBlockSize - 1]++;
213
              }
214
            off = 0;
163
            off = 0;
215
            cipher.encryptBlock(counter, 0, enc, 0);
164
            cipher.encryptBlock(counter, 0, enc, 0);
216
          }
165
          }
217
      }
166
      }
218
  }
167
  }
219
}
168
}
(-)EAX.java (-94 / +31 lines)
Lines 39-51 Link Here
39
package gnu.javax.crypto.mode;
39
package gnu.javax.crypto.mode;
40
40
41
import gnu.java.security.Registry;
41
import gnu.java.security.Registry;
42
43
import gnu.javax.crypto.cipher.IBlockCipher;
42
import gnu.javax.crypto.cipher.IBlockCipher;
44
import gnu.javax.crypto.mac.IMac;
43
import gnu.javax.crypto.mac.IMac;
45
import gnu.javax.crypto.mac.MacFactory;
44
import gnu.javax.crypto.mac.MacFactory;
46
45
47
import java.security.InvalidKeyException;
46
import java.security.InvalidKeyException;
48
49
import java.util.Arrays;
47
import java.util.Arrays;
50
import java.util.Collections;
48
import java.util.Collections;
51
import java.util.HashMap;
49
import java.util.HashMap;
Lines 53-116 Link Here
53
import java.util.Map;
51
import java.util.Map;
54
52
55
/**
53
/**
56
 * <p>A conventional two-pass authenticated-encrypted mode, EAX. EAX is a
54
 * A conventional two-pass authenticated-encrypted mode, EAX. EAX is a
57
 * <i>Authenticated Encryption with Additional Data</i> (<b>AEAD</b>) scheme,
55
 * <i>Authenticated Encryption with Additional Data</i> (<b>AEAD</b>) scheme,
58
 * which provides protection and authentication for the message, and provides
56
 * which provides protection and authentication for the message, and provides
59
 * authentication of an (optional) header. EAX is composed of the counter mode
57
 * authentication of an (optional) header. EAX is composed of the counter mode
60
 * (CTR) and the one-key CBC MAC (OMAC).
58
 * (CTR) and the one-key CBC MAC (OMAC).
61
 *
59
 * <p>
62
 * <p>This class makes full use of the {@link IAuthenticatedMode} interface,
60
 * This class makes full use of the {@link IAuthenticatedMode} interface, that
63
 * that is, all methods of both {@link IMode} and {@link IMac} can be used
61
 * is, all methods of both {@link IMode} and {@link IMac} can be used as
64
 * as specified in the {@link IAuthenticatedMode} interface.
62
 * specified in the {@link IAuthenticatedMode} interface.
65
 *
63
 * <p>
66
 * <p>References:</p>
64
 * References:
67
 * <ol>
65
 * <ol>
68
 * <li>M. Bellare, P. Rogaway, and D. Wagner; <a
66
 * <li>M. Bellare, P. Rogaway, and D. Wagner; <a
69
 * href="http://www.cs.berkeley.edu/~daw/papers/eprint-short-ae.pdf">A
67
 * href="http://www.cs.berkeley.edu/~daw/papers/eprint-short-ae.pdf">A
70
 * Conventional Authenticated-Encryption Mode</a>.</li>
68
 * Conventional Authenticated-Encryption Mode</a>.</li>
71
 * </ol>
69
 * </ol>
72
 */
70
 */
73
public class EAX implements IAuthenticatedMode
71
public class EAX
72
    implements IAuthenticatedMode
74
{
73
{
75
76
  // Constants and fields.
77
  // ------------------------------------------------------------------------
78
79
  /** The tag size, in bytes. */
74
  /** The tag size, in bytes. */
80
  private int tagSize;
75
  private int tagSize;
81
82
  /** The nonce OMAC instance. */
76
  /** The nonce OMAC instance. */
83
  private IMac nonceOmac;
77
  private IMac nonceOmac;
84
85
  /** The header OMAC instance. */
78
  /** The header OMAC instance. */
86
  private IMac headerOmac;
79
  private IMac headerOmac;
87
88
  /** The message OMAC instance. */
80
  /** The message OMAC instance. */
89
  private IMac msgOmac;
81
  private IMac msgOmac;
90
91
  /** The CTR instance. */
82
  /** The CTR instance. */
92
  private IMode ctr;
83
  private IMode ctr;
93
94
  /** The direction state (encrypting or decrypting). */
84
  /** The direction state (encrypting or decrypting). */
95
  private int state;
85
  private int state;
96
97
  /** Whether we're initialized or not. */
86
  /** Whether we're initialized or not. */
98
  private boolean init;
87
  private boolean init;
99
100
  /** The cipher block size. */
88
  /** The cipher block size. */
101
  private int cipherBlockSize;
89
  private int cipherBlockSize;
102
103
  /** The cipher. */
90
  /** The cipher. */
104
  private IBlockCipher cipher;
91
  private IBlockCipher cipher;
105
106
  /** The [t]_n array. */
92
  /** The [t]_n array. */
107
  private byte[] t_n;
93
  private byte[] t_n;
108
109
  private static boolean valid = false;
94
  private static boolean valid = false;
110
95
111
  // Constructor.
112
  // ------------------------------------------------------------------------
113
114
  public EAX(IBlockCipher cipher, int cipherBlockSize)
96
  public EAX(IBlockCipher cipher, int cipherBlockSize)
115
  {
97
  {
116
    this.cipher = cipher;
98
    this.cipher = cipher;
Lines 118-126 Link Here
118
    String name = cipher.name();
100
    String name = cipher.name();
119
    int i = name.indexOf('-');
101
    int i = name.indexOf('-');
120
    if (i >= 0)
102
    if (i >= 0)
121
      {
103
      name = name.substring(0, i);
122
        name = name.substring(0, i);
123
      }
124
    String omacname = Registry.OMAC_PREFIX + name;
104
    String omacname = Registry.OMAC_PREFIX + name;
125
    nonceOmac = MacFactory.getInstance(omacname);
105
    nonceOmac = MacFactory.getInstance(omacname);
126
    headerOmac = MacFactory.getInstance(omacname);
106
    headerOmac = MacFactory.getInstance(omacname);
Lines 130-138 Link Here
130
    init = false;
110
    init = false;
131
  }
111
  }
132
112
133
  // IMode instance methods.
134
  // ------------------------------------------------------------------------
135
136
  public Object clone()
113
  public Object clone()
137
  {
114
  {
138
    return new EAX((IBlockCipher) cipher.clone(), cipherBlockSize);
115
    return new EAX((IBlockCipher) cipher.clone(), cipherBlockSize);
Lines 167-183 Link Here
167
  {
144
  {
168
    byte[] nonce = (byte[]) attrib.get(IV);
145
    byte[] nonce = (byte[]) attrib.get(IV);
169
    if (nonce == null)
146
    if (nonce == null)
170
      {
147
      throw new IllegalArgumentException("no nonce provided");
171
        throw new IllegalArgumentException("no nonce provided");
172
      }
173
    byte[] key = (byte[]) attrib.get(KEY_MATERIAL);
148
    byte[] key = (byte[]) attrib.get(KEY_MATERIAL);
174
    if (key == null)
149
    if (key == null)
175
      {
150
      throw new IllegalArgumentException("no key provided");
176
        throw new IllegalArgumentException("no key provided");
177
      }
178
151
179
    Arrays.fill(t_n, (byte) 0);
152
    Arrays.fill(t_n, (byte) 0);
180
181
    nonceOmac.reset();
153
    nonceOmac.reset();
182
    nonceOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
154
    nonceOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
183
    nonceOmac.update(t_n, 0, t_n.length);
155
    nonceOmac.update(t_n, 0, t_n.length);
Lines 186-207 Link Here
186
    nonceOmac.reset();
158
    nonceOmac.reset();
187
    nonceOmac.update(t_n, 0, t_n.length);
159
    nonceOmac.update(t_n, 0, t_n.length);
188
    nonceOmac.update(nonce, 0, nonce.length);
160
    nonceOmac.update(nonce, 0, nonce.length);
189
190
    t_n[t_n.length - 1] = 1;
161
    t_n[t_n.length - 1] = 1;
191
    headerOmac.reset();
162
    headerOmac.reset();
192
    headerOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
163
    headerOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
193
    headerOmac.update(t_n, 0, t_n.length);
164
    headerOmac.update(t_n, 0, t_n.length);
194
195
    t_n[t_n.length - 1] = 2;
165
    t_n[t_n.length - 1] = 2;
196
    msgOmac.reset();
166
    msgOmac.reset();
197
    msgOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
167
    msgOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
198
    msgOmac.update(t_n, 0, t_n.length);
168
    msgOmac.update(t_n, 0, t_n.length);
199
200
    Integer modeSize = (Integer) attrib.get(MODE_BLOCK_SIZE);
169
    Integer modeSize = (Integer) attrib.get(MODE_BLOCK_SIZE);
201
    if (modeSize == null)
170
    if (modeSize == null)
202
      {
171
      modeSize = Integer.valueOf(cipherBlockSize);
203
        modeSize = Integer.valueOf(cipherBlockSize);
204
      }
205
    HashMap ctrAttr = new HashMap();
172
    HashMap ctrAttr = new HashMap();
206
    ctrAttr.put(KEY_MATERIAL, key);
173
    ctrAttr.put(KEY_MATERIAL, key);
207
    ctrAttr.put(IV, N);
174
    ctrAttr.put(IV, N);
Lines 209-242 Link Here
209
    ctrAttr.put(MODE_BLOCK_SIZE, modeSize);
176
    ctrAttr.put(MODE_BLOCK_SIZE, modeSize);
210
    ctr.reset();
177
    ctr.reset();
211
    ctr.init(ctrAttr);
178
    ctr.init(ctrAttr);
212
213
    Integer st = (Integer) attrib.get(STATE);
179
    Integer st = (Integer) attrib.get(STATE);
214
    if (st != null)
180
    if (st != null)
215
      {
181
      {
216
        state = st.intValue();
182
        state = st.intValue();
217
        if (state != ENCRYPTION && state != DECRYPTION)
183
        if (state != ENCRYPTION && state != DECRYPTION)
218
          {
184
          throw new IllegalArgumentException("invalid state");
219
            throw new IllegalArgumentException("invalid state");
220
          }
221
      }
185
      }
222
    else
186
    else
223
      {
187
      state = ENCRYPTION;
224
        state = ENCRYPTION;
225
      }
226
188
227
    Integer ts = (Integer) attrib.get(TRUNCATED_SIZE);
189
    Integer ts = (Integer) attrib.get(TRUNCATED_SIZE);
228
    if (ts != null)
190
    if (ts != null)
229
      {
191
      tagSize = ts.intValue();
230
        tagSize = ts.intValue();
231
      }
232
    else
192
    else
233
      {
193
      tagSize = cipherBlockSize;
234
        tagSize = cipherBlockSize;
235
      }
236
    if (tagSize < 0 || tagSize > cipherBlockSize)
194
    if (tagSize < 0 || tagSize > cipherBlockSize)
237
      {
195
      throw new IllegalArgumentException("tag size out of range");
238
        throw new IllegalArgumentException("tag size out of range");
239
      }
240
    init = true;
196
    init = true;
241
  }
197
  }
242
198
Lines 247-274 Link Here
247
203
248
  public void encryptBlock(byte[] in, int inOff, byte[] out, int outOff)
204
  public void encryptBlock(byte[] in, int inOff, byte[] out, int outOff)
249
  {
205
  {
250
    if (!init)
206
    if (! init)
251
      {
207
      throw new IllegalStateException("not initialized");
252
        throw new IllegalStateException("not initialized");
253
      }
254
    if (state != ENCRYPTION)
208
    if (state != ENCRYPTION)
255
      {
209
      throw new IllegalStateException("not encrypting");
256
        throw new IllegalStateException("not encrypting");
257
      }
258
    ctr.update(in, inOff, out, outOff);
210
    ctr.update(in, inOff, out, outOff);
259
    msgOmac.update(out, outOff, ctr.currentBlockSize());
211
    msgOmac.update(out, outOff, ctr.currentBlockSize());
260
  }
212
  }
261
213
262
  public void decryptBlock(byte[] in, int inOff, byte[] out, int outOff)
214
  public void decryptBlock(byte[] in, int inOff, byte[] out, int outOff)
263
  {
215
  {
264
    if (!init)
216
    if (! init)
265
      {
217
      throw new IllegalStateException("not initialized");
266
        throw new IllegalStateException("not initialized");
267
      }
268
    if (state != DECRYPTION)
218
    if (state != DECRYPTION)
269
      {
219
      throw new IllegalStateException("not decrypting");
270
        throw new IllegalStateException("not decrypting");
271
      }
272
    msgOmac.update(in, inOff, ctr.currentBlockSize());
220
    msgOmac.update(in, inOff, ctr.currentBlockSize());
273
    ctr.update(in, inOff, out, outOff);
221
    ctr.update(in, inOff, out, outOff);
274
  }
222
  }
Lines 301-309 Link Here
301
    return true; // XXX
249
    return true; // XXX
302
  }
250
  }
303
251
304
  // IMac instance methods.
305
  // ------------------------------------------------------------------------
306
307
  public int macSize()
252
  public int macSize()
308
  {
253
  {
309
    return tagSize;
254
    return tagSize;
Lines 319-352 Link Here
319
  public void digest(byte[] out, int outOffset)
264
  public void digest(byte[] out, int outOffset)
320
  {
265
  {
321
    if (outOffset < 0 || outOffset + tagSize > out.length)
266
    if (outOffset < 0 || outOffset + tagSize > out.length)
322
      {
267
      throw new IndexOutOfBoundsException();
323
        throw new IndexOutOfBoundsException();
324
      }
325
    byte[] N = nonceOmac.digest();
268
    byte[] N = nonceOmac.digest();
326
    byte[] H = headerOmac.digest();
269
    byte[] H = headerOmac.digest();
327
    byte[] M = msgOmac.digest();
270
    byte[] M = msgOmac.digest();
328
    for (int i = 0; i < tagSize; i++)
271
    for (int i = 0; i < tagSize; i++)
329
      {
272
      out[outOffset + i] = (byte)(N[i] ^ H[i] ^ M[i]);
330
        out[outOffset + i] = (byte) (N[i] ^ H[i] ^ M[i]);
331
      }
332
    reset();
273
    reset();
333
  }
274
  }
334
275
335
  public void update(byte b)
276
  public void update(byte b)
336
  {
277
  {
337
    if (!init)
278
    if (! init)
338
      {
279
      throw new IllegalStateException("not initialized");
339
        throw new IllegalStateException("not initialized");
340
      }
341
    headerOmac.update(b);
280
    headerOmac.update(b);
342
  }
281
  }
343
282
344
  public void update(byte[] buf, int off, int len)
283
  public void update(byte[] buf, int off, int len)
345
  {
284
  {
346
    if (!init)
285
    if (! init)
347
      {
286
      throw new IllegalStateException("not initialized");
348
        throw new IllegalStateException("not initialized");
349
      }
350
    headerOmac.update(buf, off, len);
287
    headerOmac.update(buf, off, len);
351
  }
288
  }
352
}
289
}
(-)ECB.java (-45 / +29 lines)
Lines 42-85 Link Here
42
import gnu.javax.crypto.cipher.IBlockCipher;
42
import gnu.javax.crypto.cipher.IBlockCipher;
43
43
44
/**
44
/**
45
 * <p>The implementation of the Electronic Codebook mode.</p>
45
 * The implementation of the Electronic Codebook mode.
46
 *
46
 * <p>
47
 * <p>The Electronic Codebook (ECB) mode is a confidentiality mode that is
47
 * The Electronic Codebook (ECB) mode is a confidentiality mode that is defined
48
 * defined as follows:</p>
48
 * as follows:
49
 *
50
 * <ul>
49
 * <ul>
51
 *    <li>ECB Encryption: C<sub>j</sub> = CIPH<sub>K</sub>(P<sub>j</sub>) for j = 1...n</li>
50
 * <li>ECB Encryption: C<sub>j</sub> = CIPH<sub>K</sub>(P<sub>j</sub>)
52
 *    <li>ECB Decryption: P<sub>j</sub> = CIPH<sup>-1</sup><sub>K</sub>(C<sub>j</sub>) for j = 1...n</li>
51
 * for j = 1...n</li>
52
 * <li>ECB Decryption: P<sub>j</sub> = CIPH<sup>-1</sup><sub>K</sub>(C<sub>j</sub>)
53
 * for j = 1...n</li>
53
 * </ul>
54
 * </ul>
54
 *
55
 * <p>
55
 * <p>In ECB encryption, the forward cipher function is applied directly, and
56
 * In ECB encryption, the forward cipher function is applied directly, and
56
 * independently, to each block of the plaintext. The resulting sequence of
57
 * independently, to each block of the plaintext. The resulting sequence of
57
 * output blocks is the ciphertext.</p>
58
 * output blocks is the ciphertext.
58
 *
59
 * <p>
59
 * <p>In ECB decryption, the inverse cipher function is applied directly, and
60
 * In ECB decryption, the inverse cipher function is applied directly, and
60
 * independently, to each block of the ciphertext. The resulting sequence of
61
 * independently, to each block of the ciphertext. The resulting sequence of
61
 * output blocks is the plaintext.</p>
62
 * output blocks is the plaintext.
62
 *
63
 * <p>
63
 * <p>References:</p>
64
 * References:
64
 *
65
 * <ol>
65
 * <ol>
66
 *    <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
66
 * <li><a
67
 *    Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
67
 * href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
68
 *    Morris Dworkin.</li>
68
 * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
69
 * Morris Dworkin.</li>
69
 * </ol>
70
 * </ol>
70
 */
71
 */
71
public class ECB extends BaseMode implements Cloneable
72
public class ECB
73
    extends BaseMode
74
    implements Cloneable
72
{
75
{
73
74
  // Constants and variables
75
  // -------------------------------------------------------------------------
76
77
  // Constructor(s)
78
  // -------------------------------------------------------------------------
79
80
  /**
76
  /**
81
   * <p>Trivial package-private constructor for use by the Factory class.</p>
77
   * Trivial package-private constructor for use by the Factory class.
82
   *
78
   * 
83
   * @param underlyingCipher the underlying cipher implementation.
79
   * @param underlyingCipher the underlying cipher implementation.
84
   * @param cipherBlockSize the underlying cipher block size to use.
80
   * @param cipherBlockSize the underlying cipher block size to use.
85
   */
81
   */
Lines 89-96 Link Here
89
  }
85
  }
90
86
91
  /**
87
  /**
92
   * <p>Private constructor for cloning purposes.</p>
88
   * Private constructor for cloning purposes.
93
   *
89
   * 
94
   * @param that the mode to clone.
90
   * @param that the mode to clone.
95
   */
91
   */
96
  private ECB(ECB that)
92
  private ECB(ECB that)
Lines 98-124 Link Here
98
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
94
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
99
  }
95
  }
100
96
101
  // Class methods
102
  // -------------------------------------------------------------------------
103
104
  // Instance methods
105
  // -------------------------------------------------------------------------
106
107
  // java.lang.Cloneable interface implementation ----------------------------
108
109
  public Object clone()
97
  public Object clone()
110
  {
98
  {
111
    return new ECB(this);
99
    return new ECB(this);
112
  }
100
  }
113
101
114
  // Implementation of abstract methods in BaseMode --------------------------
115
116
  public void setup()
102
  public void setup()
117
  {
103
  {
118
    if (modeBlockSize != cipherBlockSize)
104
    if (modeBlockSize != cipherBlockSize)
119
      {
105
      throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
120
        throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
121
      }
122
  }
106
  }
123
107
124
  public void teardown()
108
  public void teardown()
Lines 134-137 Link Here
134
  {
118
  {
135
    cipher.decryptBlock(in, i, out, o);
119
    cipher.decryptBlock(in, i, out, o);
136
  }
120
  }
137
}
121
}
(-)IAuthenticatedMode.java (-10 / +8 lines)
Lines 43-58 Link Here
43
/**
43
/**
44
 * The interface for encryption modes that also produce a message authentication
44
 * The interface for encryption modes that also produce a message authentication
45
 * tag.
45
 * tag.
46
 *
46
 * <p>
47
 * <p>This interface is merely the conjuction of the {@link IMode} and
47
 * This interface is merely the conjuction of the {@link IMode} and {@link IMac}
48
 * {@link IMac} interfaces. Encryption and decryption is done via the
48
 * interfaces. Encryption and decryption is done via the
49
 * {@link IMode#update(byte[],int,byte[],int)} method, tag generation
49
 * {@link IMode#update(byte[],int,byte[],int)} method, tag generation is done
50
 * is done via the {@link IMac#digest()} method, and header updating
50
 * via the {@link IMac#digest()} method, and header updating (if supported by
51
 * (if supported by the mode) is done via the {@link
51
 * the mode) is done via the {@link IMac#update(byte[],int,int)} method.
52
 * IMac#update(byte[],int,int)} method.
53
 */
52
 */
54
public interface IAuthenticatedMode extends IMode, IMac
53
public interface IAuthenticatedMode
54
    extends IMode, IMac
55
{
55
{
56
57
  // Trivial conjunction of IMode and IMac.
58
}
56
}
(-)ICM.java (-93 / +46 lines)
Lines 44-118 Link Here
44
import java.math.BigInteger;
44
import java.math.BigInteger;
45
45
46
/**
46
/**
47
 * <p>An implementation of <i>David McGrew</i> Integer Counter Mode (ICM) as an
47
 * An implementation of <i>David McGrew</i> Integer Counter Mode (ICM) as an
48
 * {@link IMode}.</p>
48
 * {@link IMode}.
49
 *
49
 * <p>
50
 * <p>ICM is a way to define a pseudorandom keystream generator using a block
50
 * ICM is a way to define a pseudorandom keystream generator using a block
51
 * cipher. The keystream can be used for additive encryption, key derivation,
51
 * cipher. The keystream can be used for additive encryption, key derivation, or
52
 * or any other application requiring pseudorandom data. In the case of this
52
 * any other application requiring pseudorandom data. In the case of this class,
53
 * class, it is used as additive encryption, XOR-ing the keystream with the
53
 * it is used as additive encryption, XOR-ing the keystream with the input text
54
 * input text --for both encryption and decryption.</p>
54
 * --for both encryption and decryption.
55
 *
55
 * <p>
56
 * <p>In ICM, the keystream is logically broken into segments. Each segment is
56
 * In ICM, the keystream is logically broken into segments. Each segment is
57
 * identified with a segment index, and the segments have equal lengths. This
57
 * identified with a segment index, and the segments have equal lengths. This
58
 * segmentation makes ICM especially appropriate for securing packet-based
58
 * segmentation makes ICM especially appropriate for securing packet-based
59
 * protocols. ICM also allows a variety of configurations based, among other
59
 * protocols. ICM also allows a variety of configurations based, among other
60
 * things, on two parameters: the <i>block index length</i> and the
60
 * things, on two parameters: the <i>block index length</i> and the <i>segment
61
 * <i>segment index length</i>. A constraint on those two values exists: The sum
61
 * index length</i>. A constraint on those two values exists: The sum of
62
 * of <i>segment index length</i> and <i>block index length</i> <b>must not</b>
62
 * <i>segment index length</i> and <i>block index length</i> <b>must not</b>
63
 * half the <i>block size</i> of the underlying cipher. This requirement protects
63
 * half the <i>block size</i> of the underlying cipher. This requirement
64
 * the ICM keystream generator from potentially failing to be pseudorandom.</p>
64
 * protects the ICM keystream generator from potentially failing to be
65
 *
65
 * pseudorandom.
66
 * <p>For simplicity, this implementation, fixes these two values to the
66
 * <p>
67
 * following:</p>
67
 * For simplicity, this implementation, fixes these two values to the following:
68
 *
69
 * <ul>
68
 * <ul>
70
 *    <li>block index length: is half the underlying cipher block size, and</li>
69
 * <li>block index length: is half the underlying cipher block size, and</li>
71
 *    <li>segment index length: is zero.</li>
70
 * <li>segment index length: is zero.</li>
72
 * </ul>
71
 * </ul>
73
 *
72
 * <p>
74
 * <p>For a 128-bit block cipher, the above values imply a maximum keystream
73
 * For a 128-bit block cipher, the above values imply a maximum keystream length
75
 * length of 295,147,905,179,352,825,856 octets, since in ICM, each segment must
74
 * of 295,147,905,179,352,825,856 octets, since in ICM, each segment must not
76
 * not exceed the value <code>(256 ^ <i>block index length</i>) * <i>block length</i></code>
75
 * exceed the value
77
 * octets.</p>
76
 * <code>(256 ^ <i>block index length</i>) * <i>block length</i></code>
78
 *
77
 * octets.
79
 * <p>Finally, for this implementation of the ICM, the IV placeholder will be
78
 * <p>
80
 * used to pass the value of the <i>Offset</i> in the keystream segment.</p>
79
 * Finally, for this implementation of the ICM, the IV placeholder will be used
81
 *
80
 * to pass the value of the <i>Offset</i> in the keystream segment.
82
 * <p>References:</p>
81
 * <p>
83
 *
82
 * References:
84
 * <ol>
83
 * <ol>
85
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-icm-00.txt">
84
 * <li><a
86
 *    Integer Counter Mode</a>, David A. McGrew.</li>
85
 * href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-icm-00.txt">
86
 * Integer Counter Mode</a>, David A. McGrew.</li>
87
 * </ol>
87
 * </ol>
88
 */
88
 */
89
public class ICM extends BaseMode implements Cloneable
89
public class ICM
90
    extends BaseMode
91
    implements Cloneable
90
{
92
{
91
92
  // Constants and variables
93
  // -------------------------------------------------------------------------
94
95
  /** The integer value 256 as a BigInteger. */
93
  /** The integer value 256 as a BigInteger. */
96
  private static final BigInteger TWO_FIFTY_SIX = new BigInteger("256");
94
  private static final BigInteger TWO_FIFTY_SIX = new BigInteger("256");
97
98
  /** Maximum number of blocks per segment. */
95
  /** Maximum number of blocks per segment. */
99
  private BigInteger maxBlocksPerSegment;
96
  private BigInteger maxBlocksPerSegment;
100
101
  /** A work constant. */
97
  /** A work constant. */
102
  private BigInteger counterRange;
98
  private BigInteger counterRange;
103
104
  /** The initial counter for a given keystream segment. */
99
  /** The initial counter for a given keystream segment. */
105
  private BigInteger C0;
100
  private BigInteger C0;
106
107
  /** The index of the next block for a given keystream segment. */
101
  /** The index of the next block for a given keystream segment. */
108
  private BigInteger blockNdx;
102
  private BigInteger blockNdx;
109
103
110
  // Constructor(s)
111
  // -------------------------------------------------------------------------
112
113
  /**
104
  /**
114
   * <p>Trivial package-private constructor for use by the Factory class.</p>
105
   * Trivial package-private constructor for use by the Factory class.
115
   *
106
   * 
116
   * @param underlyingCipher the underlying cipher implementation.
107
   * @param underlyingCipher the underlying cipher implementation.
117
   * @param cipherBlockSize the underlying cipher block size to use.
108
   * @param cipherBlockSize the underlying cipher block size to use.
118
   */
109
   */
Lines 122-129 Link Here
122
  }
113
  }
123
114
124
  /**
115
  /**
125
   * <p>Private constructor for cloning purposes.<p>
116
   * Private constructor for cloning purposes.
126
   *
117
   * 
127
   * @param that the instance to clone.
118
   * @param that the instance to clone.
128
   */
119
   */
129
  private ICM(ICM that)
120
  private ICM(ICM that)
Lines 131-157 Link Here
131
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
122
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
132
  }
123
  }
133
124
134
  // Class methods
135
  // -------------------------------------------------------------------------
136
137
  // Cloneable interface implementation
138
  // -------------------------------------------------------------------------
139
140
  public Object clone()
125
  public Object clone()
141
  {
126
  {
142
    return new ICM(this);
127
    return new ICM(this);
143
  }
128
  }
144
129
145
  // Implementation of abstract methods in BaseMode
146
  // -------------------------------------------------------------------------
147
148
  public void setup()
130
  public void setup()
149
  {
131
  {
150
    if (modeBlockSize != cipherBlockSize)
132
    if (modeBlockSize != cipherBlockSize)
151
      {
133
      throw new IllegalArgumentException();
152
        throw new IllegalArgumentException();
153
      }
154
155
    counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize);
134
    counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize);
156
    maxBlocksPerSegment = TWO_FIFTY_SIX.pow(cipherBlockSize / 2);
135
    maxBlocksPerSegment = TWO_FIFTY_SIX.pow(cipherBlockSize / 2);
157
    BigInteger r = new BigInteger(1, iv);
136
    BigInteger r = new BigInteger(1, iv);
Lines 177-211 Link Here
177
    icm(in, i, out, o);
156
    icm(in, i, out, o);
178
  }
157
  }
179
158
180
  // Instance methods
181
  // -------------------------------------------------------------------------
182
183
  private void icm(byte[] in, int inOffset, byte[] out, int outOffset)
159
  private void icm(byte[] in, int inOffset, byte[] out, int outOffset)
184
  {
160
  {
185
    if (blockNdx.compareTo(maxBlocksPerSegment) >= 0)
161
    if (blockNdx.compareTo(maxBlocksPerSegment) >= 0)
186
      throw new RuntimeException("Maximum blocks for segment reached");
162
      throw new RuntimeException("Maximum blocks for segment reached");
187
188
    // encrypt the counter for the current blockNdx
189
    // C[i] = (C[0] + i) modulo (256^BLOCK_LENGTH).
190
191
    BigInteger Ci = C0.add(blockNdx).modPow(BigInteger.ONE, counterRange);
163
    BigInteger Ci = C0.add(blockNdx).modPow(BigInteger.ONE, counterRange);
192
    byte[] result = Ci.toByteArray();
164
    byte[] result = Ci.toByteArray();
193
    int limit = result.length;
165
    int limit = result.length;
194
    //      if (limit < cipherBlockSize) {
195
    //         byte[] data = new byte[cipherBlockSize];
196
    //         System.arraycopy(result, 0, data, cipherBlockSize-limit, limit);
197
    //         result = data;
198
    //      } else if (limit > cipherBlockSize) {
199
    //         byte[] data = new byte[cipherBlockSize];
200
    //         System.arraycopy(result, limit-cipherBlockSize, data, 0, cipherBlockSize);
201
    //         result = data;
202
    //      }
203
    //
204
    //      cipher.encryptBlock(result, 0, result, 0);
205
    //      blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
206
    //      for (int i = 0; i < modeBlockSize; ) { // xor result with input block
207
    //         out[outOffset++] = (byte)(in[inOffset++] ^ result[i++]);
208
    //      }
209
    int ndx = 0;
166
    int ndx = 0;
210
    if (limit < cipherBlockSize)
167
    if (limit < cipherBlockSize)
211
      {
168
      {
Lines 214-228 Link Here
214
        result = data;
171
        result = data;
215
      }
172
      }
216
    else if (limit > cipherBlockSize)
173
    else if (limit > cipherBlockSize)
217
      {
174
      ndx = limit - cipherBlockSize;
218
        ndx = limit - cipherBlockSize;
219
      }
220
175
221
    cipher.encryptBlock(result, ndx, result, ndx);
176
    cipher.encryptBlock(result, ndx, result, ndx);
222
    blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
177
    blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
223
    for (int i = 0; i < modeBlockSize; i++)
178
    for (int i = 0; i < modeBlockSize; i++) // xor result with input block
224
      { // xor result with input block
179
      out[outOffset++] = (byte)(in[inOffset++] ^ result[ndx++]);
225
        out[outOffset++] = (byte) (in[inOffset++] ^ result[ndx++]);
226
      }
227
  }
180
  }
228
}
181
}
(-)IMode.java (-68 / +46 lines)
Lines 41-145 Link Here
41
import gnu.javax.crypto.cipher.IBlockCipher;
41
import gnu.javax.crypto.cipher.IBlockCipher;
42
42
43
/**
43
/**
44
 * <p>The basic visible methods of any block cipher mode.</p>
44
 * The basic visible methods of any block cipher mode.
45
 *
45
 * <p>
46
 * <p>Block ciphers encrypt plaintext in fixed size n-bit blocks. For messages
46
 * Block ciphers encrypt plaintext in fixed size n-bit blocks. For messages
47
 * larger than n bits, the simplest approach is to segment the message into
47
 * larger than n bits, the simplest approach is to segment the message into
48
 * n-bit blocks and process (encrypt and/or decrypt) each one separately
48
 * n-bit blocks and process (encrypt and/or decrypt) each one separately
49
 * (Electronic Codebook or ECB mode). But this approach has disadvantages in
49
 * (Electronic Codebook or ECB mode). But this approach has disadvantages in
50
 * most applications. The block cipher modes of operations are one way of
50
 * most applications. The block cipher modes of operations are one way of
51
 * working around those disadvantages.</p>
51
 * working around those disadvantages.
52
 *
52
 * <p>
53
 * <p>A <i>Mode</i> always employs an underlying block cipher for processing its
53
 * A <i>Mode</i> always employs an underlying block cipher for processing its
54
 * input. For all intents and purposes, a <i>Mode</i> appears to behave as any
54
 * input. For all intents and purposes, a <i>Mode</i> appears to behave as any
55
 * other block cipher with the following differences:</p>
55
 * other block cipher with the following differences:
56
 *
57
 * <ul>
56
 * <ul>
58
 *    <li>Depending on the specifications of the mode, the block size may be
57
 * <li>Depending on the specifications of the mode, the block size may be
59
 *    different that that of the underlying cipher.</li>
58
 * different that that of the underlying cipher.</li>
60
 *
59
 * <li>While some modes of operations allow operations on block sizes that can
61
 *    <li>While some modes of operations allow operations on block sizes that
60
 * be 1-bit long, this library will only deal with sizes that are multiple of 8
62
 *    can be 1-bit long, this library will only deal with sizes that are
61
 * bits. This is because the <tt>byte</tt> is the smallest, easy to handle,
63
 *    multiple of 8 bits. This is because the <tt>byte</tt> is the smallest,
62
 * primitive type in Java.</li>
64
 *    easy to handle, primitive type in Java.</li>
63
 * <li>Some modes need an <i>Initialisation Vector</i> (IV) to be properly
65
 *
64
 * initialised.</li>
66
 *    <li>Some modes need an <i>Initialisation Vector</i> (IV) to be properly
67
 *    initialised.</li>
68
 * </ul>
65
 * </ul>
69
 *
66
 * <p>
70
 * <p>Possible additional initialisation values for an instance of that type
67
 * Possible additional initialisation values for an instance of that type are:
71
 * are:</p>
72
 *
73
 * <ul>
68
 * <ul>
74
 *    <li>The block size in which to operate this mode instance. This
69
 * <li>The block size in which to operate this mode instance. This value is
75
 *    value is <b>optional</b>, if unspecified, the underlying block cipher's
70
 * <b>optional</b>, if unspecified, the underlying block cipher's configured
76
 *    configured block size shall be used.</li>
71
 * block size shall be used.</li>
77
 *
72
 * <li>Whether this mode will be used for encryption or decryption. This value
78
 *    <li>Whether this mode will be used for encryption or decryption. This
73
 * is <b>mandatory</b> and should be included in the initialisation parameters.
79
 *    value is <b>mandatory</b> and should be included in the initialisation
74
 * If it isn't, a {@link java.lang.IllegalStateException} will be thrown if any
80
 *    parameters. If it isn't, a {@link java.lang.IllegalStateException} will
75
 * method, other than <code>reset()</code> is invoked on the instance.</li>
81
 *    be thrown if any method, other than <code>reset()</code> is invoked on the
76
 * <li>The byte array containing the <i>initialisation vector</i>, if required
82
 *    instance.</li>
77
 * by this type of mode.</li>
83
 *
84
 *    <li>The byte array containing the <i>initialisation vector</i>, if
85
 *    required by this type of mode.</li>
86
 * </ul>
78
 * </ul>
87
 */
79
 */
88
public interface IMode extends IBlockCipher
80
public interface IMode
81
    extends IBlockCipher
89
{
82
{
90
91
  // Constants
92
  // -------------------------------------------------------------------------
93
94
  /**
83
  /**
95
   * <p>Property name of the state in which to operate this mode. The value
84
   * Property name of the state in which to operate this mode. The value
96
   * associated to this property name is taken to be an {@link Integer} which
85
   * associated to this property name is taken to be an {@link Integer} which
97
   * value is either <code>ENCRYPTION</code> or <code>DECRYPTION</code>.</p>
86
   * value is either <code>ENCRYPTION</code> or <code>DECRYPTION</code>.
98
   */
87
   */
99
  String STATE = "gnu.crypto.mode.state";
88
  String STATE = "gnu.crypto.mode.state";
100
101
  /**
89
  /**
102
   * <p>Property name of the block size in which to operate this mode. The
90
   * Property name of the block size in which to operate this mode. The value
103
   * value associated with this property name is taken to be an {@link Integer}.
91
   * associated with this property name is taken to be an {@link Integer}. If
104
   * If it is not specified, the value of the block size of the underlying
92
   * it is not specified, the value of the block size of the underlying block
105
   * block cipher, used to construct the mode instance, shall be used.</p>
93
   * cipher, used to construct the mode instance, shall be used.
106
   */
94
   */
107
  String MODE_BLOCK_SIZE = "gnu.crypto.mode.block.size";
95
  String MODE_BLOCK_SIZE = "gnu.crypto.mode.block.size";
108
109
  /**
96
  /**
110
   * <p>Property name of the initialisation vector to use, if required, with
97
   * Property name of the initialisation vector to use, if required, with this
111
   * this instance. The value associated with this property name is taken to
98
   * instance. The value associated with this property name is taken to be a
112
   * be a byte array. If the concrete instance needs such a parameter, and it
99
   * byte array. If the concrete instance needs such a parameter, and it has not
113
   * has not been specified as part of the initialissation parameters, an
100
   * been specified as part of the initialissation parameters, an all-zero byte
114
   * all-zero byte array of the appropriate size shall be used.</p>
101
   * array of the appropriate size shall be used.
115
   */
102
   */
116
  String IV = "gnu.crypto.mode.iv";
103
  String IV = "gnu.crypto.mode.iv";
117
104
  /** Constant indicating the instance is being used for <i>encryption</i>. */
118
  /**
119
   * <p>Constant indicating the instance is being used for <i>encryption</i>.</p>
120
   */
121
  int ENCRYPTION = 1;
105
  int ENCRYPTION = 1;
122
106
  /** Constant indicating the instance is being used for <i>decryption</i>. */
123
  /**
124
   * <p>Constant indicating the instance is being used for <i>decryption</i>.</p>
125
   */
126
  int DECRYPTION = 2;
107
  int DECRYPTION = 2;
127
108
128
  // Methods
129
  // -------------------------------------------------------------------------
130
131
  /**
109
  /**
132
   * <p>A convenience method. Effectively invokes the <code>encryptBlock()</code>
110
   * A convenience method. Effectively invokes the <code>encryptBlock()</code>
133
   * or <code>decryptBlock()</code> method depending on the operational state
111
   * or <code>decryptBlock()</code> method depending on the operational state
134
   * of the instance.</p>
112
   * of the instance.
135
   *
113
   * 
136
   * @param in the plaintext.
114
   * @param in the plaintext.
137
   * @param inOffset index of <code>in</code> from which to start considering
115
   * @param inOffset index of <code>in</code> from which to start considering
138
   * data.
116
   *          data.
139
   * @param out the ciphertext.
117
   * @param out the ciphertext.
140
   * @param outOffset index of <code>out</code> from which to store result.
118
   * @param outOffset index of <code>out</code> from which to store result.
141
   * @exception IllegalStateException if the instance is not initialised.
119
   * @exception IllegalStateException if the instance is not initialised.
142
   */
120
   */
143
  void update(byte[] in, int inOffset, byte[] out, int outOffset)
121
  void update(byte[] in, int inOffset, byte[] out, int outOffset)
144
      throws IllegalStateException;
122
      throws IllegalStateException;
145
}
123
}
(-)ModeFactory.java (-68 / +27 lines)
Lines 49-64 Link Here
49
import java.util.Set;
49
import java.util.Set;
50
50
51
/**
51
/**
52
 * <p>A <i>Factory</i> to instantiate block cipher modes of operations.</p>
52
 * A <i>Factory</i> to instantiate block cipher modes of operations.
53
 */
53
 */
54
public class ModeFactory implements Registry
54
public class ModeFactory
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 Singleton pattern. */
59
  /** Trivial constructor to enforce Singleton pattern. */
64
  private ModeFactory()
60
  private ModeFactory()
Lines 66-102 Link Here
66
    super();
62
    super();
67
  }
63
  }
68
64
69
  // Class methods
70
  // -------------------------------------------------------------------------
71
72
  /**
65
  /**
73
   * <p>Returns an instance of a block cipher mode of operations given its name
66
   * Returns an instance of a block cipher mode of operations given its name and
74
   * and characteristics of the underlying block cipher.</p>
67
   * characteristics of the underlying block cipher.
75
   *
68
   * 
76
   * @param mode the case-insensitive name of the mode of operations.
69
   * @param mode the case-insensitive name of the mode of operations.
77
   * @param cipher the case-insensitive name of the block cipher.
70
   * @param cipher the case-insensitive name of the block cipher.
78
   * @param cipherBlockSize the block size, in bytes, of the underlying cipher.
71
   * @param cipherBlockSize the block size, in bytes, of the underlying cipher.
79
   * @return an instance of the block cipher algorithm, operating in a given
72
   * @return an instance of the block cipher algorithm, operating in a given
80
   * mode of operations, or <code>null</code> if none found.
73
   *         mode of operations, or <code>null</code> if none found.
81
   * @exception InternalError if either the mode or the underlying block cipher
74
   * @exception InternalError if either the mode or the underlying block cipher
82
   * implementation does not pass its self-test.
75
   *              implementation does not pass its self-test.
83
   */
76
   */
84
  public static IMode getInstance(String mode, String cipher,
77
  public static IMode getInstance(String mode, String cipher,
85
                                  int cipherBlockSize)
78
                                  int cipherBlockSize)
86
  {
79
  {
87
    if (mode == null || cipher == null)
80
    if (mode == null || cipher == null)
88
      {
81
      return null;
89
        return null;
90
      }
91
82
92
    mode = mode.trim();
83
    mode = mode.trim();
93
    cipher = cipher.trim();
84
    cipher = cipher.trim();
94
95
    IBlockCipher cipherImpl = CipherFactory.getInstance(cipher);
85
    IBlockCipher cipherImpl = CipherFactory.getInstance(cipher);
96
    if (cipherImpl == null)
86
    if (cipherImpl == null)
97
      {
87
      return null;
98
        return null;
99
      }
100
88
101
    return getInstance(mode, cipherImpl, cipherBlockSize);
89
    return getInstance(mode, cipherImpl, cipherBlockSize);
102
  }
90
  }
Lines 110-168 Link Here
110
      {
98
      {
111
        ok = (cipherBlockSize == ((Integer) it.next()).intValue());
99
        ok = (cipherBlockSize == ((Integer) it.next()).intValue());
112
        if (ok)
100
        if (ok)
113
          {
101
          break;
114
            break;
115
          }
116
      }
117
118
    if (!ok)
119
      {
120
        throw new IllegalArgumentException("cipherBlockSize");
121
      }
102
      }
122
103
    if (! ok)
104
      throw new IllegalArgumentException("cipherBlockSize");
123
    IMode result = null;
105
    IMode result = null;
124
    if (mode.equalsIgnoreCase(ECB_MODE))
106
    if (mode.equalsIgnoreCase(ECB_MODE))
125
      {
107
      result = new ECB(cipher, cipherBlockSize);
126
        result = new ECB(cipher, cipherBlockSize);
127
      }
128
    else if (mode.equalsIgnoreCase(CTR_MODE))
108
    else if (mode.equalsIgnoreCase(CTR_MODE))
129
      {
109
      result = new CTR(cipher, cipherBlockSize);
130
        result = new CTR(cipher, cipherBlockSize);
131
      }
132
    else if (mode.equalsIgnoreCase(ICM_MODE))
110
    else if (mode.equalsIgnoreCase(ICM_MODE))
133
      {
111
      result = new ICM(cipher, cipherBlockSize);
134
        result = new ICM(cipher, cipherBlockSize);
135
      }
136
    else if (mode.equalsIgnoreCase(OFB_MODE))
112
    else if (mode.equalsIgnoreCase(OFB_MODE))
137
      {
113
      result = new OFB(cipher, cipherBlockSize);
138
        result = new OFB(cipher, cipherBlockSize);
139
      }
140
    else if (mode.equalsIgnoreCase(CBC_MODE))
114
    else if (mode.equalsIgnoreCase(CBC_MODE))
141
      {
115
      result = new CBC(cipher, cipherBlockSize);
142
        result = new CBC(cipher, cipherBlockSize);
143
      }
144
    else if (mode.equalsIgnoreCase(CFB_MODE))
116
    else if (mode.equalsIgnoreCase(CFB_MODE))
145
      {
117
      result = new CFB(cipher, cipherBlockSize);
146
        result = new CFB(cipher, cipherBlockSize);
147
      }
148
    else if (mode.equalsIgnoreCase(EAX_MODE))
118
    else if (mode.equalsIgnoreCase(EAX_MODE))
149
      {
119
      result = new EAX(cipher, cipherBlockSize);
150
        result = new EAX(cipher, cipherBlockSize);
151
      }
152
120
153
    if (result != null && !result.selfTest())
121
    if (result != null && ! result.selfTest())
154
      {
122
      throw new InternalError(result.name());
155
        throw new InternalError(result.name());
156
      }
157
123
158
    return result;
124
    return result;
159
  }
125
  }
160
126
161
  /**
127
  /**
162
   * <p>Returns a {@link java.util.Set} of names of mode supported by this
128
   * Returns a {@link Set} of names of mode supported by this <i>Factory</i>.
163
   * <i>Factory</i>.</p>
129
   * 
164
   *
130
   * @return a {@link Set} of mode names (Strings).
165
   * @return a {@link java.util.Set} of mode names (Strings).
166
   */
131
   */
167
  public static final Set getNames()
132
  public static final Set getNames()
168
  {
133
  {
Lines 178-192 Link Here
178
            hs.add(CBC_MODE);
143
            hs.add(CBC_MODE);
179
            hs.add(CFB_MODE);
144
            hs.add(CFB_MODE);
180
            hs.add(EAX_MODE);
145
            hs.add(EAX_MODE);
181
182
            names = Collections.unmodifiableSet(hs);
146
            names = Collections.unmodifiableSet(hs);
183
          }
147
          }
184
      }
148
      }
185
    return names;
149
    return names;
186
  }
150
  }
187
151
}
188
  private static Set names;
189
190
  // Instance methods
191
  // -------------------------------------------------------------------------
192
}
(-)OFB.java (-74 / +54 lines)
Lines 39-71 Link Here
39
package gnu.javax.crypto.mode;
39
package gnu.javax.crypto.mode;
40
40
41
import gnu.java.security.Registry;
41
import gnu.java.security.Registry;
42
43
import gnu.javax.crypto.cipher.IBlockCipher;
42
import gnu.javax.crypto.cipher.IBlockCipher;
44
43
45
/**
44
/**
46
 * <p>The Output Feedback (OFB) mode is a confidentiality mode that requires a
45
 * The Output Feedback (OFB) mode is a confidentiality mode that requires a
47
 * unique <code>IV</code> for every message that is ever encrypted under the
46
 * unique <code>IV</code> for every message that is ever encrypted under the
48
 * given key. The OFB mode is defined as follows:</p>
47
 * given key. The OFB mode is defined as follows:
49
 *
48
 * <ul>
49
 * <li>OFB Encryption:
50
 * <ul>
50
 * <ul>
51
 *    <li>OFB Encryption:
51
 * <li>I<sub>1</sub> = IV;</li>
52
 *    <ul>
52
 * <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
53
 *       <li>I<sub>1</sub> = IV;</li>
53
 * <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
54
 *       <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
54
 * <li>C<sub>j</sub> = P<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
55
 *       <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
55
 * </ul>
56
 *       <li>C<sub>j</sub> = P<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
56
 * </li>
57
 *    </ul></li>
58
 * <li>OFB Decryption:
57
 * <li>OFB Decryption:
59
 *    <ul>
58
 * <ul>
60
 *       <li>I<sub>1</sub> = IV;</li>
59
 * <li>I<sub>1</sub> = IV;</li>
61
 *       <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
60
 * <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
62
 *       <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
61
 * <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
63
 *       <li>P<sub>j</sub> = C<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
62
 * <li>P<sub>j</sub> = C<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
64
 *    </ul></li>
65
 * </ul>
63
 * </ul>
66
 *
64
 * </li>
67
 * <p>In OFB encryption, the <code>IV</code> is transformed by the forward
65
 * </ul>
68
 * cipher function to produce the first output block. The first output block is
66
 * <p>
67
 * In OFB encryption, the <code>IV</code> is transformed by the forward cipher
68
 * function to produce the first output block. The first output block is
69
 * exclusive-ORed with the first plaintext block to produce the first ciphertext
69
 * exclusive-ORed with the first plaintext block to produce the first ciphertext
70
 * block. The first output block is then transformed by the forward cipher
70
 * block. The first output block is then transformed by the forward cipher
71
 * function to produce the second output block. The second output block is
71
 * function to produce the second output block. The second output block is
Lines 74-82 Link Here
74
 * cipher function to produce the third output block. Thus, the successive
74
 * cipher function to produce the third output block. Thus, the successive
75
 * output blocks are produced from enciphering the previous output blocks, and
75
 * output blocks are produced from enciphering the previous output blocks, and
76
 * the output blocks are exclusive-ORed with the corresponding plaintext blocks
76
 * the output blocks are exclusive-ORed with the corresponding plaintext blocks
77
 * to produce the ciphertext blocks.</p>
77
 * to produce the ciphertext blocks.
78
 *
78
 * <p>
79
 * <p>In OFB decryption, the <code>IV</code> is transformed by the forward cipher
79
 * In OFB decryption, the <code>IV</code> is transformed by the forward cipher
80
 * function to produce the first output block. The first output block is
80
 * function to produce the first output block. The first output block is
81
 * exclusive-ORed with the first ciphertext block to recover the first plaintext
81
 * exclusive-ORed with the first ciphertext block to recover the first plaintext
82
 * block. The first output block is then transformed by the forward cipher
82
 * block. The first output block is then transformed by the forward cipher
Lines 86-136 Link Here
86
 * forward cipher function to produce the third output block. Thus, the
86
 * forward cipher function to produce the third output block. Thus, the
87
 * successive output blocks are produced from enciphering the previous output
87
 * successive output blocks are produced from enciphering the previous output
88
 * blocks, and the output blocks are exclusive-ORed with the corresponding
88
 * blocks, and the output blocks are exclusive-ORed with the corresponding
89
 * ciphertext blocks to recover the plaintext blocks.</p>
89
 * ciphertext blocks to recover the plaintext blocks.
90
 *
90
 * <p>
91
 * <p>In both OFB encryption and OFB decryption, each forward cipher function
91
 * In both OFB encryption and OFB decryption, each forward cipher function
92
 * (except the first) depends on the results of the previous forward cipher
92
 * (except the first) depends on the results of the previous forward cipher
93
 * function; therefore, multiple forward cipher functions cannot be performed
93
 * function; therefore, multiple forward cipher functions cannot be performed in
94
 * in parallel. However, if the <code>IV</code> is known, the output blocks can
94
 * parallel. However, if the <code>IV</code> is known, the output blocks can
95
 * be generated prior to the availability of the plaintext or ciphertext data.</p>
95
 * be generated prior to the availability of the plaintext or ciphertext data.
96
 *
96
 * <p>
97
 * <p>The OFB mode requires a unique <code>IV</code> for every message that is
97
 * The OFB mode requires a unique <code>IV</code> for every message that is
98
 * ever encrypted under the given key. If, contrary to this requirement, the
98
 * ever encrypted under the given key. If, contrary to this requirement, the
99
 * same <code>IV</code> is used for the encryption of more than one message,
99
 * same <code>IV</code> is used for the encryption of more than one message,
100
 * then the confidentiality of those messages may be compromised. In particular,
100
 * then the confidentiality of those messages may be compromised. In particular,
101
 * if a plaintext block of any of these messages is known, say, the j<sup>th</sup>
101
 * if a plaintext block of any of these messages is known, say, the j<sup>th</sup>
102
 * plaintext block, then the j<sup>th</sup> output of the forward cipher
102
 * plaintext block, then the j<sup>th</sup> output of the forward cipher
103
 * function can be determined easily from the j<sup>th</sup> ciphertext block of
103
 * function can be determined easily from the j<sup>th</sup> ciphertext block
104
 * the message. This information allows the j<sup>th</sup> plaintext block of
104
 * of the message. This information allows the j<sup>th</sup> plaintext block
105
 * any other message that is encrypted using the same <code>IV</code> to be
105
 * of any other message that is encrypted using the same <code>IV</code> to be
106
 * easily recovered from the jth ciphertext block of that message.</p>
106
 * easily recovered from the jth ciphertext block of that message.
107
 *
107
 * <p>
108
 * <p>Confidentiality may similarly be compromised if any of the input blocks to
108
 * Confidentiality may similarly be compromised if any of the input blocks to
109
 * the forward cipher function for the encryption of a message is used as the
109
 * the forward cipher function for the encryption of a message is used as the
110
 * <code>IV</code> for the encryption of another message under the given key.</p>
110
 * <code>IV</code> for the encryption of another message under the given key.
111
 *
111
 * <p>
112
 * <p>References:</p>
112
 * References:
113
 *
114
 * <ol>
113
 * <ol>
115
 *    <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
114
 * <li><a
116
 *    Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
115
 * href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
117
 *    Morris Dworkin.</li>
116
 * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
117
 * Morris Dworkin.</li>
118
 * </ol>
118
 * </ol>
119
 */
119
 */
120
public class OFB extends BaseMode implements Cloneable
120
public class OFB
121
    extends BaseMode
122
    implements Cloneable
121
{
123
{
122
123
  // Constants and variables
124
  // -------------------------------------------------------------------------
125
126
  private byte[] outputBlock;
124
  private byte[] outputBlock;
127
125
128
  // Constructor(s)
129
  // -------------------------------------------------------------------------
130
131
  /**
126
  /**
132
   * <p>Trivial package-private constructor for use by the Factory class.</p>
127
   * Trivial package-private constructor for use by the Factory class.
133
   *
128
   * 
134
   * @param underlyingCipher the underlying cipher implementation.
129
   * @param underlyingCipher the underlying cipher implementation.
135
   * @param cipherBlockSize the underlying cipher block size to use.
130
   * @param cipherBlockSize the underlying cipher block size to use.
136
   */
131
   */
Lines 140-147 Link Here
140
  }
135
  }
141
136
142
  /**
137
  /**
143
   * <p>Private constructor for cloning purposes.</p>
138
   * Private constructor for cloning purposes.
144
   *
139
   * 
145
   * @param that the mode to clone.
140
   * @param that the mode to clone.
146
   */
141
   */
147
  private OFB(OFB that)
142
  private OFB(OFB that)
Lines 149-176 Link Here
149
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
144
    this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
150
  }
145
  }
151
146
152
  // Class methods
153
  // -------------------------------------------------------------------------
154
155
  // Instance methods
156
  // -------------------------------------------------------------------------
157
158
  // java.lang.Cloneable interface implementation ----------------------------
159
160
  public Object clone()
147
  public Object clone()
161
  {
148
  {
162
    return new OFB(this);
149
    return new OFB(this);
163
  }
150
  }
164
151
165
  // Implementation of abstract methods in BaseMode --------------------------
166
167
  public void setup()
152
  public void setup()
168
  {
153
  {
169
    if (modeBlockSize != cipherBlockSize)
154
    if (modeBlockSize != cipherBlockSize)
170
      {
155
      throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
171
        throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
172
      }
173
174
    outputBlock = (byte[]) iv.clone();
156
    outputBlock = (byte[]) iv.clone();
175
  }
157
  }
176
158
Lines 182-194 Link Here
182
  {
164
  {
183
    cipher.encryptBlock(outputBlock, 0, outputBlock, 0);
165
    cipher.encryptBlock(outputBlock, 0, outputBlock, 0);
184
    for (int j = 0; j < cipherBlockSize;)
166
    for (int j = 0; j < cipherBlockSize;)
185
      {
167
      out[o++] = (byte)(in[i++] ^ outputBlock[j++]);
186
        out[o++] = (byte) (in[i++] ^ outputBlock[j++]);
187
      }
188
  }
168
  }
189
169
190
  public void decryptBlock(byte[] in, int i, byte[] out, int o)
170
  public void decryptBlock(byte[] in, int i, byte[] out, int o)
191
  {
171
  {
192
    this.encryptBlock(in, i, out, o);
172
    this.encryptBlock(in, i, out, o);
193
  }
173
  }
194
}
174
}

Return to bug 26067