14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.symmetric.util;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.AlgorithmParameters;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidAlgorithmParameterException;
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.InvalidKeyException;
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.Key;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.SecureRandom;
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.spec.AlgorithmParameterSpec;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.Cipher;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.NoSuchPaddingException;
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.SecretKey;
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.ShortBufferException;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.IvParameterSpec;
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport javax.crypto.spec.PBEParameterSpec;
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// BEGIN android-removed
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC2ParameterSpec;
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// import javax.crypto.spec.RC5ParameterSpec;
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// END android-removed
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.BlockCipher;
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.CipherParameters;
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.DataLengthException;
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.StreamBlockCipher;
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.StreamCipher;
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.KeyParameter;
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithIV;
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider;
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class BaseStreamCipher
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends BaseWrapCipher
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    implements PBE
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    // specs we can handle.
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    //
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private Class[]                 availableSpecs =
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    {
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // BEGIN android-removed
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC2ParameterSpec.class,
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // RC5ParameterSpec.class,
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        // END android-removed
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        IvParameterSpec.class,
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                        PBEParameterSpec.class
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                                    };
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private StreamCipher       cipher;
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private ParametersWithIV   ivParam;
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private int                     ivLength = 0;
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private PBEParameterSpec        pbeSpec = null;
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private String                  pbeAlgorithm = null;
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseStreamCipher(
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        StreamCipher engine,
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher = engine;
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength;
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseStreamCipher(
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BlockCipher engine,
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivLength)
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.ivLength = ivLength;
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher = new StreamBlockCipher(engine);
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetBlockSize()
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return 0;
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineGetIV()
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return (ivParam != null) ? ivParam.getIV() : null;
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetKeySize(
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key     key)
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return key.getEncoded().length * 8;
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineGetOutputSize(
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return inputLen;
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected AlgorithmParameters engineGetParameters()
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (engineParams == null)
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (pbeSpec != null)
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    AlgorithmParameters engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    engineParams.init(pbeSpec);
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return engineParams;
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return null;
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return engineParams;
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /**
1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * should never be called.
1194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetMode(
1214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  mode)
1224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!mode.equalsIgnoreCase("ECB"))
1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalArgumentException("can't support mode " + mode);
1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /**
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * should never be called.
1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineSetPadding(
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String  padding)
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws NoSuchPaddingException
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!padding.equalsIgnoreCase("NoPadding"))
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new NoSuchPaddingException("Padding " + padding + " unknown.");
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
1434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                     opmode,
1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                     key,
1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  params,
1464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom            random)
1474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException, InvalidAlgorithmParameterException
1484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        CipherParameters        param;
1504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeSpec = null;
1524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.pbeAlgorithm = null;
1534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.engineParams = null;
1554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
1574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        // basic key check
1584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        //
1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!(key instanceof SecretKey))
1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
1624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (key instanceof BCPBEKey)
1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            BCPBEKey k = (BCPBEKey)key;
1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getOID() != null)
1694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getOID().getId();
1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeAlgorithm = k.getAlgorithm();
1754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getParam() != null)
1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = k.getParam();
1804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount());
1814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else if (params instanceof PBEParameterSpec)
1834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = PBE.Util.makePBEParameters(k, params, cipher.getAlgorithmName());
1854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                pbeSpec = (PBEParameterSpec)params;
1864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
1884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
1904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (k.getIvSize() != 0)
1934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
1954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params == null)
1984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new KeyParameter(key.getEncoded());
2004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (params instanceof IvParameterSpec)
2024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV());
2044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ivParam = (ParametersWithIV)param;
2054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
2074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalArgumentException("unknown parameter type.");
2094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if ((ivLength != 0) && !(param instanceof ParametersWithIV))
2124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            SecureRandom    ivRandom = random;
2144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (ivRandom == null)
2164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom = new SecureRandom();
2184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
2214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[]  iv = new byte[ivLength];
2234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivRandom.nextBytes(iv);
2254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                param = new ParametersWithIV(param, iv);
2264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ivParam = (ParametersWithIV)param;
2274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
2294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("no IV set when one expected");
2314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        switch (opmode)
2354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        case Cipher.ENCRYPT_MODE:
2374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        case Cipher.WRAP_MODE:
2384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(true, param);
2394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            break;
2404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        case Cipher.DECRYPT_MODE:
2414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        case Cipher.UNWRAP_MODE:
2424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.init(false, param);
2434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            break;
2444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        default:
2454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            System.out.println("eeek!");
2464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
2504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
2514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
2524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameters params,
2534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
2544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException, InvalidAlgorithmParameterException
2554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
2564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        AlgorithmParameterSpec  paramSpec = null;
2574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params != null)
2594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            for (int i = 0; i != availableSpecs.length; i++)
2614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                try
2634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
2644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    paramSpec = params.getParameterSpec(availableSpecs[i]);
2654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    break;
2664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                catch (Exception e)
2684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
2694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    continue;
2704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
2714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (paramSpec == null)
2744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
2754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
2764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
2774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineInit(opmode, key, paramSpec, random);
2804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        engineParams = params;
2814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected void engineInit(
2844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int                 opmode,
2854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Key                 key,
2864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SecureRandom        random)
2874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws InvalidKeyException
2884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
2894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
2904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
2924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (InvalidAlgorithmParameterException e)
2944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
2954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new InvalidKeyException(e.getMessage());
2964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
2974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
2984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
2994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineUpdate(
3004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
3014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
3024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
3034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  out = new byte[inputLen];
3054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.processBytes(input, inputOffset, inputLen, out, 0);
3074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return out;
3094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineUpdate(
3124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
3134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
3144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
3154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
3164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     outputOffset)
3174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws ShortBufferException
3184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
3204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
3224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return inputLen;
3244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (DataLengthException e)
3264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new ShortBufferException(e.getMessage());
3284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected byte[] engineDoFinal(
3324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
3334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
3344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen)
3354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (inputLen != 0)
3374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            byte[] out = engineUpdate(input, inputOffset, inputLen);
3394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.reset();
3414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return out;
3434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.reset();
3464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return new byte[0];
3484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected int engineDoFinal(
3514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  input,
3524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputOffset,
3534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     inputLen,
3544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        byte[]  output,
3554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int     outputOffset)
3564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
3574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (inputLen != 0)
3584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
3594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
3604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
3614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        cipher.reset();
3634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
3644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return inputLen;
3654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
3664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
367