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.CipherParameters;
022    import org.bouncycastle.crypto.CryptoException;
023    import org.bouncycastle.crypto.DataLengthException;
024    import org.bouncycastle.crypto.modes.AEADBlockCipher;
025    import org.bouncycastle.crypto.modes.CCMBlockCipher;
026    import org.bouncycastle.crypto.modes.CFBBlockCipher;
027    import org.bouncycastle.crypto.modes.OFBBlockCipher;
028    import org.cumulus4j.crypto.AbstractCipher;
029    import org.cumulus4j.crypto.CipherOperationMode;
030    
031    /**
032     * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
033     */
034    public class AEADBlockCipherImpl extends AbstractCipher
035    {
036            private AEADBlockCipher delegate;
037    
038            public AEADBlockCipherImpl(String transformation, AEADBlockCipher delegate) {
039                    super(transformation);
040                    this.delegate = delegate;
041            }
042    
043            @Override
044            public void reset() {
045                    delegate.reset();
046            }
047    
048            @Override
049            public int getInputBlockSize() {
050                    return delegate.getUnderlyingCipher().getBlockSize();
051            }
052    
053            @Override
054            public int getOutputBlockSize() {
055                    return delegate.getUnderlyingCipher().getBlockSize();
056            }
057    
058            @Override
059            public int getUpdateOutputSize(int length) {
060                    return delegate.getUpdateOutputSize(length);
061            }
062    
063            @Override
064            public int getOutputSize(int length) {
065                    return delegate.getOutputSize(length);
066            }
067    
068            @Override
069            public int update(byte in, byte[] out, int outOff)
070            throws DataLengthException, IllegalStateException, CryptoException
071            {
072                    return delegate.processByte(in, out, outOff);
073            }
074    
075            @Override
076            public int update(byte[] in, int inOff, int inLen, byte[] out, int outOff)
077            throws DataLengthException, IllegalStateException, CryptoException
078            {
079                    return delegate.processBytes(in, inOff, inLen, out, outOff);
080            }
081    
082            @Override
083            public int doFinal(byte[] out, int outOff)
084            throws DataLengthException, IllegalStateException, CryptoException
085            {
086                    return delegate.doFinal(out, outOff);
087            }
088    
089            private int ivSize = -1;
090    
091            @Override
092            public int getIVSize()
093            {
094                    int ivSize = this.ivSize;
095                    if (ivSize < 0) {
096                            BlockCipher underlyingCipher = delegate.getUnderlyingCipher();
097    
098                            if (underlyingCipher instanceof CFBBlockCipher)
099                                    ivSize = ((CFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize();
100                            else if (underlyingCipher instanceof OFBBlockCipher)
101                                    ivSize = ((OFBBlockCipher)underlyingCipher).getUnderlyingCipher().getBlockSize();
102                            else
103                                    ivSize = underlyingCipher.getBlockSize();
104    
105                            if (delegate instanceof CCMBlockCipher)
106                                    --ivSize;
107    
108                            this.ivSize = ivSize;
109                    }
110    
111                    return ivSize;
112            }
113    
114            @Override
115            protected void _init(CipherOperationMode mode, CipherParameters parameters)
116            throws IllegalArgumentException
117            {
118                    delegate.init(CipherOperationMode.ENCRYPT == mode, parameters);
119            }
120    
121    //      @Override
122    //      public AsymmetricCipherKeyPairGenerator createKeyPairGenerator(boolean initWithDefaults)
123    //      throws UnsupportedOperationException
124    //      {
125    //              throw new UnsupportedOperationException("This is a SYMMETRIC cipher! Cannot get an appropriate key pair generator!");
126    //      }
127    //
128    //      @Override
129    //      public SecretKeyGenerator createSecretKeyGenerator(boolean initWithDefaults)
130    //      {
131    //              String algorithmName = CryptoRegistry.splitTransformation(getTransformation())[0];
132    //              try {
133    //                      return CryptoRegistry.sharedInstance().createSecretKeyGenerator(algorithmName, initWithDefaults);
134    //              } catch (NoSuchAlgorithmException e) {
135    //                      throw new RuntimeException(e); // We should be able to provide an SecretKeyGenerator for every Cipher => RuntimeException
136    //              }
137    //      }
138    }