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    }