1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51:
55: public abstract class BaseMode
56: implements IMode
57: {
58:
59: protected String name;
60:
61: protected int state;
62:
63: protected IBlockCipher cipher;
64:
65: protected int cipherBlockSize;
66:
67: protected int modeBlockSize;
68:
69: protected byte[] iv;
70:
71: protected Object lock = new Object();
72:
73:
81: protected BaseMode(String name, IBlockCipher underlyingCipher,
82: int cipherBlockSize)
83: {
84: super();
85:
86: this.name = name;
87: this.cipher = underlyingCipher;
88: this.cipherBlockSize = cipherBlockSize;
89: state = -1;
90: }
91:
92: public void update(byte[] in, int inOffset, byte[] out, int outOffset)
93: throws IllegalStateException
94: {
95: synchronized (lock)
96: {
97: switch (state)
98: {
99: case ENCRYPTION:
100: encryptBlock(in, inOffset, out, outOffset);
101: break;
102: case DECRYPTION:
103: decryptBlock(in, inOffset, out, outOffset);
104: break;
105: default:
106: throw new IllegalStateException();
107: }
108: }
109: }
110:
111: public String name()
112: {
113: return new StringBuffer(name).append('(').append(cipher.name()).append(')')
114: .toString();
115: }
116:
117:
129: public int defaultBlockSize()
130: {
131: return cipherBlockSize;
132: }
133:
134:
140: public int defaultKeySize()
141: {
142: return cipher.defaultKeySize();
143: }
144:
145:
156: public Iterator blockSizes()
157: {
158: ArrayList al = new ArrayList();
159: al.add(Integer.valueOf(cipherBlockSize));
160: return Collections.unmodifiableList(al).iterator();
161: }
162:
163:
170: public Iterator keySizes()
171: {
172: return cipher.keySizes();
173: }
174:
175: public void init(Map attributes) throws InvalidKeyException,
176: IllegalStateException
177: {
178: synchronized (lock)
179: {
180: if (state != -1)
181: throw new IllegalStateException();
182: Integer want = (Integer) attributes.get(STATE);
183: if (want != null)
184: {
185: switch (want.intValue())
186: {
187: case ENCRYPTION:
188: state = ENCRYPTION;
189: break;
190: case DECRYPTION:
191: state = DECRYPTION;
192: break;
193: default:
194: throw new IllegalArgumentException();
195: }
196: }
197: Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
198: modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
199: byte[] iv = (byte[]) attributes.get(IV);
200: if (iv != null)
201: this.iv = (byte[]) iv.clone();
202: else
203: this.iv = new byte[modeBlockSize];
204: cipher.init(attributes);
205: setup();
206: }
207: }
208:
209: public int currentBlockSize()
210: {
211: if (state == -1)
212: throw new IllegalStateException();
213: return modeBlockSize;
214: }
215:
216: public void reset()
217: {
218: synchronized (lock)
219: {
220: state = -1;
221: iv = null;
222: cipher.reset();
223: teardown();
224: }
225: }
226:
227: public boolean selfTest()
228: {
229: int ks;
230: Iterator bit;
231: for (Iterator kit = keySizes(); kit.hasNext();)
232: {
233: ks = ((Integer) kit.next()).intValue();
234: for (bit = blockSizes(); bit.hasNext();)
235: if (! testSymmetry(ks, ((Integer) bit.next()).intValue()))
236: return false;
237: }
238: return true;
239: }
240:
241: public abstract Object clone();
242:
243:
244: public abstract void setup();
245:
246:
247: public abstract void teardown();
248:
249: public abstract void encryptBlock(byte[] in, int i, byte[] out, int o);
250:
251: public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
252:
253: private boolean testSymmetry(int ks, int bs)
254: {
255: try
256: {
257: IMode mode = (IMode) this.clone();
258: byte[] iv = new byte[cipherBlockSize];
259: byte[] k = new byte[ks];
260: int i;
261: for (i = 0; i < ks; i++)
262: k[i] = (byte) i;
263: int blockCount = 5;
264: int limit = blockCount * bs;
265: byte[] pt = new byte[limit];
266: for (i = 0; i < limit; i++)
267: pt[i] = (byte) i;
268: byte[] ct = new byte[limit];
269: byte[] cpt = new byte[limit];
270: Map map = new HashMap();
271: map.put(KEY_MATERIAL, k);
272: map.put(CIPHER_BLOCK_SIZE, Integer.valueOf(cipherBlockSize));
273: map.put(STATE, Integer.valueOf(ENCRYPTION));
274: map.put(IV, iv);
275: map.put(MODE_BLOCK_SIZE, Integer.valueOf(bs));
276: mode.reset();
277: mode.init(map);
278: for (i = 0; i < blockCount; i++)
279: mode.update(pt, i * bs, ct, i * bs);
280: mode.reset();
281: map.put(STATE, Integer.valueOf(DECRYPTION));
282: mode.init(map);
283: for (i = 0; i < blockCount; i++)
284: mode.update(ct, i * bs, cpt, i * bs);
285: return Arrays.equals(pt, cpt);
286: }
287: catch (Exception x)
288: {
289: x.printStackTrace(System.err);
290: return false;
291: }
292: }
293: }