14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.symmetric.util;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.AlgorithmParameters;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidAlgorithmParameterException;
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidKeyException;
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidParameterException;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.Key;
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.NoSuchAlgorithmException;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.SecureRandom;
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.spec.AlgorithmParameterSpec;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.BadPaddingException;
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.Cipher;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.IllegalBlockSizeException;
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.NoSuchPaddingException;
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.SecretKey;
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.ShortBufferException;
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.IvParameterSpec;
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.PBEParameterSpec;
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC2ParameterSpec;
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC5ParameterSpec;
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
25a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.crypto.BlockCipher;
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.BufferedBlockCipher;
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.CipherParameters;
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.DataLengthException;
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.InvalidCipherTextException;
30e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.crypto.OutputLengthException;
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.AEADBlockCipher;
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CBCBlockCipher;
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CCMBlockCipher;
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CFBBlockCipher;
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CTSBlockCipher;
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.EAXBlockCipher;
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.GCMBlockCipher;
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.GOFBBlockCipher;
42a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom// import org.bouncycastle.crypto.modes.OCBBlockCipher;
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.OFBBlockCipher;
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.SICBlockCipher;
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.BlockCipherPadding;
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ISO10126d2Padding;
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ISO7816d4Padding;
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.TBCPadding;
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.X923Padding;
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ZeroBytePadding;
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.KeyParameter;
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithIV;
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithRandom;
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.params.ParametersWithSBox;
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.RC2Parameters;
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.params.RC5Parameters;
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider;
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.jce.spec.GOST28147ParameterSpec;
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.util.Strings;
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class BaseBlockCipher
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends BaseWrapCipher
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    implements PBE
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    // specs we can handle.
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private Class[]                 availableSpecs =
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    {
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // BEGIN android-removed
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC2ParameterSpec.class,
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC5ParameterSpec.class,
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // END android-removed
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        IvParameterSpec.class,
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        PBEParameterSpec.class,
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // BEGIN android-removed
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // GOST28147ParameterSpec.class
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // END android-removed
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    };
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
94a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private BlockCipher             baseEngine;
95a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private BlockCipherProvider     engineProvider;
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private GenericBlockCipher      cipher;
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ParametersWithIV        ivParam;
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private int                     ivLength = 0;
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private boolean                 padded;
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private PBEParameterSpec        pbeSpec = null;
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private String                  pbeAlgorithm = null;
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private String                  modeName = null;
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
109a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BlockCipher engine)
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine;
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher = new BufferedGenericBlockCipher(engine);
1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
117a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BlockCipherProvider provider)
118a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
119a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        baseEngine = provider.get();
120a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        engineProvider = provider;
121a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
122a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        cipher = new BufferedGenericBlockCipher(provider.get());
123a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
124a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
125a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    protected BaseBlockCipher(
1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        org.bouncycastle.crypto.BlockCipher engine,
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine;
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.cipher = new BufferedGenericBlockCipher(engine);
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength / 8;
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedBlockCipher engine,
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine.getUnderlyingCipher();
1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.cipher = new BufferedGenericBlockCipher(engine);
1424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength / 8;
1434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetBlockSize()
1464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return baseEngine.getBlockSize();
1484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineGetIV()
1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return (ivParam != null) ? ivParam.getIV() : null;
1534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetKeySize(
1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key     key)
1574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return key.getEncoded().length * 8;
1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetOutputSize(
1624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return cipher.getOutputSize(inputLen);
1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected AlgorithmParameters engineGetParameters()
1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (engineParams == null)
1704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (pbeSpec != null)
1724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
1744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
1764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams.init(pbeSpec);
1774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
1794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return null;
1814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (ivParam != null)
1844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                String  name = cipher.getUnderlyingCipher().getAlgorithmName();
1864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (name.indexOf('/') >= 0)
1884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    name = name.substring(0, name.indexOf('/'));
1904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
1934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME);
1954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams.init(ivParam.getIV());
1964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
1984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new RuntimeException(e.toString());
2004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return engineParams;
2054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetMode(
2084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  mode)
2094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws NoSuchAlgorithmException
2104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
2114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        modeName = Strings.toUpperCase(mode);
2124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (modeName.equals("ECB"))
2144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = 0;
2164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(baseEngine);
2174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.equals("CBC"))
2194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(
2224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            new CBCBlockCipher(baseEngine));
2234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("OFB"))
2254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (modeName.length() != 3)
2284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int wordSize = Integer.parseInt(modeName.substring(3));
2304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                new OFBBlockCipher(baseEngine, wordSize));
2334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
2354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
2384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CFB"))
2414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (modeName.length() != 3)
2444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int wordSize = Integer.parseInt(modeName.substring(3));
2464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                new CFBBlockCipher(baseEngine, wordSize));
2494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
2514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
2544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
2574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("PGP"))
2584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
2594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV");
2604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
2624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(
2634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         new PGPCFBBlockCipher(baseEngine, inlineIV));
2644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
2654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.equalsIgnoreCase("OpenPGPCFB"))
2664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
2674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = 0;
2684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(
2694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         new OpenPGPCFBBlockCipher(baseEngine));
2704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
2714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
2724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("SIC"))
2734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivLength < 16)
2764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
2784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
2804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new SICBlockCipher(baseEngine)));
2814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CTR"))
2834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
2864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new SICBlockCipher(baseEngine)));
2874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
2894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("GOFB"))
2904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
2914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
2924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
2934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 new GOFBBlockCipher(baseEngine)));
2944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
2954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
2964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CTS"))
2974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine)));
3004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CCM"))
3024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
3044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
3054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
307a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // else if (modeName.startsWith("OCB"))
308a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // {
309a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     if (engineProvider != null)
310a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     {
311a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //         ivLength = baseEngine.getBlockSize();
312a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //         cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
313a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     }
314a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     else
315a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     {
316a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //         throw new NoSuchAlgorithmException("can't support mode " + mode);
317a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     }
318a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // }
3194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("EAX"))
3204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
3214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
3224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine));
3234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
3244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
3254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("GCM"))
3264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
3284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
3294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
3314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new NoSuchAlgorithmException("can't support mode " + mode);
3334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetPadding(
3374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  padding)
3384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws NoSuchPaddingException
3394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  paddingName = Strings.toUpperCase(padding);
3414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (paddingName.equals("NOPADDING"))
3434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (cipher.wrapOnNoPadding())
3454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher()));
3474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (paddingName.equals("WITHCTS"))
3504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher()));
3524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
3544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            padded = true;
3564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (isAEADModeName(modeName))
3584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes.");
3604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING"))
3624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher());
3644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ZEROBYTEPADDING"))
3664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding());
3684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING"))
3704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding());
3724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING"))
3744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding());
3764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING"))
3784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding());
3804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("TBCPADDING"))
3824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding());
3844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
3864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
3874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new NoSuchPaddingException("Padding " + padding + " unknown.");
3884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
3934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                     opmode,
3944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                     key,
3954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  params,
3964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom            random)
3974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException, InvalidAlgorithmParameterException
3984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        CipherParameters        param;
4004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeSpec = null;
4024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeAlgorithm = null;
4034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.engineParams = null;
4044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // basic key check
4074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!(key instanceof SecretKey))
4094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
4114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // for RC5-64 we must have some default parameters
4154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64"))
4174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in.");
4194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it).
4234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (key instanceof BCPBEKey)
4254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            BCPBEKey k = (BCPBEKey)key;
4274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getOID() != null)
4294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getOID().getId();
4314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
4334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getAlgorithm();
4354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getParam() != null)
4384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = k.getParam();
440a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (params instanceof IvParameterSpec)
441a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
442a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    IvParameterSpec iv = (IvParameterSpec)params;
443a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
444a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    param = new ParametersWithIV(param, iv.getIV());
445a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
4464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (params instanceof PBEParameterSpec)
4484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeSpec = (PBEParameterSpec)params;
4504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName());
4514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
4534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
4554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (param instanceof ParametersWithIV)
4584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
4604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params == null)
4634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new KeyParameter(key.getEncoded());
4654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params instanceof IvParameterSpec)
4674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivLength != 0)
4694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                IvParameterSpec p = (IvParameterSpec)params;
4714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (p.getIV().length != ivLength && !isAEADModeName(modeName))
4734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
4744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
4754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
4764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (key instanceof RepeatedSecretKeySpec)
4784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
4794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    param = new ParametersWithIV(null, p.getIV());
4804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ivParam = (ParametersWithIV)param;
4814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
4824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else
4834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
4844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV());
4854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ivParam = (ParametersWithIV)param;
4864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
4874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
4894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (modeName != null && modeName.equals("ECB"))
4914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
4924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new InvalidAlgorithmParameterException("ECB mode does not use an IV");
4934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
4944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = new KeyParameter(key.getEncoded());
4964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
4994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof GOST28147ParameterSpec)
5004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     GOST28147ParameterSpec    gost28147Param = (GOST28147ParameterSpec)params;
5024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new ParametersWithSBox(
5044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox());
5054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (gost28147Param.getIV() != null && ivLength != 0)
5074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, gost28147Param.getIV());
5094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
5104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
5124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof RC2ParameterSpec)
5134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     RC2ParameterSpec    rc2Param = (RC2ParameterSpec)params;
5154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits());
5174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (rc2Param.getIV() != null && ivLength != 0)
5194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, rc2Param.getIV());
5214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
5224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
5244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof RC5ParameterSpec)
5254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     RC5ParameterSpec    rc5Param = (RC5ParameterSpec)params;
5274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds());
5294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (baseEngine.getAlgorithmName().startsWith("RC5"))
5304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         if (baseEngine.getAlgorithmName().equals("RC5-32"))
5324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         {
5334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             if (rc5Param.getWordSize() != 32)
5344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             {
5354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + ".");
5364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             }
5374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         }
5384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         else if (baseEngine.getAlgorithmName().equals("RC5-64"))
5394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         {
5404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             if (rc5Param.getWordSize() != 64)
5414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             {
5424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + ".");
5434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             }
5444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         }
5454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     else
5474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5.");
5494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if ((rc5Param.getIV() != null) && (ivLength != 0))
5514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, rc5Param.getIV());
5534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
5544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
5564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
5574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
5584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidAlgorithmParameterException("unknown parameter type.");
5604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if ((ivLength != 0) && !(param instanceof ParametersWithIV))
5634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            SecureRandom    ivRandom = random;
5654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivRandom == null)
5674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom = new SecureRandom();
5694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
5724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[]  iv = new byte[ivLength];
5744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom.nextBytes(iv);
5764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = new ParametersWithIV(param, iv);
5774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
5784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0)
5804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("no IV set when one expected");
5824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (random != null && padded)
5864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new ParametersWithRandom(param, random);
5884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
5914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            switch (opmode)
5934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.ENCRYPT_MODE:
5954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.WRAP_MODE:
5964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher.init(true, param);
5974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                break;
5984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.DECRYPT_MODE:
5994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.UNWRAP_MODE:
6004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher.init(false, param);
6014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                break;
6024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            default:
6034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidParameterException("unknown opmode " + opmode + " passed");
6044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (Exception e)
6074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException(e.getMessage());
6094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
6114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
6134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
6144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
6154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameters params,
6164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
6174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws InvalidKeyException, InvalidAlgorithmParameterException
6184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
6194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  paramSpec = null;
6204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params != null)
6224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            for (int i = 0; i != availableSpecs.length; i++)
6244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
6264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
6274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    paramSpec = params.getParameterSpec(availableSpecs[i]);
6284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    break;
6294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
6304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
6314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
6324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    // try again if possible
6334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
6344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (paramSpec == null)
6374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
6394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineInit(opmode, key, paramSpec, random);
6434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineParams = params;
6454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
6464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
6484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
6494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
6504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
6514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException
6524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
6534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
6544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
6564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (InvalidAlgorithmParameterException e)
6584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException(e.getMessage());
6604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
6624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineUpdate(
6644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
6654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
6664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
6674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
6684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     length = cipher.getUpdateOutputSize(inputLen);
6694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (length > 0)
6714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[]  out = new byte[length];
6734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int len = cipher.processBytes(input, inputOffset, inputLen, out, 0);
6754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (len == 0)
6774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
6784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return null;
6794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
6804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (len != out.length)
6814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
6824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    byte[]  tmp = new byte[len];
6834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    System.arraycopy(out, 0, tmp, 0, len);
6854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return tmp;
6874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
6884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return out;
6904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.processBytes(input, inputOffset, inputLen, null, 0);
6934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return null;
6954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
6964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineUpdate(
6984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
6994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
7004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
7014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
7024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     outputOffset)
7034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws ShortBufferException
7044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
7054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
7064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
7084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
7104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new ShortBufferException(e.getMessage());
7124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineDoFinal(
7164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
7174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
7184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
7194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IllegalBlockSizeException, BadPaddingException
7204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
7214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     len = 0;
7224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  tmp = new byte[engineGetOutputSize(inputLen)];
7234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (inputLen != 0)
7254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0);
7274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
7304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            len += cipher.doFinal(tmp, len);
7324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
7344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalBlockSizeException(e.getMessage());
7364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (InvalidCipherTextException e)
7384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new BadPaddingException(e.getMessage());
7404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (len == tmp.length)
7434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return tmp;
7454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  out = new byte[len];
7484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        System.arraycopy(tmp, 0, out, 0, len);
7504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return out;
7524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineDoFinal(
7554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
7564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
7574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
7584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
759e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        int     outputOffset)
7604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
7614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
762e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        try
763e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
764e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            int     len = 0;
7654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
766e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (inputLen != 0)
767e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
768a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
769e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
7704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
771e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return (len + cipher.doFinal(output, outputOffset + len));
7724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
773e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        catch (OutputLengthException e)
7744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
775e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            throw new ShortBufferException(e.getMessage());
7764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
7784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalBlockSizeException(e.getMessage());
7804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (InvalidCipherTextException e)
7824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new BadPaddingException(e.getMessage());
7844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private boolean isAEADModeName(
7884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String modeName)
7894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
790a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // BEGIN android-changed
791a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return "CCM".equals(modeName) || "GCM".equals(modeName);
792a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // END android-changed
7934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /*
7964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * The ciphers that inherit from us.
7974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
7984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static private interface GenericBlockCipher
8004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
8014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
8024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException;
8034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding();
8054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName();
8074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher();
8094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len);
8114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len);
8134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff)
8154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws DataLengthException;
8164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
8184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws DataLengthException;
8194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int doFinal(byte[] out, int outOff)
8214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalStateException, InvalidCipherTextException;
8224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static class BufferedGenericBlockCipher
8254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        implements GenericBlockCipher
8264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
8274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        private BufferedBlockCipher cipher;
8284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(BufferedBlockCipher cipher)
8304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = cipher;
8324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher)
8354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = new PaddedBufferedBlockCipher(cipher);
8374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding)
8404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = new PaddedBufferedBlockCipher(cipher, padding);
8424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
8454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException
8464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(forEncryption, params);
8484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding()
8514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return !(cipher instanceof CTSBlockCipher);
8534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName()
8564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher().getAlgorithmName();
8584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
8614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher();
8634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len)
8664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getOutputSize(len);
8684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len)
8714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUpdateOutputSize(len);
8734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
8764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processByte(in, out, outOff);
8784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
8814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(in, inOff, len, out, outOff);
8834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
8864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.doFinal(out, outOff);
8884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static class AEADGenericBlockCipher
8924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        implements GenericBlockCipher
8934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
8944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        private AEADBlockCipher cipher;
8954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AEADGenericBlockCipher(AEADBlockCipher cipher)
8974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = cipher;
8994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
9024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException
9034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(forEncryption, params);
9054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName()
9084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher().getAlgorithmName();
9104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding()
9134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return false;
9154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
9184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher();
9204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len)
9234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getOutputSize(len);
9254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len)
9284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUpdateOutputSize(len);
9304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
9334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processByte(in, out, outOff);
9354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
9384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(in, inOff, len, out, outOff);
9404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
9434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.doFinal(out, outOff);
9454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
9474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
948