001 /*
002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org
003 * Copyright (C) 2011 NightLabs Consulting GmbH
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018 package org.cumulus4j.crypto.internal.symmetric;
019
020 import org.bouncycastle.crypto.BlockCipher;
021 import org.bouncycastle.crypto.BufferedBlockCipher;
022 import org.bouncycastle.crypto.CipherParameters;
023 import org.bouncycastle.crypto.CryptoException;
024 import org.bouncycastle.crypto.DataLengthException;
025 import org.bouncycastle.crypto.modes.CBCBlockCipher;
026 import org.bouncycastle.crypto.modes.CFBBlockCipher;
027 import org.bouncycastle.crypto.modes.CTSBlockCipher;
028 import org.bouncycastle.crypto.modes.OFBBlockCipher;
029 import org.cumulus4j.crypto.AbstractCipher;
030 import org.cumulus4j.crypto.CipherOperationMode;
031 import org.cumulus4j.crypto.CryptoRegistry;
032
033 /**
034 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
035 */
036 public class BufferedBlockCipherImpl
037 extends AbstractCipher
038 {
039 private BufferedBlockCipher delegate;
040
041 public BufferedBlockCipherImpl(String transformation, BufferedBlockCipher delegate) {
042 super(transformation);
043 this.delegate = delegate;
044 }
045
046 @Override
047 public void _init(CipherOperationMode mode, CipherParameters parameters)
048 throws IllegalArgumentException
049 {
050 delegate.init(CipherOperationMode.ENCRYPT == mode, parameters);
051 }
052
053 @Override
054 public int getInputBlockSize() {
055 return delegate.getBlockSize();
056 // return delegate.getUnderlyingCipher().getBlockSize();
057 }
058
059 @Override
060 public int getOutputBlockSize() {
061 return delegate.getBlockSize();
062 // return delegate.getUnderlyingCipher().getBlockSize();
063 }
064
065 @Override
066 public void reset() {
067 delegate.reset();
068 }
069
070 @Override
071 public int getUpdateOutputSize(int len) {
072 return delegate.getUpdateOutputSize(len);
073 }
074
075 @Override
076 public int getOutputSize(int length) {
077 return delegate.getOutputSize(length);
078 }
079
080 @Override
081 public int update(byte in, byte[] out, int outOff)
082 throws DataLengthException, IllegalStateException, CryptoException
083 {
084 return delegate.processByte(in, out, outOff);
085 }
086
087 @Override
088 public int update(byte[] in, int inOff, int len, byte[] out, int outOff)
089 throws DataLengthException, IllegalStateException, CryptoException
090 {
091 return delegate.processBytes(in, inOff, len, out, outOff);
092 }
093
094 @Override
095 public int doFinal(byte[] out, int outOff)
096 throws DataLengthException, IllegalStateException, CryptoException
097 {
098 return delegate.doFinal(out, outOff);
099 }
100
101 private int ivSize = -1;
102
103 @Override
104 public int getIVSize()
105 {
106 if (ivSize < 0) {
107 String mode = CryptoRegistry.splitTransformation(getTransformation())[1];
108 if ("".equals(mode) || "ECB".equals(mode))
109 ivSize = 0; // No block cipher mode (i.e. ECB) => no IV.
110 else {
111 if (delegate instanceof CTSBlockCipher) {
112 CTSBlockCipher cts = (CTSBlockCipher) delegate;
113 if (cts.getUnderlyingCipher() instanceof CBCBlockCipher)
114 ivSize = cts.getUnderlyingCipher().getBlockSize();
115 else
116 ivSize = 0;
117 }
118 else {
119 BlockCipher underlyingCipher = delegate.getUnderlyingCipher();
120
121 if (underlyingCipher instanceof CFBBlockCipher)
122 ivSize = ((CFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize();
123 else if (underlyingCipher instanceof OFBBlockCipher)
124 ivSize = ((OFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize();
125 else
126 ivSize = underlyingCipher.getBlockSize();
127 }
128 }
129 }
130 return ivSize;
131 }
132
133 // @Override
134 // public AsymmetricCipherKeyPairGenerator createKeyPairGenerator(boolean initWithDefaults)
135 // throws UnsupportedOperationException
136 // {
137 // throw new UnsupportedOperationException("This is a SYMMETRIC cipher! Cannot get an appropriate key pair generator!");
138 // }
139 //
140 // @Override
141 // public SecretKeyGenerator createSecretKeyGenerator(boolean initWithDefaults)
142 // {
143 // String algorithmName = CryptoRegistry.splitTransformation(getTransformation())[0];
144 // try {
145 // return CryptoRegistry.sharedInstance().createSecretKeyGenerator(algorithmName, initWithDefaults);
146 // } catch (NoSuchAlgorithmException e) {
147 // throw new RuntimeException(e); // We should be able to provide an SecretKeyGenerator for every Cipher => RuntimeException
148 // }
149 // }
150 }