Home | History | Annotate | Download | only in cipher
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 package ch.ethz.ssh2.crypto.cipher;
      6 
      7 /**
      8  * CBCMode.
      9  *
     10  * @author Christian Plattner
     11  * @version 2.50, 03/15/10
     12  */
     13 public class CBCMode implements BlockCipher
     14 {
     15 	BlockCipher tc;
     16 	int blockSize;
     17 	boolean doEncrypt;
     18 
     19 	byte[] cbc_vector;
     20 	byte[] tmp_vector;
     21 
     22 	public void init(boolean forEncryption, byte[] key)
     23 	{
     24 	}
     25 
     26 	public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt)
     27 			throws IllegalArgumentException
     28 	{
     29 		this.tc = tc;
     30 		this.blockSize = tc.getBlockSize();
     31 		this.doEncrypt = doEncrypt;
     32 
     33 		if (this.blockSize != iv.length)
     34 			throw new IllegalArgumentException("IV must be " + blockSize
     35 					+ " bytes long! (currently " + iv.length + ")");
     36 
     37 		this.cbc_vector = new byte[blockSize];
     38 		this.tmp_vector = new byte[blockSize];
     39 		System.arraycopy(iv, 0, cbc_vector, 0, blockSize);
     40 	}
     41 
     42 	public int getBlockSize()
     43 	{
     44 		return blockSize;
     45 	}
     46 
     47 	private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff)
     48 	{
     49 		for (int i = 0; i < blockSize; i++)
     50 			cbc_vector[i] ^= src[srcoff + i];
     51 
     52 		tc.transformBlock(cbc_vector, 0, dst, dstoff);
     53 
     54 		System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize);
     55 	}
     56 
     57 	private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff)
     58 	{
     59 		/* Assume the worst, src and dst are overlapping... */
     60 
     61 		System.arraycopy(src, srcoff, tmp_vector, 0, blockSize);
     62 
     63 		tc.transformBlock(src, srcoff, dst, dstoff);
     64 
     65 		for (int i = 0; i < blockSize; i++)
     66 			dst[dstoff + i] ^= cbc_vector[i];
     67 
     68 		/* ...that is why we need a tmp buffer. */
     69 
     70 		byte[] swap = cbc_vector;
     71 		cbc_vector = tmp_vector;
     72 		tmp_vector = swap;
     73 	}
     74 
     75 	public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff)
     76 	{
     77 		if (doEncrypt)
     78 			encryptBlock(src, srcoff, dst, dstoff);
     79 		else
     80 			decryptBlock(src, srcoff, dst, dstoff);
     81 	}
     82 }
     83