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