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