116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.jcajce.provider.symmetric.util;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport java.lang.reflect.Constructor;
480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giroimport java.lang.reflect.Method;
580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giroimport java.nio.ByteBuffer;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.AlgorithmParameters;
716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.InvalidAlgorithmParameterException;
816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.InvalidKeyException;
916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.InvalidParameterException;
1016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.Key;
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.NoSuchAlgorithmException;
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.SecureRandom;
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.security.spec.AlgorithmParameterSpec;
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.BadPaddingException;
1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.Cipher;
1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.IllegalBlockSizeException;
1816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.NoSuchPaddingException;
1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.SecretKey;
2016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.ShortBufferException;
2179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giroimport javax.crypto.interfaces.PBEKey;
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.IvParameterSpec;
234936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// BEGIN Android-added: Various key-handling modifications
2464fe4be2b2c98b1231314c785da2c050eccfe99bSergio Giroimport javax.crypto.spec.PBEKeySpec;
254936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// END Android-added: Various key-handling modifications
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport javax.crypto.spec.PBEParameterSpec;
274936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
28c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import javax.crypto.spec.RC2ParameterSpec;
29c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import javax.crypto.spec.RC5ParameterSpec;
3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giroimport org.bouncycastle.asn1.cms.GCMParameters;
3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.BlockCipher;
3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.BufferedBlockCipher;
3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.CipherParameters;
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.DataLengthException;
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.InvalidCipherTextException;
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.OutputLengthException;
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.AEADBlockCipher;
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.CBCBlockCipher;
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.CCMBlockCipher;
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.CFBBlockCipher;
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.CTSBlockCipher;
434936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
44c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.EAXBlockCipher;
45c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.GCFBBlockCipher;
4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.GCMBlockCipher;
474936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
48c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.GOFBBlockCipher;
49c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.OCBBlockCipher;
5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.OFBBlockCipher;
514936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
52c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
53c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.modes.SICBlockCipher;
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.BlockCipherPadding;
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.ISO10126d2Padding;
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.ISO7816d4Padding;
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.TBCPadding;
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.X923Padding;
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.paddings.ZeroBytePadding;
6280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giroimport org.bouncycastle.crypto.params.AEADParameters;
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.KeyParameter;
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.ParametersWithIV;
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.ParametersWithRandom;
664936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
67c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.params.ParametersWithSBox;
6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.RC2Parameters;
694936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
70c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.crypto.params.RC5Parameters;
7179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro// import org.bouncycastle.jcajce.PBKDF1Key;
7279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro// import org.bouncycastle.jcajce.PBKDF1KeyWithParameters;
7379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giroimport org.bouncycastle.jcajce.PKCS12Key;
7479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giroimport org.bouncycastle.jcajce.PKCS12KeyWithParameters;
754caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giroimport org.bouncycastle.jcajce.spec.AEADParameterSpec;
764936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian// Android-removed: Unsupported algorithms
77c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
78c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
7916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.util.Strings;
8016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
8116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class BaseBlockCipher
8216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    extends BaseWrapCipher
8316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    implements PBE
8416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
8580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
8680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
8716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    //
8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    // specs we can handle.
8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    //
9016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private Class[]                 availableSpecs =
9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                    {
924936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                                        // Android-removed: Unsupported algorithms
93c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                                        // RC2ParameterSpec.class,
94c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro                                        // RC5ParameterSpec.class,
9579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                                        gcmSpecClass,
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                        IvParameterSpec.class,
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                        PBEParameterSpec.class,
984936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                                        // Android-removed: Unsupported algorithms
9979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                                        // GOST28147ParameterSpec.class
10016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                    };
10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private BlockCipher             baseEngine;
10316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private BlockCipherProvider     engineProvider;
10416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private GenericBlockCipher      cipher;
10516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private ParametersWithIV        ivParam;
10680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    private AEADParameters          aeadParams;
10716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private int keySizeInBits;
10979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private int scheme = -1;
11079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private int digest;
11179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int                     ivLength = 0;
11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private boolean                 padded;
11579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private boolean                 fixedIv = true;
11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private PBEParameterSpec        pbeSpec = null;
11716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private String                  pbeAlgorithm = null;
11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private String                  modeName = null;
12016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
12180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    private static Class lookup(String className)
12280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    {
12380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        try
12480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        {
12580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            Class def = BaseBlockCipher.class.getClassLoader().loadClass(className);
12680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
12780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            return def;
12880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        }
12980261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        catch (Exception e)
13080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        {
13180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            return null;
13280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        }
13380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    }
13480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
13516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected BaseBlockCipher(
13616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BlockCipher engine)
13716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
13816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        baseEngine = engine;
13916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
14016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        cipher = new BufferedGenericBlockCipher(engine);
14116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
14216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
14316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected BaseBlockCipher(
14479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        BlockCipher engine,
14579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int scheme,
14679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int digest,
14779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int keySizeInBits,
14879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int ivLength)
14979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
15079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        baseEngine = engine;
15179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
15279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.scheme = scheme;
15379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.digest = digest;
15479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.keySizeInBits = keySizeInBits;
15579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.ivLength = ivLength;
15679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
15779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        cipher = new BufferedGenericBlockCipher(engine);
15879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
15979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
16079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    protected BaseBlockCipher(
16116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BlockCipherProvider provider)
16216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
16316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        baseEngine = provider.get();
16416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        engineProvider = provider;
16516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
16616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        cipher = new BufferedGenericBlockCipher(provider.get());
16716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
16816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
16916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected BaseBlockCipher(
17080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        AEADBlockCipher engine)
17180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    {
1724caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        this.baseEngine = engine.getUnderlyingCipher();
1734caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        this.ivLength = baseEngine.getBlockSize();
1744caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        this.cipher = new AEADGenericBlockCipher(engine);
17580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    }
17680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
17780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    protected BaseBlockCipher(
17879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        AEADBlockCipher engine,
17979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        boolean fixedIv,
18079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int ivLength)
18179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
18279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.baseEngine = engine.getUnderlyingCipher();
18379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.fixedIv = fixedIv;
18479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.ivLength = ivLength;
18579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this.cipher = new AEADGenericBlockCipher(engine);
18679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
18779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
18879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    protected BaseBlockCipher(
18916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        org.bouncycastle.crypto.BlockCipher engine,
19016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int ivLength)
19116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
19216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        baseEngine = engine;
19316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
19416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.cipher = new BufferedGenericBlockCipher(engine);
19516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.ivLength = ivLength / 8;
19616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
19716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
19816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected BaseBlockCipher(
19916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BufferedBlockCipher engine,
20016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int ivLength)
20116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
20216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        baseEngine = engine.getUnderlyingCipher();
20316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
20416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.cipher = new BufferedGenericBlockCipher(engine);
20516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.ivLength = ivLength / 8;
20616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
20716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
20816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected int engineGetBlockSize()
20916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
21016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return baseEngine.getBlockSize();
21116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
21216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
21316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected byte[] engineGetIV()
21416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
21553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (aeadParams != null)
21653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
21753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            return aeadParams.getNonce();
21853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
21953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
22016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return (ivParam != null) ? ivParam.getIV() : null;
22116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
22216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
22316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected int engineGetKeySize(
22416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Key     key)
22516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
22616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return key.getEncoded().length * 8;
22716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
22816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
22916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected int engineGetOutputSize(
23016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputLen)
23116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
23216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return cipher.getOutputSize(inputLen);
23316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
23416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
23516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected AlgorithmParameters engineGetParameters()
23616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
23716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (engineParams == null)
23816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
23916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (pbeSpec != null)
24016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
24116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                try
24216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
24353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    engineParams = createParametersInstance(pbeAlgorithm);
24416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    engineParams.init(pbeSpec);
24516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
24616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                catch (Exception e)
24716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
24816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    return null;
24916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
25016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
2514caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            else if (aeadParams != null)
2524caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            {
2534caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                try
2544caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                {
2554caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    engineParams = createParametersInstance("GCM");
2564caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded());
2574caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                }
2584caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                catch (Exception e)
2594caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                {
2604caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    throw new RuntimeException(e.toString());
2614caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                }
2624caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            }
26316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (ivParam != null)
26416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
26516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                String  name = cipher.getUnderlyingCipher().getAlgorithmName();
26616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
26716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                if (name.indexOf('/') >= 0)
26816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
26916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    name = name.substring(0, name.indexOf('/'));
27016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
27116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
27216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                try
27316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
27453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    engineParams = createParametersInstance(name);
2756b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    // Android-changed: Use IvParameterSpec instead of passing raw bytes.
2766b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    // The documentation of init() says that a byte array should be decoded
2776b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    // as ASN.1, and Conscrypt's implementations follow that requirement,
2786b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    // even though Bouncy Castle's implementations don't.  Wrapping it in
2796b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    // an IvParameterSpec makes the interpretation unambiguous to both.
2806b5b8b2f1e184da74aa4b2d083cb3f6a3c227844Adam Vartanian                    engineParams.init(new IvParameterSpec(ivParam.getIV()));
28116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
28216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                catch (Exception e)
28316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
28416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    throw new RuntimeException(e.toString());
28516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
28616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
28716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
28816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
28916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return engineParams;
29016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
29116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void engineSetMode(
29316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        String  mode)
29416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws NoSuchAlgorithmException
29516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
29616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        modeName = Strings.toUpperCase(mode);
29716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (modeName.equals("ECB"))
29916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
30016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = 0;
30116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new BufferedGenericBlockCipher(baseEngine);
30216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
30316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.equals("CBC"))
30416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
30516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
30616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new BufferedGenericBlockCipher(
30716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                            new CBCBlockCipher(baseEngine));
30816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
30916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("OFB"))
31016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
31116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
31216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (modeName.length() != 3)
31316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
31416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                int wordSize = Integer.parseInt(modeName.substring(3));
31516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
31616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(
31716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                new OFBBlockCipher(baseEngine, wordSize));
31816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
31916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
32016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
32116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(
32216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
32316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
32416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
32516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("CFB"))
32616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
32716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
32816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (modeName.length() != 3)
32916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
33016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                int wordSize = Integer.parseInt(modeName.substring(3));
33116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
33216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(
33316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                                new CFBBlockCipher(baseEngine, wordSize));
33416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
33516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
33616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
33716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(
33816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
33916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
34016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
3414936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unsupported modes
3424936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        /*
3434936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("PGP"))
3444936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
3454936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV");
3464936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
3474936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = baseEngine.getBlockSize();
3484936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new BufferedGenericBlockCipher(
3494936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                new PGPCFBBlockCipher(baseEngine, inlineIV));
3504936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
3514936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.equalsIgnoreCase("OpenPGPCFB"))
3524936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
3534936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = 0;
3544936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new BufferedGenericBlockCipher(
3554936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                new OpenPGPCFBBlockCipher(baseEngine));
3564936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
3574936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("SIC"))
3584936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
3594936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = baseEngine.getBlockSize();
3604936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (ivLength < 16)
3614936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
3624936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                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)");
3634936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
3644936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            fixedIv = false;
3654936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3664936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                        new SICBlockCipher(baseEngine)));
3674936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
3684936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        */
3694936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unsupported modes
37016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("CTR"))
37116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
37216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
37379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            fixedIv = false;
37416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
37516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                        new SICBlockCipher(baseEngine)));
37616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
3774936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unsupported modes
3784936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        /*
3794936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("GOFB"))
3804936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
3814936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = baseEngine.getBlockSize();
3824936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3834936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                        new GOFBBlockCipher(baseEngine)));
3844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
3854936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("GCFB"))
3864936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
3874936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = baseEngine.getBlockSize();
3884936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
3894936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                        new GCFBBlockCipher(baseEngine)));
3904936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
3914936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        */
3924936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unsupported modes
39316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("CTS"))
39416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
39516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
39616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine)));
39716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
39816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("CCM"))
39916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
40080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            ivLength = 13; // CCM nonce 7..13 bytes
40116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
40216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
4034936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unsupported modes
4044936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        /*
4054936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("OCB"))
4064936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
4074936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (engineProvider != null)
4084936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
4094936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                /*
4104936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                 * RFC 7253 4.2. Nonce is a string of no more than 120 bits
4114936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                 *
4124936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                ivLength = 15;
4134936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
4144936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
4154936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            else
4164936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
4174936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                throw new NoSuchAlgorithmException("can't support mode " + mode);
4184936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
4194936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
4204936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (modeName.startsWith("EAX"))
4214936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
4224936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            ivLength = baseEngine.getBlockSize();
4234936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine));
4244936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
4254936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        */
4264936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unsupported modes
42716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (modeName.startsWith("GCM"))
42816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
42916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ivLength = baseEngine.getBlockSize();
43016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
43116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
43216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else
43316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
43416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new NoSuchAlgorithmException("can't support mode " + mode);
43516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
43616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
43716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
43816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void engineSetPadding(
43916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        String  padding)
44016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    throws NoSuchPaddingException
44116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
44216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        String  paddingName = Strings.toUpperCase(padding);
44316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
44416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (paddingName.equals("NOPADDING"))
44516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
44616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (cipher.wrapOnNoPadding())
44716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
44816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher()));
44916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
45016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
45116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else if (paddingName.equals("WITHCTS"))
45216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
45316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher()));
45416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
45516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else
45616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
45716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            padded = true;
45816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
45916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (isAEADModeName(modeName))
46016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
46116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes.");
46216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
46316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING"))
46416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
46516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher());
46616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
46716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("ZEROBYTEPADDING"))
46816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
46916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding());
47016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
47116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING"))
47216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
47316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding());
47416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
47516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING"))
47616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
47716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding());
47816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
47916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING"))
48016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
48116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding());
48216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
48316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (paddingName.equals("TBCPADDING"))
48416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
48516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding());
48616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
48716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
48816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
48916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new NoSuchPaddingException("Padding " + padding + " unknown.");
49016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
49116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
49216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
49316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4944936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian    // BEGIN Android-added: Handling missing IVs
4956ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro    private boolean isBCPBEKeyWithoutIV(Key key) {
4966ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro        return (key instanceof BCPBEKey) && !(((BCPBEKey)key).getParam() instanceof ParametersWithIV);
4976ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro    }
4984936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian    // END Android-added: Handling missing IVs
4996ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro
50016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void engineInit(
50116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int                     opmode,
50216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Key                     key,
50316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AlgorithmParameterSpec  params,
50416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SecureRandom            random)
50516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws InvalidKeyException, InvalidAlgorithmParameterException
50616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
50716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        CipherParameters        param;
50816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
50916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.pbeSpec = null;
51016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.pbeAlgorithm = null;
51116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.engineParams = null;
51280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        this.aeadParams = null;
51316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
51416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
51516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // basic key check
51616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
51716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (!(key instanceof SecretKey))
51816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
5194caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            throw new InvalidKeyException("Key for algorithm " + ((key != null) ? key.getAlgorithm() : null) + " not suitable for symmetric enryption.");
52016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
52116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
52216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
52316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // for RC5-64 we must have some default parameters
52416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
52516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64"))
52616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
52716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in.");
52816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
52916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
53016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
53116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it).
53216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
5334936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-changed: Don't use PKCS12 with missing IV.
5346ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro        // If the key is a BCPBE one without an IV, ignore the fact that the scheme is PKCS12.
5354936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // if (scheme == PKCS12 || key instanceof PKCS12Key)
5366ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro        if ((scheme == PKCS12 || key instanceof PKCS12Key) && !isBCPBEKeyWithoutIV(key))
5374936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-changed: Don't use PKCS12 with missing IV.
53879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
53979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            SecretKey k;
54079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            try
54179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
54279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                k = (SecretKey)key;
54379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
54479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            catch (Exception e)
54579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
54679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                throw new InvalidKeyException("PKCS12 requires a SecretKey/PBEKey");
54779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
54879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
54979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (params instanceof  PBEParameterSpec)
55079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
55179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                pbeSpec = (PBEParameterSpec)params;
55279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
55379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
55479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (k instanceof PBEKey && pbeSpec == null)
55579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
5564caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                PBEKey pbeKey = (PBEKey)k;
5574caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                if (pbeKey.getSalt() == null)
5584caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                {
5594caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    throw new InvalidAlgorithmParameterException("PBEKey requires parameters to specify salt");
56079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                }
5614caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                pbeSpec = new PBEParameterSpec(pbeKey.getSalt(), pbeKey.getIterationCount());
56279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
56379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
56479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (pbeSpec == null && !(k instanceof PBEKey))
56579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
56679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                throw new InvalidKeyException("Algorithm requires a PBE key");
56779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
5684caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
56979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (key instanceof BCPBEKey)
57079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
5714caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to reject it. If the
5724caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                // key has no parameters it means it's an old-school JCE PBE Key - we use getEncoded() on it.
5734caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                CipherParameters pbeKeyParam = ((BCPBEKey)key).getParam();
5744caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                if (pbeKeyParam instanceof ParametersWithIV)
57579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                {
5764caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    param = pbeKeyParam;
57779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                }
5784caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                else if (pbeKeyParam == null)
57979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                {
5804936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    // BEGIN Android-changed: Unreachable code
581d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    // See above for the Android change that makes this code unreachable.
5824936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    // param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName());
5834936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    throw new AssertionError("Unreachable code");
5844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    // END Android-changed: Unreachable code
58579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                }
5864caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                else
5874caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                {
5884caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                    throw new InvalidKeyException("Algorithm requires a PBE key suitable for PKCS12");
5894caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                }
59079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
59179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            else
59279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
59379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName());
59479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
59579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (param instanceof ParametersWithIV)
59679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
59779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                ivParam = (ParametersWithIV)param;
59879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
59979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
6004936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unsupported algorithms
6014936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        /*
6024936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (key instanceof PBKDF1Key)
6034936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
6044936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            PBKDF1Key k = (PBKDF1Key)key;
6054936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
6064936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (params instanceof PBEParameterSpec)
6074936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
6084936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                pbeSpec = (PBEParameterSpec)params;
6094936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
6104936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (k instanceof PBKDF1KeyWithParameters && pbeSpec == null)
6114936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
6124936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                pbeSpec = new PBEParameterSpec(((PBKDF1KeyWithParameters)k).getSalt(), ((PBKDF1KeyWithParameters)k).getIterationCount());
6134936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
6144936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
6154936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS5S1, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName());
6164936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (param instanceof ParametersWithIV)
6174936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
6184936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                ivParam = (ParametersWithIV)param;
6194936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
6204936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
6214936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        */
6224936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unsupported algorithms
62379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else if (key instanceof BCPBEKey)
62416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
62516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            BCPBEKey k = (BCPBEKey)key;
62616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
62716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (k.getOID() != null)
62816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
62916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                pbeAlgorithm = k.getOID().getId();
63016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
63116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
63216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
63316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                pbeAlgorithm = k.getAlgorithm();
63416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
63516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
63616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (k.getParam() != null)
63716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
63879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                param = adjustParameters(params, k.getParam());
63916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
64016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (params instanceof PBEParameterSpec)
64116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
64216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                pbeSpec = (PBEParameterSpec)params;
6434936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // BEGIN Android-added: Allow PBE keys with only passwords.
64465832e311cb5fda062d79599b149232b47294feaAdam Vartanian                // At this point, k.getParam() == null, so the key hasn't been generated.  If
64565832e311cb5fda062d79599b149232b47294feaAdam Vartanian                // the parameters have non-default values, recreate the BCPBEKey from algorithm
64665832e311cb5fda062d79599b149232b47294feaAdam Vartanian                // parameters as to generate the key.
64765832e311cb5fda062d79599b149232b47294feaAdam Vartanian                if ((pbeSpec.getSalt().length != 0) && (pbeSpec.getIterationCount() > 0)) {
64865832e311cb5fda062d79599b149232b47294feaAdam Vartanian                    k = new BCPBEKey(k.getAlgorithm(), k.getOID(), k.getType(), k.getDigest(),
64965832e311cb5fda062d79599b149232b47294feaAdam Vartanian                            k.getKeySize(), k.getIvSize(),
65065832e311cb5fda062d79599b149232b47294feaAdam Vartanian                            new PBEKeySpec(
65165832e311cb5fda062d79599b149232b47294feaAdam Vartanian                                    k.getPassword(), pbeSpec.getSalt(), pbeSpec.getIterationCount(),
65265832e311cb5fda062d79599b149232b47294feaAdam Vartanian                                    k.getKeySize()),
65365832e311cb5fda062d79599b149232b47294feaAdam Vartanian                            null /* CipherParameters */);
65465832e311cb5fda062d79599b149232b47294feaAdam Vartanian                }
6554936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // END Android-added: Allow PBE keys with only passwords.
65616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName());
65716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
65816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
65916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
66016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
66116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
66216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
66316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (param instanceof ParametersWithIV)
66416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
66516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                ivParam = (ParametersWithIV)param;
66616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
66716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
66879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else if (key instanceof PBEKey)
66916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
67079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            PBEKey k = (PBEKey)key;
67179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            pbeSpec = (PBEParameterSpec)params;
67279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (k instanceof PKCS12KeyWithParameters && pbeSpec == null)
67379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
67479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount());
67579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
67679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
67779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            param = PBE.Util.makePBEParameters(k.getEncoded(), scheme, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName());
67879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (param instanceof ParametersWithIV)
67979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
68079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                ivParam = (ParametersWithIV)param;
68179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
68279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
6834936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-changed: Unsupported algorithm
6844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // else if (!(key instanceof RepeatedSecretKeySpec))
68579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else
6864936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-changed: Unsupported algorithms
68779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
68879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (scheme == PKCS5S1 || scheme == PKCS5S1_UTF8 || scheme == PKCS5S2 || scheme == PKCS5S2_UTF8)
68979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
69079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                throw new InvalidKeyException("Algorithm requires a PBE key");
69179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
69216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            param = new KeyParameter(key.getEncoded());
69316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
6944936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unreachable
69579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        // else
69679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        // {
69779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        //    param = null;
69879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        // }
6994936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unreachable
70079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
7014caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        if (params instanceof AEADParameterSpec)
7024caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        {
7034caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
7044caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            {
7054caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                throw new InvalidAlgorithmParameterException("AEADParameterSpec can only be used with AEAD modes.");
7064caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            }
7074caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
7084caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            AEADParameterSpec aeadSpec = (AEADParameterSpec)params;
7094caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
7104caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            KeyParameter keyParam;
7114caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            if (param instanceof ParametersWithIV)
7124caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            {
7134caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                keyParam = (KeyParameter)((ParametersWithIV)param).getParameters();
7144caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            }
7154caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            else
7164caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            {
7174caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                keyParam = (KeyParameter)param;
7184caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            }
7194caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            param = aeadParams = new AEADParameters(keyParam, aeadSpec.getMacSizeInBits(), aeadSpec.getNonce(), aeadSpec.getAssociatedData());
7204caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        }
7214caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        else if (params instanceof IvParameterSpec)
72216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
72316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (ivLength != 0)
72416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
72516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                IvParameterSpec p = (IvParameterSpec)params;
72616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
72779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                if (p.getIV().length != ivLength && !(cipher instanceof AEADGenericBlockCipher) && fixedIv)
72816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
72916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
73016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
73116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
73279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                if (param instanceof ParametersWithIV)
73379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                {
73479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                    param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), p.getIV());
73579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                }
73679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                else
73716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
73879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                    param = new ParametersWithIV(param, p.getIV());
73916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
74079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                ivParam = (ParametersWithIV)param;
74116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
74216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else
74316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
74416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                if (modeName != null && modeName.equals("ECB"))
74516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
74616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    throw new InvalidAlgorithmParameterException("ECB mode does not use an IV");
74716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
74816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
74916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
7504936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // BEGIN Android-removed: Unsupported algorithms
7514936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        /*
7524936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (params instanceof GOST28147ParameterSpec)
7534936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
7544936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            GOST28147ParameterSpec    gost28147Param = (GOST28147ParameterSpec)params;
7554936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
7564936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            param = new ParametersWithSBox(
7574936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                       new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox());
7584936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
7594936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (gost28147Param.getIV() != null && ivLength != 0)
7604936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
7614936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (param instanceof ParametersWithIV)
7624936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
7634936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), gost28147Param.getIV());
7644936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
7654936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                else
7664936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
7674936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(param, gost28147Param.getIV());
7684936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
7694936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                ivParam = (ParametersWithIV)param;
7704936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
7714936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
7724936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (params instanceof RC2ParameterSpec)
7734936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
7744936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            RC2ParameterSpec    rc2Param = (RC2ParameterSpec)params;
7754936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
7764936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits());
7774936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
7784936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (rc2Param.getIV() != null && ivLength != 0)
7794936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
7804936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (param instanceof ParametersWithIV)
7814936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
7824936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc2Param.getIV());
7834936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
7844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                else
7854936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
7864936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(param, rc2Param.getIV());
7874936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
7884936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                ivParam = (ParametersWithIV)param;
7894936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
7904936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
7914936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        else if (params instanceof RC5ParameterSpec)
7924936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        {
7934936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            RC5ParameterSpec    rc5Param = (RC5ParameterSpec)params;
7944936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
7954936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds());
7964936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if (baseEngine.getAlgorithmName().startsWith("RC5"))
7974936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
7984936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (baseEngine.getAlgorithmName().equals("RC5-32"))
7994936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
8004936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    if (rc5Param.getWordSize() != 32)
8014936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    {
8024936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                        throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + ".");
8034936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    }
8044936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
8054936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                else if (baseEngine.getAlgorithmName().equals("RC5-64"))
8064936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
8074936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    if (rc5Param.getWordSize() != 64)
8084936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    {
8094936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                        throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + ".");
8104936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    }
8114936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
8124936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
8134936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            else
8144936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
8154936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5.");
8164936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
8174936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            if ((rc5Param.getIV() != null) && (ivLength != 0))
8184936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
8194936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (param instanceof ParametersWithIV)
8204936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
8214936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc5Param.getIV());
8224936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
8234936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                else
8244936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
8254936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(param, rc5Param.getIV());
8264936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
8274936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                ivParam = (ParametersWithIV)param;
8284936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
8294936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        }
8304936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        */
8314936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // END Android-removed: Unsupported algorithms
83280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        else if (gcmSpecClass != null && gcmSpecClass.isInstance(params))
83380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        {
83480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
83580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            {
83680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                throw new InvalidAlgorithmParameterException("GCMParameterSpec can only be used with AEAD modes.");
83780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            }
83880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
83980261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            try
84080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            {
84180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
84280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
84380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
84479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                KeyParameter keyParam;
84579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                if (param instanceof ParametersWithIV)
84680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                {
84779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                    keyParam = (KeyParameter)((ParametersWithIV)param).getParameters();
84880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                }
84979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                else
85079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                {
85179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                    keyParam = (KeyParameter)param;
85279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                }
85379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                param = aeadParams = new AEADParameters(keyParam, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
85480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            }
85580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            catch (Exception e)
85680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            {
85780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec.");
85880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            }
85980261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        }
86079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else if (params != null && !(params instanceof PBEParameterSpec))
86116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
86216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new InvalidAlgorithmParameterException("unknown parameter type.");
86316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
86416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
86580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        if ((ivLength != 0) && !(param instanceof ParametersWithIV) && !(param instanceof AEADParameters))
86616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
86716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            SecureRandom    ivRandom = random;
86816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
86916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (ivRandom == null)
87016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
87116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                ivRandom = new SecureRandom();
87216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
8734936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
87416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
87516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
87616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                byte[]  iv = new byte[ivLength];
87716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
878d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // BEGIN Android-changed: For PBE keys with no IV, log and use IV of 0
879d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // These keys were accepted in BC 1.52 (and treated as having an IV of 0) but
880d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // rejected outright in BC 1.54 (even if an IV was passed in params).  We
881d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // want the eventual state to be that an IV can be passed in params, but the key
882d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // is rejected otherwise.  For now, log that these will be rejected in a future
883d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // release.  See b/27995180 for historical details.
8844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // ivRandom.nextBytes(iv);
8856ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                if (!isBCPBEKeyWithoutIV(key)) {
8866ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                    ivRandom.nextBytes(iv);
887d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                } else {
888d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    // TODO(b/70275132): Change to rejecting these keys
889d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" ******** DEPRECATED FUNCTIONALITY ********");
890d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * You have initialized a cipher with a PBE key with no IV and");
891d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * have not provided an IV in the AlgorithmParameterSpec.  This");
892d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * configuration is deprecated.  The cipher will be initialized");
893d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * with an all-zero IV, but in a future release this call will");
894d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * throw an exception.");
895d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    new InvalidAlgorithmParameterException("No IV set when using PBE key")
896d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                            .printStackTrace(System.err);
8976ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                }
898d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // END Android-changed: For PBE keys with no IV, log and use IV of 0
89916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                param = new ParametersWithIV(param, iv);
90016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                ivParam = (ParametersWithIV)param;
90116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
90216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0)
90316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
904d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // BEGIN Android-changed: For PBE keys with no IV, log and use IV of 0
905d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // These keys were accepted in BC 1.52 (and treated as having an IV of 0) but
906d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // rejected outright in BC 1.54 (even if an IV was passed in params).  We
907d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // want the eventual state to be that an IV can be passed in params, but the key
908d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // is rejected otherwise.  For now, log that these will be rejected in a future
909d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // release.  See b/27995180 for historical details.
9104936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // throw new InvalidAlgorithmParameterException("no IV set when one expected");
9116ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                if (!isBCPBEKeyWithoutIV(key)) {
9126ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                    throw new InvalidAlgorithmParameterException("no IV set when one expected");
9136ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                } else {
914d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    // TODO(b/70275132): Change to rejecting these keys
915d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" ******** DEPRECATED FUNCTIONALITY ********");
916d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * You have initialized a cipher with a PBE key with no IV and");
917d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * have not provided an IV in the AlgorithmParameterSpec.  This");
918d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * configuration is deprecated.  The cipher will be initialized");
919d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * with an all-zero IV, but in a future release this call will");
920d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    System.err.println(" * throw an exception.");
921d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                    new InvalidAlgorithmParameterException("No IV set when using PBE key")
922d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                            .printStackTrace(System.err);
9236ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                    // Mimic behaviour in 1.52 by using an IV of 0's
9246ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                    param = new ParametersWithIV(param, new byte[ivLength]);
9256ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                    ivParam = (ParametersWithIV)param;
9266ba5cb51e71a3b359d6bc5815f3d378336a51cb6Sergio Giro                }
927d07596fb6810cd74cf719bf6467b7bc96d07e9f9Adam Vartanian                // END Android-changed: For PBE keys with no IV, log and use IV of 0
92816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
92916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
93016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
9314caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
9324caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
93316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (random != null && padded)
93416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
93516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            param = new ParametersWithRandom(param, random);
93616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
93716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
93816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        try
93916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
94016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            switch (opmode)
94116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
94216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            case Cipher.ENCRYPT_MODE:
94316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            case Cipher.WRAP_MODE:
94416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher.init(true, param);
94516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                break;
94616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            case Cipher.DECRYPT_MODE:
94716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            case Cipher.UNWRAP_MODE:
94816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                cipher.init(false, param);
94916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                break;
95016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            default:
95116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new InvalidParameterException("unknown opmode " + opmode + " passed");
95216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
9534caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
9544caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            if (cipher instanceof AEADGenericBlockCipher && aeadParams == null)
9554caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            {
9564caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                AEADBlockCipher aeadCipher = ((AEADGenericBlockCipher)cipher).cipher;
9574caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
9584caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro                aeadParams = new AEADParameters((KeyParameter)ivParam.getParameters(), aeadCipher.getMac().length * 8, ivParam.getIV());
9594caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            }
96016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
96179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        catch (final Exception e)
96216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
9634caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            throw new InvalidKeyOrParametersException(e.getMessage(), e);
96416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
96516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
96616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
96779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private CipherParameters adjustParameters(AlgorithmParameterSpec params, CipherParameters param)
96879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
96979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        CipherParameters key;
97079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
97179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        if (param instanceof ParametersWithIV)
97279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
97379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            key = ((ParametersWithIV)param).getParameters();
97479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (params instanceof IvParameterSpec)
97579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
97679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                IvParameterSpec iv = (IvParameterSpec)params;
97779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
97879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                ivParam = new ParametersWithIV(key, iv.getIV());
97979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                param = ivParam;
98079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
9814936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            // BEGIN Android-removed: Unsupported algorithms
9824936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            /*
9834936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            else if (params instanceof GOST28147ParameterSpec)
9844936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
9854936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // need to pick up IV and SBox.
9864936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
9874936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
9884936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                param = new ParametersWithSBox(param, gost28147Param.getSbox());
9894936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
9904936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (gost28147Param.getIV() != null && ivLength != 0)
9914936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
9924936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    ivParam = new ParametersWithIV(key, gost28147Param.getIV());
9934936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = ivParam;
9944936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
9954936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
9964936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            */
9974936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            // END Android-removed: Unsupported algorithms
99879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
99979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else
100079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
100179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            if (params instanceof IvParameterSpec)
100279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
100379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                IvParameterSpec iv = (IvParameterSpec)params;
100479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
100579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                ivParam = new ParametersWithIV(param, iv.getIV());
100679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                param = ivParam;
100779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
10084936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            // BEGIN Android-removed: Unsupported algorithms
10094936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            /*
10104936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            else if (params instanceof GOST28147ParameterSpec)
10114936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            {
10124936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                // need to pick up IV and SBox.
10134936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
10144936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
10154936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                param = new ParametersWithSBox(param, gost28147Param.getSbox());
10164936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian
10174936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                if (gost28147Param.getIV() != null && ivLength != 0)
10184936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                {
10194936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                    param = new ParametersWithIV(param, gost28147Param.getIV());
10204936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian                }
10214936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            }
10224936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            */
10234936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian            // END Android-removed: Unsupported algorithms
102479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
102579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        return param;
102679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
102779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
102816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void engineInit(
102916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int                 opmode,
103016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Key                 key,
103116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AlgorithmParameters params,
103216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SecureRandom        random)
103316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    throws InvalidKeyException, InvalidAlgorithmParameterException
103416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
103516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AlgorithmParameterSpec  paramSpec = null;
103616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
103716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (params != null)
103816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
103916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            for (int i = 0; i != availableSpecs.length; i++)
104016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
104180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                if (availableSpecs[i] == null)
104280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                {
104380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                    continue;
104480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro                }
104580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
104616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                try
104716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
104816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    paramSpec = params.getParameterSpec(availableSpecs[i]);
104916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    break;
105016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
105116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                catch (Exception e)
105216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
105316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    // try again if possible
105416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
105516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
105616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
105716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (paramSpec == null)
105816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
105916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
106016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
106116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
106216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
106316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        engineInit(opmode, key, paramSpec, random);
106416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
106516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        engineParams = params;
106616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
106716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
106816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void engineInit(
106916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int                 opmode,
107016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Key                 key,
107116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SecureRandom        random)
107216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws InvalidKeyException
107316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
107416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        try
107516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
107616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
107716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
107816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        catch (InvalidAlgorithmParameterException e)
107916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
108016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new InvalidKeyException(e.getMessage());
108116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
108216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
108316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
108480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    protected void engineUpdateAAD(byte[] input, int offset, int length)
108580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    {
108680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        cipher.updateAAD(input, offset, length);
108780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    }
108880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
108980261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    protected void engineUpdateAAD(ByteBuffer bytebuffer)
109080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    {
109180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        int offset = bytebuffer.arrayOffset() + bytebuffer.position();
109280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        int length = bytebuffer.limit() - bytebuffer.position();
109380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        engineUpdateAAD(bytebuffer.array(), offset, length);
109480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro    }
109580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
109616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected byte[] engineUpdate(
109716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  input,
109816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputOffset,
109916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputLen)
110016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
110116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     length = cipher.getUpdateOutputSize(inputLen);
110216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
110316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (length > 0)
110416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
110516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                byte[]  out = new byte[length];
110616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
110716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                int len = cipher.processBytes(input, inputOffset, inputLen, out, 0);
110816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
110916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                if (len == 0)
111016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
111116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    return null;
111216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
111316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                else if (len != out.length)
111416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                {
111516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    byte[]  tmp = new byte[len];
111616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
111716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    System.arraycopy(out, 0, tmp, 0, len);
111816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
111916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                    return tmp;
112016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                }
112116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
112216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                return out;
112316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
112416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
112516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        cipher.processBytes(input, inputOffset, inputLen, null, 0);
112616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
112716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return null;
112816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
112916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
113016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected int engineUpdate(
113116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  input,
113216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputOffset,
113316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputLen,
113416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  output,
113516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     outputOffset)
113616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws ShortBufferException
113716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
113879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        if (outputOffset + cipher.getUpdateOutputSize(inputLen) > output.length)
113979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
114079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            throw new ShortBufferException("output buffer too short for input.");
114179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
114279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
114316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        try
114416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
114516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
114616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
114716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        catch (DataLengthException e)
114816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
114979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            // should never occur
115079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            throw new IllegalStateException(e.toString());
115116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
115216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
115316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
115416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected byte[] engineDoFinal(
115516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  input,
115616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputOffset,
115716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputLen)
115816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IllegalBlockSizeException, BadPaddingException
115916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
116016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     len = 0;
116116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  tmp = new byte[engineGetOutputSize(inputLen)];
116216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
116316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (inputLen != 0)
116416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
116516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0);
116616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
116716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
116816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        try
116916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
117016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            len += cipher.doFinal(tmp, len);
117116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
117216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        catch (DataLengthException e)
117316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
117416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new IllegalBlockSizeException(e.getMessage());
117516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
117616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
117716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (len == tmp.length)
117816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
117916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return tmp;
118016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
118116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
118216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  out = new byte[len];
118316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
118416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        System.arraycopy(tmp, 0, out, 0, len);
118516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
118616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return out;
118716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
118816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
118916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected int engineDoFinal(
119016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  input,
119116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputOffset,
119216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inputLen,
119316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  output,
119416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     outputOffset)
119516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
119616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
119779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int     len = 0;
119879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
119979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        if (outputOffset + engineGetOutputSize(inputLen) > output.length)
120016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
120179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            throw new ShortBufferException("output buffer too short for input.");
120279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
120316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
120479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        try
120579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
120616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (inputLen != 0)
120716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
120816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
120916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
121016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
121116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return (len + cipher.doFinal(output, outputOffset + len));
121216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
121316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        catch (OutputLengthException e)
121416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
121579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            throw new IllegalBlockSizeException(e.getMessage());
121616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
121716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        catch (DataLengthException e)
121816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
121916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new IllegalBlockSizeException(e.getMessage());
122016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
122116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
122216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
122316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private boolean isAEADModeName(
122416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        String modeName)
122516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
12264936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // Android-changed: Unsupported modes
12274936950820c68699a4ace55a2a8e5f7f677a913dAdam Vartanian        // return "CCM".equals(modeName) || "EAX".equals(modeName) || "GCM".equals(modeName) || "OCB".equals(modeName);
1228c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro        return "CCM".equals(modeName) || "GCM".equals(modeName);
122916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
123016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
123116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /*
123216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * The ciphers that inherit from us.
123316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
123416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
123516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static private interface GenericBlockCipher
123616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
123716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public void init(boolean forEncryption, CipherParameters params)
123816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throws IllegalArgumentException;
123916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
124016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public boolean wrapOnNoPadding();
124116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
124216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public String getAlgorithmName();
124316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
124416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher();
124516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
124616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getOutputSize(int len);
124716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
124816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getUpdateOutputSize(int len);
124916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
125080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        public void updateAAD(byte[] input, int offset, int length);
125180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
125216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processByte(byte in, byte[] out, int outOff)
125316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throws DataLengthException;
125416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
125516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
125616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throws DataLengthException;
125716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
125816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int doFinal(byte[] out, int outOff)
125953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            throws IllegalStateException,
126053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            BadPaddingException;
126116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
126216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
126316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private static class BufferedGenericBlockCipher
126416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        implements GenericBlockCipher
126516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
126616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        private BufferedBlockCipher cipher;
126716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
126816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BufferedGenericBlockCipher(BufferedBlockCipher cipher)
126916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
127016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            this.cipher = cipher;
127116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
127216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
127316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher)
127416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
127516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            this.cipher = new PaddedBufferedBlockCipher(cipher);
127616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
127716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
127816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding)
127916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
128016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            this.cipher = new PaddedBufferedBlockCipher(cipher, padding);
128116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
128216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
128316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public void init(boolean forEncryption, CipherParameters params)
128416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throws IllegalArgumentException
128516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
128616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher.init(forEncryption, params);
128716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
128816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
128916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public boolean wrapOnNoPadding()
129016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
129116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return !(cipher instanceof CTSBlockCipher);
129216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
129316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
129416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public String getAlgorithmName()
129516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
129616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUnderlyingCipher().getAlgorithmName();
129716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
129816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
129916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
130016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
130116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUnderlyingCipher();
130216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
130316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
130416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getOutputSize(int len)
130516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
130616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getOutputSize(len);
130716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
130816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
130916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getUpdateOutputSize(int len)
131016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
131116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUpdateOutputSize(len);
131216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
131316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
131480261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        public void updateAAD(byte[] input, int offset, int length)
131580261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        {
131680261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            throw new UnsupportedOperationException("AAD is not supported in the current mode.");
131780261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        }
131880261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
131916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
132016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
132116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.processByte(in, out, outOff);
132216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
132316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
132416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
132516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
132616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.processBytes(in, inOff, len, out, outOff);
132716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
132816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
132953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
133016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
133153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            try
133253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
133353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                return cipher.doFinal(out, outOff);
133453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
133553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            catch (InvalidCipherTextException e)
133653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
133753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                throw new BadPaddingException(e.getMessage());
133853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
133916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
134016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
134116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
134216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private static class AEADGenericBlockCipher
134316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        implements GenericBlockCipher
134416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
134553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        private static final Constructor aeadBadTagConstructor;
134653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
134753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        static {
134853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException");
134953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            if (aeadBadTagClass != null)
135053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
135153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass);
135253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
135353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            else
135453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
135553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                aeadBadTagConstructor = null;
135653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
135753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
135853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
135953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        private static Constructor findExceptionConstructor(Class clazz)
136053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
136153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            try
136253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
136353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                return clazz.getConstructor(new Class[]{String.class});
136453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
136553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            catch (Exception e)
136653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
136753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                return null;
136853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
136953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
137053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
137116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        private AEADBlockCipher cipher;
137216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
137316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AEADGenericBlockCipher(AEADBlockCipher cipher)
137416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
137516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            this.cipher = cipher;
137616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
137716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
137816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public void init(boolean forEncryption, CipherParameters params)
137916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throws IllegalArgumentException
138016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
138116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            cipher.init(forEncryption, params);
138216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
138316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
138416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public String getAlgorithmName()
138516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
138616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUnderlyingCipher().getAlgorithmName();
138716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
138816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
138916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public boolean wrapOnNoPadding()
139016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
139116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return false;
139216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
139316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
139416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher()
139516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
139616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUnderlyingCipher();
139716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
139816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
139916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getOutputSize(int len)
140016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
140116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getOutputSize(len);
140216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
140316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
140416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int getUpdateOutputSize(int len)
140516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
140616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.getUpdateOutputSize(len);
140716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
140816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
140980261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        public void updateAAD(byte[] input, int offset, int length)
141080261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        {
141180261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro            cipher.processAADBytes(input, offset, length);
141280261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro        }
141380261dd2d1824bb3862e90e77a5412d56ad88b1fSergio Giro
141416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
141516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
141616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.processByte(in, out, outOff);
141716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
141816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
141916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
142016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
142116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            return cipher.processBytes(in, inOff, len, out, outOff);
142216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
142316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
142453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
142516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
142653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            try
142753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
142853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                return cipher.doFinal(out, outOff);
142953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
143053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            catch (InvalidCipherTextException e)
143153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
143253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                if (aeadBadTagConstructor != null)
143353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                {
143453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    BadPaddingException aeadBadTag = null;
143553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    try
143653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    {
143753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                        aeadBadTag = (BadPaddingException)aeadBadTagConstructor
143853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                                .newInstance(new Object[]{e.getMessage()});
143953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    }
144053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    catch (Exception i)
144153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    {
144253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                        // Shouldn't happen, but fall through to BadPaddingException
144353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    }
144453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    if (aeadBadTag != null)
144553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    {
144653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                        throw aeadBadTag;
144753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                    }
144853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                }
144953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                throw new BadPaddingException(e.getMessage());
145053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
145116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
145216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
14534caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
14544caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    private static class InvalidKeyOrParametersException
14554caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        extends InvalidKeyException
14564caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    {
14574caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        private final Throwable cause;
14584caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
14594caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        InvalidKeyOrParametersException(String msg, Throwable cause)
14604caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        {
14614caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro             super(msg);
14624caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            this.cause = cause;
14634caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        }
14644caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
14654caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        public Throwable getCause()
14664caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        {
14674caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            return cause;
14684caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        }
14694caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    }
147016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
1471