2 Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
4 This file is a part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.javax
.crypto
.mode
;
41 import gnu
.javax
.crypto
.cipher
.IBlockCipher
;
43 import java
.security
.InvalidKeyException
;
44 import java
.util
.ArrayList
;
45 import java
.util
.Arrays
;
46 import java
.util
.Collections
;
47 import java
.util
.HashMap
;
48 import java
.util
.Iterator
;
52 * <p>A basic abstract class to facilitate implementing block cipher modes of
55 public abstract class BaseMode
implements IMode
58 // Constants and variables
59 // -------------------------------------------------------------------------
61 /** The canonical name prefix of this mode. */
62 protected String name
;
64 /** The state indicator of this instance. */
67 /** The underlying block cipher implementation. */
68 protected IBlockCipher cipher
;
70 /** The block size, in bytes, to operate the underlying block cipher in. */
71 protected int cipherBlockSize
;
73 /** The block size, in bytes, in which to operate the mode instance. */
74 protected int modeBlockSize
;
76 /** The initialisation vector value. */
79 /** The instance lock. */
80 protected Object lock
= new Object();
83 // -------------------------------------------------------------------------
86 * <p>Trivial constructor for use by concrete subclasses.</p>
88 * @param name the canonical name prefix of this mode.
89 * @param underlyingCipher the implementation of the underlying cipher.
90 * @param cipherBlockSize the block size, in bytes, in which to operate the
93 protected BaseMode(String name
, IBlockCipher underlyingCipher
,
99 this.cipher
= underlyingCipher
;
100 this.cipherBlockSize
= cipherBlockSize
;
105 // -------------------------------------------------------------------------
108 // -------------------------------------------------------------------------
110 // IMode interface implementation ------------------------------------------
112 public void update(byte[] in
, int inOffset
, byte[] out
, int outOffset
)
113 throws IllegalStateException
120 encryptBlock(in
, inOffset
, out
, outOffset
);
123 decryptBlock(in
, inOffset
, out
, outOffset
);
126 throw new IllegalStateException();
131 // IBlockCipher interface implementation -----------------------------------
135 return new StringBuffer().append(name
).append('(').append(cipher
.name()).append(
140 * <p>Returns the default value, in bytes, of the mode's block size. This
141 * value is part of the construction arguments passed to the Factory methods
142 * in {@link ModeFactory}. Unless changed by an invocation of any of the
143 * <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,
145 * the block size of the underlying block cipher itself is specified in one
146 * of the method(s) available in the factory class.</p>
148 * @return the default value, in bytes, of the mode's block size.
149 * @see gnu.crypto.mode.ModeFactory
151 public int defaultBlockSize()
153 return cipherBlockSize
;
157 * <p>Returns the default value, in bytes, of the underlying block cipher
160 * @return the default value, in bytes, of the underlying cipher's key size.
162 public int defaultKeySize()
164 return cipher
.defaultKeySize();
168 * <p>Returns an {@link Iterator} over the supported block sizes. Each
169 * element returned by this object is an {@link Integer}.</p>
171 * <p>The default behaviour is to return an iterator with just one value,
172 * which is that currently configured for the underlying block cipher.
173 * Concrete implementations may override this behaviour to signal their
174 * ability to support other values.</p>
176 * @return an {@link Iterator} over the supported block sizes.
178 public Iterator
blockSizes()
180 ArrayList al
= new ArrayList();
181 al
.add(new Integer(cipherBlockSize
));
183 return Collections
.unmodifiableList(al
).iterator();
187 * <p>Returns an {@link Iterator} over the supported underlying block cipher
188 * key sizes. Each element returned by this object is an instance of
189 * {@link Integer}.</p>
191 * @return an {@link Iterator} over the supported key sizes.
193 public Iterator
keySizes()
195 return cipher
.keySizes();
198 public void init(Map attributes
) throws InvalidKeyException
,
199 IllegalStateException
205 throw new IllegalStateException();
208 Integer want
= (Integer
) attributes
.get(STATE
);
211 switch (want
.intValue())
220 throw new IllegalArgumentException();
224 Integer bs
= (Integer
) attributes
.get(MODE_BLOCK_SIZE
);
225 modeBlockSize
= (bs
== null ? cipherBlockSize
: bs
.intValue());
227 byte[] iv
= (byte[]) attributes
.get(IV
);
230 this.iv
= (byte[]) iv
.clone();
234 this.iv
= new byte[modeBlockSize
];
237 cipher
.init(attributes
);
242 public int currentBlockSize()
246 throw new IllegalStateException();
248 return modeBlockSize
;
263 public boolean selfTest()
267 for (Iterator kit
= keySizes(); kit
.hasNext();)
269 ks
= ((Integer
) kit
.next()).intValue();
270 for (bit
= blockSizes(); bit
.hasNext();)
272 if (!testSymmetry(ks
, ((Integer
) bit
.next()).intValue()))
282 // methods to be implemented by concrete subclasses ------------------------
284 public abstract Object
clone();
286 /** The initialisation phase of the concrete mode implementation. */
287 public abstract void setup();
289 /** The termination phase of the concrete mode implementation. */
290 public abstract void teardown();
292 public abstract void encryptBlock(byte[] in
, int i
, byte[] out
, int o
);
294 public abstract void decryptBlock(byte[] in
, int i
, byte[] out
, int o
);
296 // own methods -------------------------------------------------------------
298 private boolean testSymmetry(int ks
, int bs
)
302 IMode mode
= (IMode
) this.clone();
303 byte[] iv
= new byte[cipherBlockSize
]; // all zeroes
304 byte[] k
= new byte[ks
];
306 for (i
= 0; i
< ks
; i
++)
312 int limit
= blockCount
* bs
;
313 byte[] pt
= new byte[limit
];
314 for (i
= 0; i
< limit
; i
++)
318 byte[] ct
= new byte[limit
];
319 byte[] cpt
= new byte[limit
];
321 Map map
= new HashMap();
322 map
.put(KEY_MATERIAL
, k
);
323 map
.put(CIPHER_BLOCK_SIZE
, new Integer(cipherBlockSize
));
324 map
.put(STATE
, new Integer(ENCRYPTION
));
326 map
.put(MODE_BLOCK_SIZE
, new Integer(bs
));
330 for (i
= 0; i
< blockCount
; i
++)
332 mode
.update(pt
, i
* bs
, ct
, i
* bs
);
336 map
.put(STATE
, new Integer(DECRYPTION
));
338 for (i
= 0; i
< blockCount
; i
++)
340 mode
.update(ct
, i
* bs
, cpt
, i
* bs
);
343 return Arrays
.equals(pt
, cpt
);
348 x
.printStackTrace(System
.err
);