14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.symmetric.util;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.lang.reflect.Constructor;
45db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.lang.reflect.Method;
55db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport java.nio.ByteBuffer;
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.AlgorithmParameters;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidAlgorithmParameterException;
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidKeyException;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidParameterException;
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.Key;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.NoSuchAlgorithmException;
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.SecureRandom;
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.spec.AlgorithmParameterSpec;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.BadPaddingException;
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.Cipher;
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.IllegalBlockSizeException;
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.NoSuchPaddingException;
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.SecretKey;
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.ShortBufferException;
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.IvParameterSpec;
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.PBEParameterSpec;
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC2ParameterSpec;
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC5ParameterSpec;
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.asn1.cms.GCMParameters;
29a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.crypto.BlockCipher;
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.BufferedBlockCipher;
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.CipherParameters;
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.DataLengthException;
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.InvalidCipherTextException;
34e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstromimport org.bouncycastle.crypto.OutputLengthException;
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.AEADBlockCipher;
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CBCBlockCipher;
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CCMBlockCipher;
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CFBBlockCipher;
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.CTSBlockCipher;
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.EAXBlockCipher;
425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.crypto.modes.GCFBBlockCipher;
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.GCMBlockCipher;
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.GOFBBlockCipher;
47a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom// import org.bouncycastle.crypto.modes.OCBBlockCipher;
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.OFBBlockCipher;
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.modes.SICBlockCipher;
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.BlockCipherPadding;
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ISO10126d2Padding;
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ISO7816d4Padding;
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.TBCPadding;
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.X923Padding;
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.paddings.ZeroBytePadding;
625db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.crypto.params.AEADParameters;
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.KeyParameter;
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithIV;
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithRandom;
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.params.ParametersWithSBox;
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.RC2Parameters;
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import org.bouncycastle.crypto.params.RC5Parameters;
725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root// import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider;
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.util.Strings;
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class BaseBlockCipher
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends BaseWrapCipher
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    implements PBE
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    // specs we can handle.
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private Class[]                 availableSpecs =
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    {
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // BEGIN android-removed
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC2ParameterSpec.class,
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC5ParameterSpec.class,
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // END android-removed
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        IvParameterSpec.class,
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        PBEParameterSpec.class,
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // BEGIN android-removed
965db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                                        // GOST28147ParameterSpec.class,
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // END android-removed
985db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                                        gcmSpecClass
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    };
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
101a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private BlockCipher             baseEngine;
102a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private BlockCipherProvider     engineProvider;
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private GenericBlockCipher      cipher;
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ParametersWithIV        ivParam;
1055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private AEADParameters          aeadParams;
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private int                     ivLength = 0;
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private boolean                 padded;
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private PBEParameterSpec        pbeSpec = null;
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private String                  pbeAlgorithm = null;
1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private String                  modeName = null;
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1165db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    private static Class lookup(String className)
1175db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
1185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        try
1195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
1205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            Class def = BaseBlockCipher.class.getClassLoader().loadClass(className);
1215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
1225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            return def;
1235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
1245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        catch (Exception e)
1255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
1265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            return null;
1275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
1285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
1295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
131a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BlockCipher engine)
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine;
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher = new BufferedGenericBlockCipher(engine);
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
139a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        BlockCipherProvider provider)
140a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
141a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        baseEngine = provider.get();
142a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        engineProvider = provider;
143a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
144a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        cipher = new BufferedGenericBlockCipher(provider.get());
145a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
146a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
147a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    protected BaseBlockCipher(
1485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        AEADBlockCipher engine)
1495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
1505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        baseEngine = engine.getUnderlyingCipher();
1515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        ivLength = baseEngine.getBlockSize();
1525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        cipher = new AEADGenericBlockCipher(engine);
1535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
1545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
1555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    protected BaseBlockCipher(
1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        org.bouncycastle.crypto.BlockCipher engine,
1574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
1584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine;
1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.cipher = new BufferedGenericBlockCipher(engine);
1624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength / 8;
1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseBlockCipher(
1664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedBlockCipher engine,
1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        baseEngine = engine.getUnderlyingCipher();
1704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.cipher = new BufferedGenericBlockCipher(engine);
1724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength / 8;
1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetBlockSize()
1764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return baseEngine.getBlockSize();
1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineGetIV()
1814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
182d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (aeadParams != null)
183d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
184b6f0864d4715861be258f5e61d8959bf4bcf0e8cKenny Root            return aeadParams.getNonce();
185b6f0864d4715861be258f5e61d8959bf4bcf0e8cKenny Root        }
186d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
1874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return (ivParam != null) ? ivParam.getIV() : null;
1884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetKeySize(
1914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key     key)
1924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return key.getEncoded().length * 8;
1944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetOutputSize(
1974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
1984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return cipher.getOutputSize(inputLen);
2004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected AlgorithmParameters engineGetParameters()
2034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
2044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (engineParams == null)
2054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (pbeSpec != null)
2074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
2094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
210028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro                    engineParams = createParametersInstance(pbeAlgorithm);
2114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams.init(pbeSpec);
2124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
2144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
2154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return null;
2164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (ivParam != null)
2194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                String  name = cipher.getUnderlyingCipher().getAlgorithmName();
2214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (name.indexOf('/') >= 0)
2234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
2244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    name = name.substring(0, name.indexOf('/'));
2254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
2284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
229028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro                    engineParams = createParametersInstance(name);
2304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams.init(ivParam.getIV());
2314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
2334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
2344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new RuntimeException(e.toString());
2354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2375db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            else if (aeadParams != null)
2385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
2395db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                try
2405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                {
241028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro                    engineParams = createParametersInstance("GCM");
2425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize()).getEncoded());
2435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                }
2445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                catch (Exception e)
2455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                {
2465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    throw new RuntimeException(e.toString());
2475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                }
2485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
2494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return engineParams;
2524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetMode(
2554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  mode)
2564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws NoSuchAlgorithmException
2574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
2584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        modeName = Strings.toUpperCase(mode);
2594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (modeName.equals("ECB"))
2614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = 0;
2634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(baseEngine);
2644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.equals("CBC"))
2664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(
2694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                            new CBCBlockCipher(baseEngine));
2704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("OFB"))
2724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (modeName.length() != 3)
2754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int wordSize = Integer.parseInt(modeName.substring(3));
2774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                new OFBBlockCipher(baseEngine, wordSize));
2804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
2824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
2854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CFB"))
2884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
2904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (modeName.length() != 3)
2914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int wordSize = Integer.parseInt(modeName.substring(3));
2934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
2954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                new CFBBlockCipher(baseEngine, wordSize));
2964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
2984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(
3004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
3014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
3024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
3044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("PGP"))
3054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
3064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV");
3075db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //
3084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
3094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(
3104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         new PGPCFBBlockCipher(baseEngine, inlineIV));
3114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
3124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.equalsIgnoreCase("OpenPGPCFB"))
3134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
3144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = 0;
3154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(
3164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         new OpenPGPCFBBlockCipher(baseEngine));
3174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
3185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // else if (modeName.startsWith("SIC"))
3195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // {
3205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     ivLength = baseEngine.getBlockSize();
3215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     if (ivLength < 16)
3225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     {
3235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //         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)");
3245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     }
3255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //                 new SICBlockCipher(baseEngine)));
3275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // }
3284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
3294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CTR"))
3304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
3324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        new SICBlockCipher(baseEngine)));
3344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
3364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("GOFB"))
3374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
3384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
3394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 new GOFBBlockCipher(baseEngine)));
3414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
3425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // else if (modeName.startsWith("GCFB"))
3435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // {
3445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     ivLength = baseEngine.getBlockSize();
3455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //     cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //                 new GCFBBlockCipher(baseEngine)));
3475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        // }
3484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
3494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CTS"))
3504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
3524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine)));
3534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("CCM"))
3554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3565db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            ivLength = 13; // CCM nonce 7..13 bytes
3574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
3584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
360a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // else if (modeName.startsWith("OCB"))
361a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // {
362a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     if (engineProvider != null)
363a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     {
364d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        //         /*
365d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        //          * RFC 7253 4.2. Nonce is a string of no more than 120 bits
366d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        //          */
3675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        //         ivLength = 15;
368a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //         cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
369a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     }
370a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     else
371a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     {
372a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //         throw new NoSuchAlgorithmException("can't support mode " + mode);
373a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        //     }
374a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // }
3754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (modeName.startsWith("EAX"))
3764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
3774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     ivLength = baseEngine.getBlockSize();
3784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine));
3794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
3804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
3814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (modeName.startsWith("GCM"))
3824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivLength = baseEngine.getBlockSize();
3844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
3854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
3874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new NoSuchAlgorithmException("can't support mode " + mode);
3894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetPadding(
3934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  padding)
3944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws NoSuchPaddingException
3954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  paddingName = Strings.toUpperCase(padding);
3974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (paddingName.equals("NOPADDING"))
3994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (cipher.wrapOnNoPadding())
4014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher()));
4034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (paddingName.equals("WITHCTS"))
4064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher()));
4084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
4104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            padded = true;
4124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (isAEADModeName(modeName))
4144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes.");
4164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING"))
4184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher());
4204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ZEROBYTEPADDING"))
4224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding());
4244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING"))
4264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding());
4284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING"))
4304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding());
4324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING"))
4344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding());
4364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (paddingName.equals("TBCPADDING"))
4384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding());
4404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
4424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new NoSuchPaddingException("Padding " + padding + " unknown.");
4444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
4474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
4494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                     opmode,
4504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                     key,
4514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  params,
4524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom            random)
4534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException, InvalidAlgorithmParameterException
4544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
4554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        CipherParameters        param;
4564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeSpec = null;
4584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeAlgorithm = null;
4594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.engineParams = null;
4605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        this.aeadParams = null;
4614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // basic key check
4644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!(key instanceof SecretKey))
4664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
4684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // for RC5-64 we must have some default parameters
4724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64"))
4744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in.");
4764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
4774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it).
4804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
4814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (key instanceof BCPBEKey)
4824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
4834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            BCPBEKey k = (BCPBEKey)key;
4844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getOID() != null)
4864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getOID().getId();
4884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
4904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getAlgorithm();
4924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
4934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
4944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getParam() != null)
4954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
4964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = k.getParam();
497a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                if (params instanceof IvParameterSpec)
498a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                {
499a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    IvParameterSpec iv = (IvParameterSpec)params;
500a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
501a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                    param = new ParametersWithIV(param, iv.getIV());
502a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                }
5035db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // BEGIN android-removed
5045db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // else if (params instanceof GOST28147ParameterSpec)
5055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // {
5065db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     // need to pick up IV and SBox.
5075db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     GOST28147ParameterSpec    gost28147Param = (GOST28147ParameterSpec)params;
5085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //
5095db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     param = new ParametersWithSBox(param, gost28147Param.getSbox());
5105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //
5115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     if (gost28147Param.getIV() != null && ivLength != 0)
5125db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     {
5135db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //         param = new ParametersWithIV(param, gost28147Param.getIV());
5145db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     }
5155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // }
5165db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // END android-removed
5174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (params instanceof PBEParameterSpec)
5194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeSpec = (PBEParameterSpec)params;
5214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName());
5224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
5244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
5264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (param instanceof ParametersWithIV)
5294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
5314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params == null)
5344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new KeyParameter(key.getEncoded());
5364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params instanceof IvParameterSpec)
5384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
5394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivLength != 0)
5404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                IvParameterSpec p = (IvParameterSpec)params;
5424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (p.getIV().length != ivLength && !isAEADModeName(modeName))
5444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
5454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
5464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
5474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // BEGIN android-removed
5495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // if (key instanceof RepeatedSecretKeySpec)
5505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // {
5515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     param = new ParametersWithIV(null, p.getIV());
5525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     ivParam = (ParametersWithIV)param;
5535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // }
5545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // else
5555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // END android-removed
5564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
5574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV());
5584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    ivParam = (ParametersWithIV)param;
5594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
5604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
5624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
5634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (modeName != null && modeName.equals("ECB"))
5644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
5654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new InvalidAlgorithmParameterException("ECB mode does not use an IV");
5664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
5674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
5684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = new KeyParameter(key.getEncoded());
5694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
5704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
5714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // BEGIN android-removed
5724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof GOST28147ParameterSpec)
5734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     GOST28147ParameterSpec    gost28147Param = (GOST28147ParameterSpec)params;
5754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new ParametersWithSBox(
5774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox());
5784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (gost28147Param.getIV() != null && ivLength != 0)
5804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, gost28147Param.getIV());
5824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
5834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
5854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof RC2ParameterSpec)
5864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     RC2ParameterSpec    rc2Param = (RC2ParameterSpec)params;
5884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits());
5904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
5914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (rc2Param.getIV() != null && ivLength != 0)
5924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
5934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, rc2Param.getIV());
5944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
5954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
5964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
5974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // else if (params instanceof RC5ParameterSpec)
5984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // {
5994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     RC5ParameterSpec    rc5Param = (RC5ParameterSpec)params;
6004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
6014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds());
6024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if (baseEngine.getAlgorithmName().startsWith("RC5"))
6034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
6044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         if (baseEngine.getAlgorithmName().equals("RC5-32"))
6054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         {
6064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             if (rc5Param.getWordSize() != 32)
6074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             {
6084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + ".");
6094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             }
6104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         }
6114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         else if (baseEngine.getAlgorithmName().equals("RC5-64"))
6124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         {
6134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             if (rc5Param.getWordSize() != 64)
6144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             {
6154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //                 throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + ".");
6164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //             }
6174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         }
6184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
6194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     else
6204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
6214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5.");
6224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
6234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     if ((rc5Param.getIV() != null) && (ivLength != 0))
6244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     {
6254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         param = new ParametersWithIV(param, rc5Param.getIV());
6264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //         ivParam = (ParametersWithIV)param;
6274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //     }
6284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // }
6294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // END android-removed
6305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        else if (gcmSpecClass != null && gcmSpecClass.isInstance(params))
6315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
6325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
6335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
6345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                throw new InvalidAlgorithmParameterException("GCMParameterSpec can only be used with AEAD modes.");
6355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
6365db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
6375db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            try
6385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
6395db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
6405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
6415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
6425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // BEGIN android-removed
6435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // if (key instanceof RepeatedSecretKeySpec)
6445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // {
6455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                //     param = aeadParams = new AEADParameters(null, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
6465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // }
6475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // else
6485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                // END android-removed
6495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                {
6505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    param = aeadParams = new AEADParameters(new KeyParameter(key.getEncoded()), ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
6515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                }
6525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
6535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            catch (Exception e)
6545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            {
6555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec.");
6565db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            }
6575db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
6584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
6594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidAlgorithmParameterException("unknown parameter type.");
6614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        if ((ivLength != 0) && !(param instanceof ParametersWithIV) && !(param instanceof AEADParameters))
6644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            SecureRandom    ivRandom = random;
6664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivRandom == null)
6684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom = new SecureRandom();
6704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
6734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[]  iv = new byte[ivLength];
6754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom.nextBytes(iv);
6774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = new ParametersWithIV(param, iv);
6784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
6794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0)
6814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("no IV set when one expected");
6834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
6844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (random != null && padded)
6874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new ParametersWithRandom(param, random);
6894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
6904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
6914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
6924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
6934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            switch (opmode)
6944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
6954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.ENCRYPT_MODE:
6964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.WRAP_MODE:
6974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher.init(true, param);
6984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                break;
6994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.DECRYPT_MODE:
7004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            case Cipher.UNWRAP_MODE:
7014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                cipher.init(false, param);
7024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                break;
7034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            default:
7044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidParameterException("unknown opmode " + opmode + " passed");
7054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
7064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (Exception e)
7084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException(e.getMessage());
7104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
7144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
7154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
7164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameters params,
7174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
7184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws InvalidKeyException, InvalidAlgorithmParameterException
7194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
7204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  paramSpec = null;
7214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params != null)
7234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            for (int i = 0; i != availableSpecs.length; i++)
7254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
7265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                if (availableSpecs[i] == null)
7275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                {
7285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                    continue;
7295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root                }
7305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
7324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
7334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    paramSpec = params.getParameterSpec(availableSpecs[i]);
7344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    break;
7354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
7364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
7374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
7384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    // try again if possible
7394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
7404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
7414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (paramSpec == null)
7434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
7444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
7454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
7464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineInit(opmode, key, paramSpec, random);
7494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineParams = params;
7514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
7544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
7554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
7564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
7574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException
7584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
7594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
7604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
7624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (InvalidAlgorithmParameterException e)
7644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException(e.getMessage());
7664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
7674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
7684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    protected void engineUpdateAAD(byte[] input, int offset, int length)
7705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
7715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        cipher.updateAAD(input, offset, length);
7725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
7735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    protected void engineUpdateAAD(ByteBuffer bytebuffer)
7755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    {
7765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        int offset = bytebuffer.arrayOffset() + bytebuffer.position();
7775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        int length = bytebuffer.limit() - bytebuffer.position();
7785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        engineUpdateAAD(bytebuffer.array(), offset, length);
7795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    }
7805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
7814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineUpdate(
7824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
7834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
7844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
7854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
7864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     length = cipher.getUpdateOutputSize(inputLen);
7874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (length > 0)
7894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
7904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[]  out = new byte[length];
7914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int len = cipher.processBytes(input, inputOffset, inputLen, out, 0);
7934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
7944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (len == 0)
7954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
7964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return null;
7974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
7984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (len != out.length)
7994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
8004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    byte[]  tmp = new byte[len];
8014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    System.arraycopy(out, 0, tmp, 0, len);
8034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return tmp;
8054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
8064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return out;
8084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.processBytes(input, inputOffset, inputLen, null, 0);
8114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return null;
8134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineUpdate(
8164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
8174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
8184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
8194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
8204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     outputOffset)
8214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws ShortBufferException
8224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
8234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
8244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
8264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
8284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new ShortBufferException(e.getMessage());
8304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineDoFinal(
8344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
8354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
8364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
8374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IllegalBlockSizeException, BadPaddingException
8384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
8394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     len = 0;
8404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  tmp = new byte[engineGetOutputSize(inputLen)];
8414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (inputLen != 0)
8434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0);
8454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
8484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            len += cipher.doFinal(tmp, len);
8504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
8524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalBlockSizeException(e.getMessage());
8544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (len == tmp.length)
8574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return tmp;
8594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  out = new byte[len];
8624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        System.arraycopy(tmp, 0, out, 0, len);
8644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return out;
8664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineDoFinal(
8694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
8704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
8714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
8724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
873e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        int     outputOffset)
8744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
8754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
876e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        try
877e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        {
878e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            int     len = 0;
8794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
880e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            if (inputLen != 0)
881e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            {
882a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom                len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
883e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            }
8844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
885e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            return (len + cipher.doFinal(output, outputOffset + len));
8864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
887e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom        catch (OutputLengthException e)
8884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
889e1142c149e244797ce73b0e7fad40816e447a817Brian Carlstrom            throw new ShortBufferException(e.getMessage());
8904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
8924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
8934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalBlockSizeException(e.getMessage());
8944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
8954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
8964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
8974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private boolean isAEADModeName(
8984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String modeName)
8994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
900a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // BEGIN android-changed
901a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return "CCM".equals(modeName) || "GCM".equals(modeName);
902a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        // END android-changed
9034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
9044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /*
9064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * The ciphers that inherit from us.
9074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
9084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static private interface GenericBlockCipher
9104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
9114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
9124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException;
9134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding();
9154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName();
9174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher();
9194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len);
9214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len);
9234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        public void updateAAD(byte[] input, int offset, int length);
9255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
9264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff)
9274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws DataLengthException;
9284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
9304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws DataLengthException;
9314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int doFinal(byte[] out, int outOff)
933d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            throws IllegalStateException,
934d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            BadPaddingException;
9354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
9364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static class BufferedGenericBlockCipher
9384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        implements GenericBlockCipher
9394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
9404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        private BufferedBlockCipher cipher;
9414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(BufferedBlockCipher cipher)
9434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = cipher;
9454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher)
9484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = new PaddedBufferedBlockCipher(cipher);
9504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding)
9534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = new PaddedBufferedBlockCipher(cipher, padding);
9554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
9584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException
9594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(forEncryption, params);
9614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding()
9644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return !(cipher instanceof CTSBlockCipher);
9664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName()
9694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher().getAlgorithmName();
9714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
9744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher();
9764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len)
9794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getOutputSize(len);
9814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len)
9844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUpdateOutputSize(len);
9864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        public void updateAAD(byte[] input, int offset, int length)
9895db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
9905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            throw new UnsupportedOperationException("AAD is not supported in the current mode.");
9915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
9925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
9934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
9944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
9954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processByte(in, out, outOff);
9964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
9974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
9984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
9994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(in, inOff, len, out, outOff);
10014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1003d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
10044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1005d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            try
1006d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1007d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return cipher.doFinal(out, outOff);
1008d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1009d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            catch (InvalidCipherTextException e)
1010d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1011d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                throw new BadPaddingException(e.getMessage());
1012d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
10134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
10154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static class AEADGenericBlockCipher
10174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        implements GenericBlockCipher
10184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1019d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        private static final Constructor aeadBadTagConstructor;
1020d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
1021d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        static {
1022d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException");
1023d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            if (aeadBadTagClass != null)
1024d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1025d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass);
1026d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1027d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            else
1028d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1029d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                aeadBadTagConstructor = null;
1030d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1031d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
1032d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
1033d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        private static Constructor findExceptionConstructor(Class clazz)
1034d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
1035d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            try
1036d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1037d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return clazz.getConstructor(new Class[]{String.class});
1038d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1039d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            catch (Exception e)
1040d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1041d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return null;
1042d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1043d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
1044d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
10454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        private AEADBlockCipher cipher;
10464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AEADGenericBlockCipher(AEADBlockCipher cipher)
10484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.cipher = cipher;
10504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public void init(boolean forEncryption, CipherParameters params)
10534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throws IllegalArgumentException
10544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(forEncryption, params);
10564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public String getAlgorithmName()
10594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher().getAlgorithmName();
10614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public boolean wrapOnNoPadding()
10644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return false;
10664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
10694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUnderlyingCipher();
10714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getOutputSize(int len)
10744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getOutputSize(len);
10764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int getUpdateOutputSize(int len)
10794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.getUpdateOutputSize(len);
10814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        public void updateAAD(byte[] input, int offset, int length)
10845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        {
10855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root            cipher.processAADBytes(input, offset, length);
10865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root        }
10875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root
10884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
10894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processByte(in, out, outOff);
10914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
10934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
10944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
10954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return cipher.processBytes(in, inOff, len, out, outOff);
10964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
10974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1098d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
10994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1100d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            try
1101d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1102d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return cipher.doFinal(out, outOff);
1103d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
1104d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            catch (InvalidCipherTextException e)
1105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
1106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                if (aeadBadTagConstructor != null)
1107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                {
1108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    BadPaddingException aeadBadTag = null;
1109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    try
1110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    {
1111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                        aeadBadTag = (BadPaddingException)aeadBadTagConstructor
1112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                                .newInstance(new Object[]{e.getMessage()});
1113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    }
1114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    catch (Exception i)
1115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    {
1116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                        // Shouldn't happen, but fall through to BadPaddingException
1117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    }
1118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    if (aeadBadTag != null)
1119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    {
1120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                        throw aeadBadTag;
1121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                    }
1122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                }
1123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                throw new BadPaddingException(e.getMessage());
1124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
11254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
11264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
11274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
1128