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