14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.symmetric.util;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.AlgorithmParameters;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.InvalidAlgorithmParameterException;
56e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.InvalidKeyException;
66e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.Key;
76e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.KeyFactory;
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.NoSuchAlgorithmException;
96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.NoSuchProviderException;
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.PrivateKey;
11028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giroimport java.security.Provider;
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.SecureRandom;
13028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giroimport java.security.Security;
146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.spec.AlgorithmParameterSpec;
156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.spec.InvalidKeySpecException;
166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.spec.PKCS8EncodedKeySpec;
176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport java.security.spec.X509EncodedKeySpec;
186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.BadPaddingException;
206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.Cipher;
216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.CipherSpi;
226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.IllegalBlockSizeException;
236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.NoSuchPaddingException;
246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.ShortBufferException;
256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.spec.IvParameterSpec;
266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.spec.PBEParameterSpec;
276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom// BEGIN android-removed
286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom// import javax.crypto.spec.RC2ParameterSpec;
296e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom// import javax.crypto.spec.RC5ParameterSpec;
306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom// END android-removed
316e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport javax.crypto.spec.SecretKeySpec;
326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters;
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.InvalidCipherTextException;
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.Wrapper;
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter;
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithIV;
39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.crypto.params.ParametersWithRandom;
40028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giroimport org.bouncycastle.jcajce.util.BCJcaJceHelper;
41028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giroimport org.bouncycastle.jcajce.util.JcaJceHelper;
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider;
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic abstract class BaseWrapCipher
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends CipherSpi
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements PBE
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // specs we can handle.
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private Class[]                 availableSpecs =
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    {
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        IvParameterSpec.class,
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                        PBEParameterSpec.class,
55c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // BEGIN android-removed
56c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // RC2ParameterSpec.class,
570d31ca0f54efe12f12049174bfa9403961654a92Brian Carlstrom                                        // RC5ParameterSpec.class
58c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                                        // END android-removed
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    };
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int                     pbeType = PKCS12;
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int                     pbeHash = SHA1;
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int                     pbeKeySize;
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int                     pbeIvSize;
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected AlgorithmParameters     engineParams = null;
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
68c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    protected Wrapper                 wrapEngine = null;
69c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
70c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private int                       ivSize;
71c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private byte[]                    iv;
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
73028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro    private final JcaJceHelper helper = new BCJcaJceHelper();
74028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseWrapCipher()
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseWrapCipher(
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Wrapper wrapEngine)
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
82c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this(wrapEngine, 0);
83c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    protected BaseWrapCipher(
86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        Wrapper wrapEngine,
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int ivSize)
88c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.wrapEngine = wrapEngine;
90c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        this.ivSize = ivSize;
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int engineGetBlockSize()
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return 0;
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] engineGetIV()
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
100c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return (byte[])iv.clone();
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int engineGetKeySize(
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key     key)
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return key.getEncoded().length;
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int engineGetOutputSize(
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputLen)
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return -1;
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected AlgorithmParameters engineGetParameters()
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
120028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro    protected final AlgorithmParameters createParametersInstance(String algorithm)
121028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro        throws NoSuchAlgorithmException, NoSuchProviderException
122028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro    {
123028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro        return helper.createAlgorithmParameters(algorithm);
124028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro    }
125028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void engineSetMode(
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  mode)
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws NoSuchAlgorithmException
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new NoSuchAlgorithmException("can't support mode " + mode);
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void engineSetPadding(
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  padding)
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    throws NoSuchPaddingException
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new NoSuchPaddingException("Padding " + padding + " unknown.");
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void engineInit(
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int                     opmode,
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key                     key,
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        AlgorithmParameterSpec  params,
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SecureRandom            random)
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    throws InvalidKeyException, InvalidAlgorithmParameterException
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CipherParameters        param;
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (key instanceof BCPBEKey)
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            BCPBEKey k = (BCPBEKey)key;
1524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (params instanceof PBEParameterSpec)
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                param = PBE.Util.makePBEParameters(k, params, wrapEngine.getAlgorithmName());
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else if (k.getParam() != null)
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                param = k.getParam();
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            param = new KeyParameter(key.getEncoded());
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (params instanceof IvParameterSpec)
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            IvParameterSpec iv = (IvParameterSpec) params;
174c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            param = new ParametersWithIV(param, iv.getIV());
175c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
176c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
177c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (param instanceof KeyParameter && ivSize != 0)
178c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            iv = new byte[ivSize];
180c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            random.nextBytes(iv);
181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            param = new ParametersWithIV(param, iv);
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
184d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (random != null)
185d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
186d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            param = new ParametersWithRandom(param, random);
187d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
188d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        switch (opmode)
190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        case Cipher.WRAP_MODE:
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            wrapEngine.init(true, param);
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            break;
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        case Cipher.UNWRAP_MODE:
195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            wrapEngine.init(false, param);
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            break;
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        case Cipher.ENCRYPT_MODE:
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        case Cipher.DECRYPT_MODE:
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("engine only valid for wrapping");
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        default:
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            System.out.println("eeek!");
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void engineInit(
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int                 opmode,
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key                 key,
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        AlgorithmParameters params,
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SecureRandom        random)
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    throws InvalidKeyException, InvalidAlgorithmParameterException
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        AlgorithmParameterSpec  paramSpec = null;
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (params != null)
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != availableSpecs.length; i++)
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                try
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    paramSpec = params.getParameterSpec(availableSpecs[i]);
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    break;
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                catch (Exception e)
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
225c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    // try next spec
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (paramSpec == null)
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        engineParams = params;
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        engineInit(opmode, key, paramSpec, random);
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void engineInit(
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int                 opmode,
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key                 key,
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SecureRandom        random)
243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws InvalidKeyException
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (InvalidAlgorithmParameterException e)
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException(e.getMessage());
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] engineUpdate(
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  input,
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputOffset,
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputLen)
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new RuntimeException("not supported for wrapping");
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int engineUpdate(
264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  input,
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputOffset,
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputLen,
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  output,
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     outputOffset)
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws ShortBufferException
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new RuntimeException("not supported for wrapping");
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] engineDoFinal(
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  input,
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputOffset,
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputLen)
278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IllegalBlockSizeException, BadPaddingException
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // BEGIN android-changed
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // added ShortBufferException to throws statement
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected int engineDoFinal(
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  input,
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputOffset,
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inputLen,
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  output,
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     outputOffset)
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return 0;
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // END android-changed
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected byte[] engineWrap(
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Key     key)
2994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    throws IllegalBlockSizeException, InvalidKeyException
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[] encoded = key.getEncoded();
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (encoded == null)
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new InvalidKeyException("Cannot wrap key, null encoding.");
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (wrapEngine == null)
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return engineDoFinal(encoded, 0, encoded.length);
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return wrapEngine.wrap(encoded, 0, encoded.length);
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (BadPaddingException e)
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalBlockSizeException(e.getMessage());
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected Key engineUnwrap(
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  wrappedKey,
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  wrappedKeyAlgorithm,
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     wrappedKeyType)
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    throws InvalidKeyException, NoSuchAlgorithmException
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
330c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        byte[] encoded;
331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (wrapEngine == null)
334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                encoded = wrapEngine.unwrap(wrappedKey, 0, wrappedKey.length);
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (InvalidCipherTextException e)
343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new InvalidKeyException(e.getMessage());
345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (BadPaddingException e)
347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new InvalidKeyException(e.getMessage());
349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (IllegalBlockSizeException e2)
351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new InvalidKeyException(e2.getMessage());
353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
355b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (wrappedKeyType == Cipher.SECRET_KEY)
356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY)
360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            /*
36270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom             * The caller doesn't know the algorithm as it is part of
36370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom             * the encrypted data.
36470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom             */
365b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
366b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
3674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                PrivateKeyInfo       in = PrivateKeyInfo.getInstance(encoded);
368b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in);
370b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (privKey != null)
372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
3734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return privKey;
374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
3754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else
376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
3774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported");
378b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
380b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (Exception e)
381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new InvalidKeyException("Invalid key encoding.");
383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
385b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            try
388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
389028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro                KeyFactory kf = helper.createKeyFactory(wrappedKeyAlgorithm);
390b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (wrappedKeyType == Cipher.PUBLIC_KEY)
392b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    return kf.generatePublic(new X509EncodedKeySpec(encoded));
394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
395b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else if (wrappedKeyType == Cipher.PRIVATE_KEY)
396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (NoSuchProviderException e)
401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new InvalidKeyException("Unknown key type " + e.getMessage());
403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            catch (InvalidKeySpecException e2)
405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new InvalidKeyException("Unknown key type " + e2.getMessage());
407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
408b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
409b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
414