01: package org.bouncycastle.crypto.modes;
02:
03: import org.bouncycastle.crypto.BlockCipher;
04: import org.bouncycastle.crypto.CipherParameters;
05: import org.bouncycastle.crypto.DataLengthException;
06: import org.bouncycastle.crypto.params.ParametersWithIV;
07:
08: /**
09: * Implements the Segmented Integer Counter (SIC) mode on top of a simple
10: * block cipher. This mode is also known as CTR mode.
11: */
12: public class SICBlockCipher implements BlockCipher {
13: private final BlockCipher cipher;
14: private final int blockSize;
15:
16: private byte[] IV;
17: private byte[] counter;
18: private byte[] counterOut;
19:
20: /**
21: * Basic constructor.
22: *
23: * @param c the block cipher to be used.
24: */
25: public SICBlockCipher(BlockCipher c) {
26: this .cipher = c;
27: this .blockSize = cipher.getBlockSize();
28: this .IV = new byte[blockSize];
29: this .counter = new byte[blockSize];
30: this .counterOut = new byte[blockSize];
31: }
32:
33: /**
34: * return the underlying block cipher that we are wrapping.
35: *
36: * @return the underlying block cipher that we are wrapping.
37: */
38: public BlockCipher getUnderlyingCipher() {
39: return cipher;
40: }
41:
42: public void init(boolean forEncryption, //ignored by this CTR mode
43: CipherParameters params) throws IllegalArgumentException {
44: if (params instanceof ParametersWithIV) {
45: ParametersWithIV ivParam = (ParametersWithIV) params;
46: byte[] iv = ivParam.getIV();
47: System.arraycopy(iv, 0, IV, 0, IV.length);
48:
49: reset();
50: cipher.init(true, ivParam.getParameters());
51: }
52: }
53:
54: public String getAlgorithmName() {
55: return cipher.getAlgorithmName() + "/SIC";
56: }
57:
58: public int getBlockSize() {
59: return cipher.getBlockSize();
60: }
61:
62: public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
63: throws DataLengthException, IllegalStateException {
64: cipher.processBlock(counter, 0, counterOut, 0);
65:
66: //
67: // XOR the counterOut with the plaintext producing the cipher text
68: //
69: for (int i = 0; i < counterOut.length; i++) {
70: out[outOff + i] = (byte) (counterOut[i] ^ in[inOff + i]);
71: }
72:
73: int carry = 1;
74:
75: for (int i = counter.length - 1; i >= 0; i--) {
76: int x = (counter[i] & 0xff) + carry;
77:
78: if (x > 0xff) {
79: carry = 1;
80: } else {
81: carry = 0;
82: }
83:
84: counter[i] = (byte) x;
85: }
86:
87: return counter.length;
88: }
89:
90: public void reset() {
91: System.arraycopy(IV, 0, counter, 0, counter.length);
92: cipher.reset();
93: }
94: }
|