1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage javax.crypto;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AlgorithmParameters;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.InvalidAlgorithmParameterException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.InvalidKeyException;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.InvalidParameterException;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Key;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.NoSuchAlgorithmException;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.NoSuchProviderException;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Provider;
2985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Rootimport java.security.Provider.Service;
3085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Rootimport java.security.ProviderException;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.SecureRandom;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.Security;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.Certificate;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.spec.AlgorithmParameterSpec;
3685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Rootimport java.util.ArrayList;
3785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Rootimport java.util.Locale;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.crypto.internal.NullCipherSpi;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.fortress.Engine;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class provides access to implementations of cryptographic ciphers for
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encryption and decryption. Cipher classes can not be instantiated directly,
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * one has to call the Cipher's {@code getInstance} method with the name of a
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * requested transformation, optionally with a provider. A transformation
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specifies an operation (or a set of operations) as a string in the form:
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul>
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li><i>"algorithm/mode/padding"</i></li> or
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li><i>"algorithm"</i></li>
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul>
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * name of a feedback mode and <i>padding</i> is the name of a padding scheme.
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * default values will be used.
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A valid transformation would be:
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul>
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");}
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul>
61e722ddfbbd83104acea33d93a390c7fb233db1bbXizhi Zhu (Steven) * When a block cipher is requested in stream cipher mode, the number of bits
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to be processed at a time can be optionally specified by appending it to the
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provider specific default value is used.
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class Cipher {
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant for decryption operation mode.
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int DECRYPT_MODE = 2;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant for encryption operation mode.
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int ENCRYPT_MODE = 1;
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant indicating that the key to be unwrapped is a private key.
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int PRIVATE_KEY = 2;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant indicating that the key to be unwrapped is a public key.
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int PUBLIC_KEY = 1;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant indicating that the key to be unwrapped is a secret key.
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int SECRET_KEY = 3;
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant for key unwrapping operation mode.
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int UNWRAP_MODE = 4;
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constant for key wrapping operation mode.
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int WRAP_MODE = 3;
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mode;
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /** Items that need to be set on the Cipher instance. */
10685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private enum NeedToSet {
10785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        NONE, MODE, PADDING, BOTH,
10885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    };
10985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
111484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Used to keep track of which underlying {@code CipherSpi#engineInit(...)}
112484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * variant to call when testing suitability.
113484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
114484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private static enum InitType {
115484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        KEY, ALGORITHM_PARAMS, ALGORITHM_PARAM_SPEC,
116484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    };
117484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
118484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
119484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Keeps track of the possible arguments to {@code Cipher#init(...)}.
120484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
121484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private static class InitParams {
122484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final InitType initType;
123484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final int opmode;
124484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final Key key;
125484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final SecureRandom random;
126484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final AlgorithmParameterSpec spec;
127484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final AlgorithmParameters params;
128484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
129484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private InitParams(InitType initType, int opmode, Key key, SecureRandom random,
130484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                AlgorithmParameterSpec spec, AlgorithmParameters params) {
131484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.initType = initType;
132484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.opmode = opmode;
133484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.key = key;
134484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.random = random;
135484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.spec = spec;
136484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.params = params;
137484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
138484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    }
139484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
140484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
141484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Expresses the various types of transforms that may be used during
142484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * initialization.
143484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
144484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private static class Transform {
145484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final String name;
146484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        private final NeedToSet needToSet;
147484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
148484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        public Transform(String name, NeedToSet needToSet) {
149484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.name = name;
150484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            this.needToSet = needToSet;
151484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
152484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    }
153484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
154484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The service name.
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
157f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private static final String SERVICE = "Cipher";
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Used to access common engine functionality.
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1620a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom    private static final Engine ENGINE = new Engine(SERVICE);
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
16485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /** The attribute used for supported paddings. */
16585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private static final String ATTRIBUTE_PADDINGS = "SupportedPaddings";
16685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
16785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /** The attribute used for supported modes. */
16885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private static final String ATTRIBUTE_MODES = "SupportedModes";
16985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The provider.
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Provider provider;
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
176beff0f1375b635c692d48190aa69a06986b5111fKenny Root     * The provider specified when instance created.
177beff0f1375b635c692d48190aa69a06986b5111fKenny Root     */
178beff0f1375b635c692d48190aa69a06986b5111fKenny Root    private final Provider specifiedProvider;
179beff0f1375b635c692d48190aa69a06986b5111fKenny Root
180beff0f1375b635c692d48190aa69a06986b5111fKenny Root    /**
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The SPI implementation.
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private CipherSpi spiImpl;
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
18616ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root     * The SPI implementation.
18716ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root     */
18816ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root    private final CipherSpi specifiedSpi;
18916ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root
19016ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root    /**
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The transformation.
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
19385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private final String transformation;
19485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
19585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
19685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * The transformation split into parts.
19785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
19885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private final String[] transformParts;
19985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
20085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
20185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * Lock held while the SPI is initializing.
20285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
20385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private final Object initLock = new Object();
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2059229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes    private static SecureRandom secureRandom;
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new Cipher instance.
209ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cipherSpi
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the implementation delegate of the cipher.
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param provider
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the provider of the implementation of this cipher.
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the transformation that this cipher performs.
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if either cipherSpi is {@code null} or provider is {@code
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             null} and {@code cipherSpi} is a {@code NullCipherSpi}.
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
22085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation) {
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (cipherSpi == null) {
22286acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("cipherSpi == null");
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!(cipherSpi instanceof NullCipherSpi) && provider == null) {
22586acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("provider == null");
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
227beff0f1375b635c692d48190aa69a06986b5111fKenny Root        this.specifiedProvider = provider;
22816ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root        this.specifiedSpi = cipherSpi;
22985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        this.transformation = transformation;
23085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        this.transformParts = null;
23185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
23285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
23385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private Cipher(String transformation, String[] transformParts, Provider provider) {
23485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        this.transformation = transformation;
23585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        this.transformParts = transformParts;
236beff0f1375b635c692d48190aa69a06986b5111fKenny Root        this.specifiedProvider = provider;
23716ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root        this.specifiedSpi = null;
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new Cipher for the specified transformation. The installed
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * providers are searched in order for an implementation of the specified
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformation. The first found provider providing the transformation is
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * used to create the cipher. If no provider is found an exception is
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * thrown.
247ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the transformation to create a cipher for.
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a cipher for the requested transformation.
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no installed provider can provide the
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             <i>transformation</i>, or it is {@code null}, empty or in an
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             invalid format.
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchPaddingException
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no installed provider can provide the padding scheme in
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             the <i>transformation</i>.
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final Cipher getInstance(String transformation)
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws NoSuchAlgorithmException, NoSuchPaddingException {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getCipher(transformation, null);
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new cipher for the specified transformation provided by the
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified provider.
267ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the transformation to create a cipher for.
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param provider
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the provider to ask for the transformation.
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a cipher for the requested transformation.
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified provider can not provide the
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             <i>transformation</i>, or it is {@code null}, empty or in an
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             invalid format.
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchProviderException
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no provider with the specified name can be found.
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchPaddingException
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the requested padding scheme in the <i>transformation</i>
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             is not available.
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified provider is {@code null}.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final Cipher getInstance(String transformation,
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String provider) throws NoSuchAlgorithmException,
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            NoSuchProviderException, NoSuchPaddingException {
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (provider == null) {
29080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("provider == null");
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Provider p = Security.getProvider(provider);
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (p == null) {
29580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new NoSuchProviderException("Provider not available: " + provider);
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getInstance(transformation, p);
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
3010a64887ae9127d081fc6e312ba1f06f727453800Kenny Root     * Creates a new cipher for the specified transformation. The
3020a64887ae9127d081fc6e312ba1f06f727453800Kenny Root     * {@code provider} supplied does not have to be registered.
303ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name of the transformation to create a cipher for.
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param provider
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the provider to ask for the transformation.
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a cipher for the requested transformation.
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified provider can not provide the
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             <i>transformation</i>, or it is {@code null}, empty or in an
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             invalid format.
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchPaddingException
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the requested padding scheme in the <i>transformation</i>
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             is not available.
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the provider is {@code null}.
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final Cipher getInstance(String transformation,
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Provider provider) throws NoSuchAlgorithmException,
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            NoSuchPaddingException {
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (provider == null) {
32380a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("provider == null");
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
32585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getCipher(transformation, provider);
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes    private static NoSuchAlgorithmException invalidTransformation(String transformation)
32980a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throws NoSuchAlgorithmException {
33080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        throw new NoSuchAlgorithmException("Invalid transformation: " + transformation);
33180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes    }
33280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
33485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * Create a Cipher instance but don't choose a CipherSpi until we have more
33585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * information.
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
33785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private static Cipher getCipher(String transformation, Provider provider)
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws NoSuchAlgorithmException, NoSuchPaddingException {
33980a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes        if (transformation == null || transformation.isEmpty()) {
34080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw invalidTransformation(transformation);
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        String[] transformParts = checkTransformation(transformation);
3442ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro
345484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        Engine.SpiAndProvider sap;
346484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        try {
347484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            sap = tryCombinations(null /* params */, provider, transformation, transformParts);
348484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
349484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // should never happen since we passed in null params
350484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new ProviderException(e);
351484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
352484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
353484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        if (sap == null) {
3546cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom            if (provider == null) {
35585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                throw new NoSuchAlgorithmException("No provider found for " + transformation);
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
35785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                throw new NoSuchAlgorithmException("Provider " + provider.getName()
35885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                        + " does not provide " + transformation);
3596cdb6b7e6939270ccd21790ec95e42197cefc0c3Brian Carlstrom            }
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
36185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return new Cipher(transformation, transformParts, provider);
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
364484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
365484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Checks that the provided algorithm {@code transformation} string is a
366484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * valid input. The algorithm is the only mandatory field and input can be
367484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * of the form:
368484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <ul>
369484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>"[cipher]"</code>
370484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>"[cipher]/[mode]/[padding]"</code>
371484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>"[cipher]//[padding]"</code>
372484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>"[cipher]/[mode]"</code>
373484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * </ul>
374484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <p>
375484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Returns the specified transformation split up into three parts
376484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * corresponding to their function:
377484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <p>
378484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <code>
379484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {&lt;algorithm&gt;, &lt;mode&gt;, &lt;padding&gt;}
380484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * </code>
381484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <p>
382484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
38385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private static String[] checkTransformation(String transformation)
38485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            throws NoSuchAlgorithmException {
385937b6c4ef5f8ad57279e2ebed4393a78d1729d8bBrian Carlstrom        // ignore an extra prefix / characters such as in
38685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        // "/DES/CBC/PKCS5Padding" http://b/3387688
387937b6c4ef5f8ad57279e2ebed4393a78d1729d8bBrian Carlstrom        if (transformation.startsWith("/")) {
388937b6c4ef5f8ad57279e2ebed4393a78d1729d8bBrian Carlstrom            transformation = transformation.substring(1);
389937b6c4ef5f8ad57279e2ebed4393a78d1729d8bBrian Carlstrom        }
390118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        // 'transformation' should be of the form "algorithm/mode/padding".
391118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        String[] pieces = transformation.split("/");
392118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        if (pieces.length > 3) {
393118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes            throw invalidTransformation(transformation);
394118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        }
395118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        // Empty or missing pieces are represented by null.
396118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        String[] result = new String[3];
397118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        for (int i = 0; i < pieces.length; ++i) {
398118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes            String piece = pieces[i].trim();
399118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes            if (!piece.isEmpty()) {
400118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes                result[i] = piece;
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
403118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        // You MUST specify an algorithm.
404118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        if (result[0] == null) {
40580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw invalidTransformation(transformation);
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
407118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) {
40880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw invalidTransformation(transformation);
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
410118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes        return result;
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
414484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Makes sure a CipherSpi that matches this type is selected. If
415484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code key != null} then it assumes that a suitable provider exists for
416484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * this instance (used by {@link #init}. If the {@code initParams} is passed
417484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * in, then the {@code CipherSpi} returned will be initialized.
41830bc3f8566f9b089ce02a7a22b51991d896f5524Sergio Giro     *
4192ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro     * @throws InvalidKeyException if the specified key cannot be used to
4202ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro     *             initialize this cipher.
421484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * @throws InvalidAlgorithmParameterException
42285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
423484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private CipherSpi getSpi(InitParams initParams) throws InvalidKeyException,
424484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            InvalidAlgorithmParameterException {
42516ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root        if (specifiedSpi != null) {
42616ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root            return specifiedSpi;
42716ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root        }
42816ec6489f8339c55fb65db423c4a997a9f91d089Kenny Root
42985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        synchronized (initLock) {
43030bc3f8566f9b089ce02a7a22b51991d896f5524Sergio Giro            // This is not only a matter of performance. Many methods like update, doFinal, etc.
431484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // call {@code #getSpi()} (ie, {@code #getSpi(null /* params */)}) and without this
43230bc3f8566f9b089ce02a7a22b51991d896f5524Sergio Giro            // shortcut they would override an spi that was chosen using the key.
433484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            if (spiImpl != null && initParams == null) {
43485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                return spiImpl;
43585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            }
43685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
437484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            final Engine.SpiAndProvider sap = tryCombinations(initParams, specifiedProvider,
438484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    transformation, transformParts);
43985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            if (sap == null) {
440484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                throw new ProviderException("No provider found for " + transformation);
44185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            }
44285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
44385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            spiImpl = (CipherSpi) sap.spi;
44485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            provider = sap.provider;
44585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
44685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            return spiImpl;
44785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
44885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
44985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
45085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
45185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * Convenience call when the Key is not available.
45285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
453834660d9ce0cdcedf256e4b90b7bd4b4d3832daaAlex Klyubin    private CipherSpi getSpi() {
4542ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro        try {
4552ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro            return getSpi(null);
456484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
457484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new ProviderException("Exception thrown when params == null", e);
4582ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro        }
45985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
46085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
46185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
4624ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin     * Returns the {@code CipherSpi} backing this {@code Cipher} or {@code null} if no
4634ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin     * {@code CipherSpi} is backing this {@code Cipher}.
4644ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin     *
4654ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin     * @hide
4664ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin     */
4674ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin    public CipherSpi getCurrentSpi() {
4684ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin        if (specifiedSpi != null) {
4694ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin            return specifiedSpi;
4704ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin        }
4714ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin
4724ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin        synchronized (initLock) {
4734ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin            return spiImpl;
4744ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin        }
4754ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin    }
4764ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin
4774ec153a9ae62f6f62694fd0a320db16c254174c9Alex Klyubin    /**
478484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Tries to find the correct {@code Cipher} transform to use. Returns a
479484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@link Engine.SpiAndProvider}, throws the first exception that was
480484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * encountered during attempted initialization, or {@code null} if there are
481484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * no providers that support the {@code initParams}.
482484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <p>
483484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code transformParts} must be in the format returned by
484484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@link #checkTransformation(String)}. The combinations of mode strings
485484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * tried are as follows:
486484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <ul>
487484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>[cipher]/[mode]/[padding]</code>
488484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>[cipher]/[mode]</code>
489484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>[cipher]//[padding]</code>
490484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * <li><code>[cipher]</code>
491484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * </ul>
49285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
493484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private static Engine.SpiAndProvider tryCombinations(InitParams initParams, Provider provider,
494484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            String transformation, String[] transformParts) throws InvalidKeyException,
495484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            InvalidAlgorithmParameterException {
496484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        // Enumerate all the transforms we need to try
497484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        ArrayList<Transform> transforms = new ArrayList<Transform>();
49885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (transformParts[1] != null && transformParts[2] != null) {
499484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            transforms.add(new Transform(transformParts[0] + "/" + transformParts[1] + "/"
500484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    + transformParts[2], NeedToSet.NONE));
50185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
50285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (transformParts[1] != null) {
503484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            transforms.add(new Transform(transformParts[0] + "/" + transformParts[1],
504484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    NeedToSet.PADDING));
50585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
50685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (transformParts[2] != null) {
507484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            transforms.add(new Transform(transformParts[0] + "//" + transformParts[2],
508484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    NeedToSet.MODE));
50985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
510484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        transforms.add(new Transform(transformParts[0], NeedToSet.BOTH));
511484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
512484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        // Try each of the transforms and keep track of the first exception
513484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        // encountered.
514484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        Exception cause = null;
515484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        for (Transform transform : transforms) {
516484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            if (provider != null) {
517484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                Provider.Service service = provider.getService(SERVICE, transform.name);
518484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                if (service == null) {
519484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    continue;
520484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                }
521484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                return tryTransformWithProvider(initParams, transformParts, transform.needToSet,
522484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        service);
5233ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            }
524484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            ArrayList<Provider.Service> services = ENGINE.getServices(transform.name);
525484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            if (services == null || services.isEmpty()) {
526484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                continue;
527484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            }
528484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            for (Provider.Service service : services) {
529484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                if (initParams == null || initParams.key == null
530484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        || service.supportsParameter(initParams.key)) {
531484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    try {
532484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        Engine.SpiAndProvider sap = tryTransformWithProvider(initParams,
533484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                                transformParts, transform.needToSet, service);
534484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        if (sap != null) {
535484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                            return sap;
536484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        }
537484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    } catch (Exception e) {
538484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        if (cause == null) {
539484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                            cause = e;
540484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        }
541484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    }
5422ae508725e0b6c4dd4c23717bc1625bd745670b6Sergio Giro                }
54385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            }
54485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
545484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        if (cause instanceof InvalidKeyException) {
546484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw (InvalidKeyException) cause;
547484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } else if (cause instanceof InvalidAlgorithmParameterException) {
548484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw (InvalidAlgorithmParameterException) cause;
549484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } else if (cause instanceof RuntimeException) {
550484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw (RuntimeException) cause;
551484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } else if (cause != null) {
552484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new InvalidKeyException("No provider can be initialized with given key", cause);
553484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } else if (initParams == null || initParams.key == null) {
554484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            return null;
555484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } else {
556484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // Since the key is not null, a suitable provider exists,
557484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // and it is an InvalidKeyException.
558484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new InvalidKeyException("No provider offers " + transformation + " for "
559484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    + initParams.key.getAlgorithm() + " key of class "
560484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    + initParams.key.getClass().getName() + " and export format "
561484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    + initParams.key.getFormat());
562484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
56385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
56485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
565484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
566484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Tries to initialize the {@code Cipher} from a given {@code service}. If
567484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * initialization is successful, the initialized {@code spi} is returned. If
568484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * the {@code service} cannot be initialized with the specified
569484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code initParams}, then it's expected to throw
570484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code InvalidKeyException} or {@code InvalidAlgorithmParameterException}
571484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * as a hint to the caller that it should continue searching for a
572484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code Service} that will work.
573484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
574484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    private static Engine.SpiAndProvider tryTransformWithProvider(InitParams initParams,
575484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            String[] transformParts, NeedToSet type, Provider.Service service)
576484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throws InvalidKeyException, InvalidAlgorithmParameterException {
5773ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root        try {
5783ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            /*
5793ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root             * Check to see if the Cipher even supports the attributes before
5803ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root             * trying to instantiate it.
5813ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root             */
5823ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            if (!matchAttribute(service, ATTRIBUTE_MODES, transformParts[1])
5833ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                    || !matchAttribute(service, ATTRIBUTE_PADDINGS, transformParts[2])) {
5843ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                return null;
5853ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            }
5863ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root
5873ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
5883ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            if (sap.spi == null || sap.provider == null) {
58907c8c69f59b60684fe07b003b3462e8d9687f422Kenny Root                return null;
5903ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            }
5913ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            CipherSpi spi = (CipherSpi) sap.spi;
5923ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH))
5933ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                    && (transformParts[1] != null)) {
5943ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                spi.engineSetMode(transformParts[1]);
5953ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            }
5963ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            if (((type == NeedToSet.PADDING) || (type == NeedToSet.BOTH))
5973ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                    && (transformParts[2] != null)) {
5983ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root                spi.engineSetPadding(transformParts[2]);
5993ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            }
600484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root
601484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            if (initParams != null) {
602484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                switch (initParams.initType) {
603484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    case ALGORITHM_PARAMS:
604484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        spi.engineInit(initParams.opmode, initParams.key, initParams.params,
605484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                                initParams.random);
606484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        break;
607484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    case ALGORITHM_PARAM_SPEC:
608484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        spi.engineInit(initParams.opmode, initParams.key, initParams.spec,
609484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                                initParams.random);
610484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        break;
611484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    case KEY:
612484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        spi.engineInit(initParams.opmode, initParams.key, initParams.random);
613484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        break;
614484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                    default:
615484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                        throw new AssertionError("This should never be reached");
616484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root                }
617484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            }
6183ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root            return sap;
6193ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root        } catch (NoSuchAlgorithmException ignored) {
6203ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root        } catch (NoSuchPaddingException ignored) {
6213ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root        }
6223ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root        return null;
6233ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root    }
6243ed78a8925825daccdba23fda1f69cbb3aa77a24Kenny Root
62585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
62685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * If the attribute listed exists, check that it matches the regular
62785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * expression.
62885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     */
62985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private static boolean matchAttribute(Service service, String attr, String value) {
63085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (value == null) {
63185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            return true;
63285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
63385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        final String pattern = service.getAttribute(attr);
63485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (pattern == null) {
63585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            return true;
63685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
63785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        final String valueUc = value.toUpperCase(Locale.US);
63885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return valueUc.matches(pattern.toUpperCase(Locale.US));
63985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
64085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
64185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    /**
64285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root     * Returns the provider of this cipher instance.
64307c8c69f59b60684fe07b003b3462e8d9687f422Kenny Root     *
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the provider of this cipher instance.
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Provider getProvider() {
64785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        getSpi();
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return provider;
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the name of the algorithm of this cipher instance.
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is the name of the <i>transformation</i> argument used in the
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code getInstance} call creating this object.
656ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the name of the algorithm of this cipher instance.
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final String getAlgorithm() {
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return transformation;
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns this ciphers block size (in bytes).
665ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this ciphers block size.
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int getBlockSize() {
66985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineGetBlockSize();
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the length in bytes an output buffer needs to be when this cipher
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is updated with {@code inputLen} bytes.
675ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of bytes of the input.
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the output buffer length for the input length.
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is in an invalid state.
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int getOutputSize(int inputLen) {
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode == 0) {
68480a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException("Cipher has not yet been initialized");
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
68685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineGetOutputSize(inputLen);
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the <i>initialization vector</i> for this cipher instance.
691ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the <i>initialization vector</i> for this cipher instance.
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] getIV() {
69585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineGetIV();
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the parameters that where used to create this cipher instance.
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * These may be a the same parameters that were used to create this cipher
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * instance, or may be a combination of default and random parameters,
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * depending on the underlying cipher implementation.
704ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the parameters that where used to create this cipher instance, or
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code null} if this cipher instance does not have any
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         parameters.
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final AlgorithmParameters getParameters() {
71085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineGetParameters();
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the exemption mechanism associated with this cipher.
715ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return currently {@code null}
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final ExemptionMechanism getExemptionMechanism() {
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //FIXME implement getExemptionMechanism
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        try {
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //            return ExemptionMechanism.getInstance(transformation, provider);
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        } catch (NoSuchAlgorithmException e) {
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        }
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
729484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root    /**
730484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * Checks that the provided {@code mode} is one that is valid for
731484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     * {@code Cipher}.
732484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root     */
73385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    private void checkMode(int mode) {
73485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE
73585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root                && mode != WRAP_MODE) {
73685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root            throw new InvalidParameterException("Invalid mode: " + mode);
73785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        }
73885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root    }
73985dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key.
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher is initialized for the specified operational mode (one of:
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
746ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters or random values
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that the specified key can not provide, the underlying implementation of
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this cipher is supposed to generate the required parameters (using its
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider or random values).
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, meaning that it
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is equivalent to creating a new instance and calling its {@code init}
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method.
756ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Key key) throws InvalidKeyException {
7689229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        if (secureRandom == null) {
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // In theory it might be thread-unsafe but in the given case it's OK
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // since it does not matter which SecureRandom instance is passed
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // to the init()
7729229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes            secureRandom = new SecureRandom();
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
7749229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        init(opmode, key, secureRandom);
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key and a source of
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * randomness.
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher is initialized for the specified operational mode (one of:
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
784ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters or random values
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that the specified key can not provide, the underlying implementation of
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this cipher is supposed to generate the required parameters (using its
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider or random values). Random values are generated using {@code
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * random};
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, means it is
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equivalent to creating a new instance and calling it {@code init} method.
794ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param random
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source of randomness to use.
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidParameterException
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified opmode is invalid.
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
80980a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes    public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
8100c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        checkMode(opmode);
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidKeyException
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if keysize exceeds the maximum allowable keysize
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
814484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        try {
815484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            getSpi(new InitParams(InitType.KEY, opmode, key, random, null, null));
816484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } catch (InvalidAlgorithmParameterException e) {
817484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // Should never happen since we only specified the key.
818484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new ProviderException("Invalid parameters when params == null", e);
819484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        mode = opmode;
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key and algorithm
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parameters.
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher is initialized for the specified operational mode (one of:
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping).
829ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters and {@code params}
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is {@code null}, the underlying implementation of this cipher is supposed
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to generate the required parameters (using its provider or random
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * values).
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, means it is
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equivalent to creating a new instance and calling it {@code init} method.
838ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param params
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm parameters.
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidAlgorithmParameterException
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             it the specified parameters are inappropriate for this
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher.
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Key key, AlgorithmParameterSpec params)
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws InvalidKeyException, InvalidAlgorithmParameterException {
8569229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        if (secureRandom == null) {
8579229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes            secureRandom = new SecureRandom();
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
8599229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        init(opmode, key, params, secureRandom);
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key, algorithm
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parameters and a source of randomness.
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher is initialized for the specified operational mode (one of:
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters and {@code params}
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is {@code null}, the underlying implementation of this cipher is supposed
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to generate the required parameters (using its provider or random
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * values). Random values are generated using {@code random};
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, meaning that it
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is equivalent to creating a new instance and calling it {@code init}
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method.
879ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param params
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm parameters.
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param random
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source of randomness to use.
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidAlgorithmParameterException
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             it the specified parameters are inappropriate for this
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher.
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidParameterException
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified {@code opmode} is invalid.
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Key key, AlgorithmParameterSpec params,
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SecureRandom random) throws InvalidKeyException,
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InvalidAlgorithmParameterException {
9020c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        checkMode(opmode);
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidKeyException
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if keysize exceeds the maximum allowable keysize
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidAlgorithmParameterException
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        cryptographic strength exceed the legal limits
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
909484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        getSpi(new InitParams(InitType.ALGORITHM_PARAM_SPEC, opmode, key, random, params, null));
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        mode = opmode;
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key and algorithm
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parameters.
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher is initialized for the specified operation (one of:
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
920ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters and {@code params}
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is {@code null}, the underlying implementation of this cipher is supposed
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to generate the required parameters (using its provider or random
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * values).
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, meaning that it
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is equivalent to creating a new instance and calling it {@code init}
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method.
930ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param params
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm parameters.
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidAlgorithmParameterException
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             it the specified parameters are inappropriate for this
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher.
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Key key, AlgorithmParameters params)
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws InvalidKeyException, InvalidAlgorithmParameterException {
9489229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        if (secureRandom == null) {
9499229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes            secureRandom = new SecureRandom();
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
9519229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        init(opmode, key, params, secureRandom);
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the specified key, algorithm
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parameters and a source of randomness.
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher will be initialized for the specified operation (one of:
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
961ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters and {@code params}
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is {@code null}, the underlying implementation of this cipher is supposed
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to generate the required parameters (using its provider or random
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * values). Random values are generated using {@code random}.
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, means it is
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equivalent to creating a new instance and calling it {@code init} method.
970ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input key for the operation.
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param params
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm parameters.
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param random
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source of randomness to use.
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified key can not be used to initialize this
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher instance.
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidAlgorithmParameterException
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified parameters are inappropriate for this
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher.
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidParameterException
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the specified {@code opmode} is invalid.
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Key key, AlgorithmParameters params,
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SecureRandom random) throws InvalidKeyException,
992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InvalidAlgorithmParameterException {
9930c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        checkMode(opmode);
994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidKeyException
995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if keysize exceeds the maximum allowable keysize
996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidAlgorithmParameterException
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        cryptographic strength exceed the legal limits
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
1000484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        getSpi(new InitParams(InitType.ALGORITHM_PARAMS, opmode, key, random, null, params));
1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        mode = opmode;
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the public key from the specified
1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * certificate.
1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher will be initialized for the specified operation (one of:
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * It the type of the certificate is X.509 and the certificate has a <i>key
1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * usage</i> extension field marked as critical, the specified {@code
1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * opmode} has the be enabled for this key, otherwise an {@code
1015adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * InvalidKeyException} is thrown.
1016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1017adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters that the key in
1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the certificate can not provide, the underlying implementation of this
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * cipher is supposed to generate the required parameters (using its
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider or random values).
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, means it is
1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equivalent to creating a new instance and calling it {@code init} method.
1025ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param certificate
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the certificate.
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the public key in the certificate can not be used to
1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             initialize this cipher instance.
1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Certificate certificate)
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws InvalidKeyException {
10389229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        if (secureRandom == null) {
10399229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes            secureRandom = new SecureRandom();
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
10419229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes        init(opmode, certificate, secureRandom);
1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Initializes this cipher instance with the public key from the specified
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * certificate and a source of randomness.
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The cipher will be initialized for the specified operation (one of:
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * encryption, decryption, key wrapping or key unwrapping) depending on
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code opmode}.
1051ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * It the type of the certificate is X.509 and the certificate has a <i>key
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * usage</i> extension field marked as critical, the specified {@code
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * opmode} has the be enabled for this key, otherwise an {@code
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * InvalidKeyException} is thrown.
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this cipher instance needs any algorithm parameters that the key in
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the certificate can not provide, the underlying implementation of this
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * cipher is supposed to generate the required parameters (using its
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provider or random values). Random values are generated using {@code
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * random}.
1062ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * When a cipher instance is initialized by a call to any of the {@code
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * init} methods, the state of the instance is overridden, means it is
1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equivalent to creating a new instance and calling it {@code init} method.
1066ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param opmode
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the operation this cipher instance should be initialized for
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            WRAP_MODE} or {@code UNWRAP_MODE}).
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param certificate
1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the certificate.
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param random
1074adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source of randomness to be used.
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the public key in the certificate can not be used to
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             initialize this cipher instance.
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void init(int opmode, Certificate certificate,
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SecureRandom random) throws InvalidKeyException {
10810c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        checkMode(opmode);
1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (certificate instanceof X509Certificate) {
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean critical = false;
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ce != null && !ce.isEmpty()) {
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (String oid : ce) {
10870d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        critical = true;
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (critical) {
10930d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    boolean[] keyUsage = ((X509Certificate) certificate).getKeyUsage();
10940d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    // As specified in RFC 3280:
10950d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //   Internet X.509 Public Key Infrastructure
10960d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //   Certificate and Certificate Revocation List (CRL) Profile.
10970d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    // Section 4.2.1.3  Key Usage
10980d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    // http://www.ietf.org/rfc/rfc3280.txt
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    //
1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // KeyUsage ::= BIT STRING {digitalSignature (0),
11010d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          nonRepudiation   (1),
11020d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          keyEncipherment  (2),
11030d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          dataEncipherment (3),
11040d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          keyAgreement     (4),
11050d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          keyCertSign      (5),
11060d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          cRLSign          (6),
11070d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          encipherOnly     (7),
11080d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                    //                          decipherOnly     (8) }
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (keyUsage != null) {
11100d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                        if (opmode == ENCRYPT_MODE && !keyUsage[3]) {
11110a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom                            throw new InvalidKeyException("The public key in the certificate "
11120a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom                                                          + "cannot be used for ENCRYPT_MODE");
11130d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                        } else if (opmode == WRAP_MODE && !keyUsage[2]) {
11140a480846a9798c763b088a122ab0dcd3dc3a17b6Brian Carlstrom                            throw new InvalidKeyException("The public key in the certificate "
11150d5c7588179fb373da70ce04362be5ce74a98eb4Brian Carlstrom                                                          + "cannot be used for WRAP_MODE");
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        FIXME InvalidKeyException
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        if keysize exceeds the maximum allowable keysize
1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //        (jurisdiction policy files)
112485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        final Key key = certificate.getPublicKey();
1125484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        try {
1126484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            getSpi(new InitParams(InitType.KEY, opmode, key, random, null, null));
1127484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        } catch (InvalidAlgorithmParameterException e) {
1128484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            // Should never happen since we only specified the key.
1129484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root            throw new ProviderException("Invalid parameters when params == null", e);
1130484509de8262bb0a56b303016e93f4be1cf0d795Kenny Root        }
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        mode = opmode;
1132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Continues a multi-part transformation (encryption or decryption). The
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformed bytes are returned.
1137ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input bytes to transform.
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the transformed bytes in a new buffer, or {@code null} if the
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         input has zero length.
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input is {@code null}.
1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] update(byte[] input) {
1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
115080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input == null) {
115380a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("input == null");
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input.length == 0) {
1156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
115885dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineUpdate(input, 0, input.length);
1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Continues a multi-part transformation (encryption or decryption). The
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformed bytes are returned.
1164ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input bytes to transform.
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input to start.
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input to transform.
1171b8211a7b902b559da234264f5fa1fcf09677f54bAlex Klyubin     * @return the transformed bytes in a new buffer, or {@code null} if {@code inputLen} is zero.
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1176d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if {@code input} is {@code null}, or if {@code inputOffset} and
1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code inputLen} do not specify a valid chunk in the input
1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             buffer.
1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] update(byte[] input, int inputOffset, int inputLen) {
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
118280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input == null) {
118580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("input == null");
1186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1187c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1188b8211a7b902b559da234264f5fa1fcf09677f54bAlex Klyubin        if (inputLen == 0) {
1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
1190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
119185dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineUpdate(input, inputOffset, inputLen);
1192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1194c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom    private static void checkInputOffsetAndCount(int inputArrayLength,
1195c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                                                 int inputOffset,
1196c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                                                 int inputLen) {
1197c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        if ((inputOffset | inputLen) < 0
1198c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                || inputOffset > inputArrayLength
1199c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                || inputArrayLength - inputOffset < inputLen) {
1200c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom            throw new IllegalArgumentException("input.length=" + inputArrayLength
1201c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                                               + "; inputOffset=" + inputOffset
1202c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom                                               + "; inputLen=" + inputLen);
1203c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        }
1204c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom    }
1205c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Continues a multi-part transformation (encryption or decryption). The
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformed bytes are stored in the {@code output} buffer.
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If the size of the {@code output} buffer is too small to hold the result,
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a {@code ShortBufferException} is thrown. Use
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * output buffer.
1214ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input bytes to transform.
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input to start.
1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input to transform.
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer.
1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed in output.
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input is {@code null}, the output is {@code null}, or
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code inputOffset} and {@code inputLen} do not specify a
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             valid chunk in the input buffer.
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int update(byte[] input, int inputOffset, int inputLen,
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] output) throws ShortBufferException {
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return update(input, inputOffset, inputLen, output, 0);
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Continues a multi-part transformation (encryption or decryption). The
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformed bytes are stored in the {@code output} buffer.
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If the size of the {@code output} buffer is too small to hold the result,
1244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a {@code ShortBufferException} is thrown. Use
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * output buffer.
1247ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input bytes to transform.
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input to start.
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input to transform.
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer.
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param outputOffset
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the output buffer.
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed in output.
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input is {@code null}, the output is {@code null}, or
1266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code inputOffset} and {@code inputLen} do not specify a
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             valid chunk in the input buffer.
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int update(byte[] input, int inputOffset, int inputLen,
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] output, int outputOffset) throws ShortBufferException {
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
127280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input == null) {
127580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("input == null");
1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (output == null) {
127880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("output == null");
1279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (outputOffset < 0) {
1281c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom            throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1283c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input.length == 0) {
1285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
128785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineUpdate(input, inputOffset, inputLen, output,
1288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                outputOffset);
1289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Continues a multi-part transformation (encryption or decryption). The
1293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code input.remaining()} bytes starting at {@code input.position()} are
1294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformed and stored in the {@code output} buffer.
1295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If the {@code output.remaining()} is too small to hold the transformed
1297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bytes a {@code ShortBufferException} is thrown. Use
1298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * output buffer.
1300ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer to transform.
1303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer to store the result within.
1305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes stored in the output buffer.
1306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input buffer and the output buffer are the identical
1313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             object.
1314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int update(ByteBuffer input, ByteBuffer output)
1316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws ShortBufferException {
1317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
131880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input == output) {
132180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("input == output");
1322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
132385dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineUpdate(input, output);
1324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1327d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Continues a multi-part transformation (encryption or decryption) with
1328d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Authenticated Additional Data (AAD). AAD may only be added after the
1329d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * {@code Cipher} is initialized and before any data is passed to the
1330d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * instance.
1331d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * <p>
1332d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * This is only usable with cipher modes that support Authenticated
1333d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1334d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *
1335d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @param input bytes of AAD to use with the cipher
1336d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws IllegalStateException
1337d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if this cipher instance is not initialized for encryption or
1338d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             decryption.
1339d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws IllegalArgumentException
1340d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if {@code input} is {@code null}
1341d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws UnsupportedOperationException if the cipher does not support AEAD
1342d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @since 1.7
1343d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     */
1344d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    public final void updateAAD(byte[] input) {
1345d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (input == null) {
1346d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            throw new IllegalArgumentException("input == null");
1347d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
1348d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1349d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            throw new IllegalStateException();
1350d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
1351d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (input.length == 0) {
1352d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            return;
1353d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
135485dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        getSpi().engineUpdateAAD(input, 0, input.length);
1355d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    }
1356d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root
1357d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    /**
1358d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Continues a multi-part transformation (encryption or decryption) with
1359d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Authenticated Additional Data (AAD). AAD may only be added after the
1360d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * {@code Cipher} is initialized and before any data is passed to the
1361d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * instance.
1362d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * <p>
1363d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * This is only usable with cipher modes that support Authenticated
1364d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1365d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *
1366d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @param input bytes of AAD to use with the cipher
1367d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @param inputOffset offset within bytes of additional data to add to cipher
1368d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @param inputLen length of bytes of additional data to add to cipher
1369d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws IllegalStateException
1370d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if this cipher instance is not initialized for encryption or
1371d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             decryption.
1372d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws IllegalArgumentException
1373d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if {@code input} is {@code null}, or if {@code inputOffset} and
1374d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             {@code inputLen} do not specify a valid chunk in the input
1375d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             buffer.
1376d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws UnsupportedOperationException if the cipher does not support AEAD
1377d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @since 1.7
1378d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     */
1379d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    public final void updateAAD(byte[] input, int inputOffset, int inputLen) {
1380d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1381d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            throw new IllegalStateException();
1382d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
138357323260f130e086301b1b7c0d3124a6c51f9fa8Kenny Root        if (input == null) {
138457323260f130e086301b1b7c0d3124a6c51f9fa8Kenny Root            throw new IllegalArgumentException("input == null");
138557323260f130e086301b1b7c0d3124a6c51f9fa8Kenny Root        }
1386d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1387d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (input.length == 0) {
1388d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            return;
1389d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
139085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        getSpi().engineUpdateAAD(input, inputOffset, inputLen);
1391d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    }
1392d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root
1393d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    /**
1394d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Continues a multi-part transformation (encryption or decryption) with
1395d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Authenticated Additional Data (AAD). AAD may only be added after the
1396d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * {@code Cipher} is initialized and before any data is passed to the
1397d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * instance.
1398d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * <p>
1399d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * This is only usable with cipher modes that support Authenticated
1400d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1401d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *
1402d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @param input buffer of AAD to be used
1403d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws IllegalStateException
1404d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             if this cipher instance is not initialized for encryption or
1405d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     *             decryption.
1406d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @throws UnsupportedOperationException if the cipher does not support AEAD
1407d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     * @since 1.7
1408d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root     */
1409d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    public final void updateAAD(ByteBuffer input) {
1410d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1411d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            throw new IllegalStateException("Cipher is not initialized");
1412d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
1413d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        if (input == null) {
1414d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root            throw new IllegalArgumentException("input == null");
1415d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root        }
141685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        getSpi().engineUpdateAAD(input);
1417d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    }
1418d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root
1419d416195acbc08f2b3bdd5d5532d40438465d99e9Kenny Root    /**
1420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes any bytes that may have been buffered in previous {@code
1423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * update} calls.
1424ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the final bytes from the transformation.
1426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] doFinal() throws IllegalBlockSizeException,
1436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            BadPaddingException {
1437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
143880a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
144085dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(null, 0, 0);
1441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes any bytes that may have been buffered in previous {@code
1447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * update} calls.
1448ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     * <p>
1449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The final transformed bytes are stored in the {@code output} buffer.
1450ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer.
1453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param outputOffset
1454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the output buffer.
1455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed in the output buffer.
1456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int doFinal(byte[] output, int outputOffset)
1468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IllegalBlockSizeException, ShortBufferException,
1469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            BadPaddingException {
1470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
147180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (outputOffset < 0) {
1474c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom            throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
147685dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(null, 0, 0, output, outputOffset);
1477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes the bytes in {@code input} buffer, and any bytes that have been
1483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * buffered in previous {@code update} calls.
1484ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer.
1487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the final bytes from the transformation.
1488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
1498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            BadPaddingException {
1499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
150080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
150285dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(input, 0, input.length);
1503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * inputOffset}, and any bytes that have been buffered in previous {@code
1510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * update} calls.
1511ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer.
1514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input buffer.
1516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input
1518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the final bytes from the transformation.
1519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code inputOffset} and {@code inputLen} do not specify an
1529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             valid chunk in the input buffer.
1530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
1532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IllegalBlockSizeException, BadPaddingException {
1533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
153480a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1536c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
153785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(input, inputOffset, inputLen);
1538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * inputOffset}, and any bytes that have been buffered in previous {@code
1545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * update} calls.
1546ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer.
1549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input buffer.
1551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input.
1553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer for the transformed bytes.
1555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed in the output buffer.
1556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code inputOffset} and {@code inputLen} do not specify an
1568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             valid chunk in the input buffer.
1569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int doFinal(byte[] input, int inputOffset, int inputLen,
1571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] output) throws ShortBufferException,
1572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            IllegalBlockSizeException, BadPaddingException {
1573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return doFinal(input, inputOffset, inputLen, output, 0);
1574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * inputOffset}, and any bytes that have been buffered in previous {@code
1581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * update} calls.
1582ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer.
1585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputOffset
1586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the input buffer.
1587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inputLen
1588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the length of the input.
1589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer for the transformed bytes.
1591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param outputOffset
1592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the offset in the output buffer.
1593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed in the output buffer.
1594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code inputOffset} and {@code inputLen} do not specify an
1606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             valid chunk in the input buffer.
1607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int doFinal(byte[] input, int inputOffset, int inputLen,
1609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte[] output, int outputOffset) throws ShortBufferException,
1610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            IllegalBlockSizeException, BadPaddingException {
1611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
161280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1614c1e57ed799a4fea200144330823f4acbb5330395Brian Carlstrom        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
161585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(input, inputOffset, inputLen, output,
1616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                outputOffset);
1617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Finishes a multi-part transformation (encryption or decryption).
1621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes the {@code input.remaining()} bytes in {@code input} buffer at
1623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code input.position()}, and any bytes that have been buffered in
1624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * previous {@code update} calls. The transformed bytes are placed into
1625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code output} buffer.
1626ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param input
1628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input buffer.
1629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param output
1630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the output buffer.
1631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes placed into the output buffer.
1632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ShortBufferException
1633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the {@code output} buffer is too small.
1634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws BadPaddingException
1638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the padding of the data does not match the padding scheme.
1639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the input buffer and the output buffer are the same
1641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             object.
1642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for encryption or
1644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             decryption.
1645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int doFinal(ByteBuffer input, ByteBuffer output)
1647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws ShortBufferException, IllegalBlockSizeException,
1648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            BadPaddingException {
1649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
165080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (input == output) {
165380a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalArgumentException("input == output");
1654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
165585dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineDoFinal(input, output);
1656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Wraps a key using this cipher instance.
1660ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key
1662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the key to wrap.
1663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the wrapped key.
1664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockSizeException
1665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the size of the resulting bytes is not a multiple of the
1666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             cipher block size.
1667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
1668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance can not wrap this key.
1669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for wrapping.
1671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final byte[] wrap(Key key) throws IllegalBlockSizeException,
1673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InvalidKeyException {
1674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != WRAP_MODE) {
167580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
167785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineWrap(key);
1678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Unwraps a key using this cipher instance.
1682ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param wrappedKey
1684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the wrapped key to unwrap.
1685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param wrappedKeyAlgorithm
1686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the algorithm for the wrapped key.
1687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param wrappedKeyType
1688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the type of the wrapped key (one of: {@code SECRET_KEY
1689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY})
1690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the unwrapped key
1691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws InvalidKeyException
1692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the {@code wrappedKey} can not be unwrapped to a key of
1693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             type {@code wrappedKeyType} for the {@code
1694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             wrappedKeyAlgorithm}.
1695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
1696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no provider can be found that can create a key of type
1697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
1698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalStateException
1699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this cipher instance is not initialized for unwrapping.
1700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
1702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int wrappedKeyType) throws InvalidKeyException,
1703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            NoSuchAlgorithmException {
1704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mode != UNWRAP_MODE) {
170580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes            throw new IllegalStateException();
1706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
170785dab151e734557d356fb45c45cf7d4548dd6fdcKenny Root        return getSpi().engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
1708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                wrappedKeyType);
1709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the maximum key length for the specified transformation.
1713ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
1715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the transformation name.
1716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the maximum key length, currently {@code Integer.MAX_VALUE}.
1717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
1718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no provider for the specified {@code transformation} can
1719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             be found.
1720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
1721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code transformation} is {@code null}.
1722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int getMaxAllowedKeyLength(String transformation)
1724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws NoSuchAlgorithmException {
1725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (transformation == null) {
172686acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("transformation == null");
1727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkTransformation(transformation);
1729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //FIXME jurisdiction policy files
1730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Integer.MAX_VALUE;
1731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the maximum cipher parameter value for the specified
1735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * transformation. If there is no maximum limit, {@code null} is returned.
1736ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson     *
1737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param transformation
1738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the transformation name.
1739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a parameter spec holding the maximum value or {@code null}.
1740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Currently {@code null}.
1741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NoSuchAlgorithmException
1742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if no provider for the specified {@code transformation} can
1743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             be found.
1744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
1745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code transformation} is {@code null}.
1746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
1748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String transformation) throws NoSuchAlgorithmException {
1749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (transformation == null) {
175086acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("transformation == null");
1751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkTransformation(transformation);
1753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //FIXME jurisdiction policy files
1754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
1755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1757