blob: 5a73dc57af30e9c3f0991946135b5cc0548193cc [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package javax.crypto;
19
20import java.nio.ByteBuffer;
21import java.security.InvalidAlgorithmParameterException;
22import java.security.InvalidKeyException;
23import java.security.Key;
24import java.security.NoSuchAlgorithmException;
25import java.security.NoSuchProviderException;
26import java.security.Provider;
Kenny Root91e77f62014-02-06 16:00:43 -080027import java.security.ProviderException;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080028import java.security.Security;
29import java.security.spec.AlgorithmParameterSpec;
Kenny Root91e77f62014-02-06 16:00:43 -080030import java.util.ArrayList;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080031import org.apache.harmony.security.fortress.Engine;
32
33
34/**
35 * This class provides the public API for <i>Message Authentication Code</i>
36 * (MAC) algorithms.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080037 */
38public class Mac implements Cloneable {
39
Kenny Root91e77f62014-02-06 16:00:43 -080040 // The service name.
41 private static final String SERVICE = "Mac";
42
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080043 //Used to access common engine functionality
Kenny Root91e77f62014-02-06 16:00:43 -080044 private static final Engine ENGINE = new Engine(SERVICE);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080045
46 // Store used provider
Kenny Root91e77f62014-02-06 16:00:43 -080047 private Provider provider;
48
49 // Provider that was requested during creation.
50 private final Provider specifiedProvider;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080051
52 // Store used spi implementation
Kenny Root91e77f62014-02-06 16:00:43 -080053 private MacSpi spiImpl;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080054
55 // Store used algorithm name
56 private final String algorithm;
57
Kenny Root91e77f62014-02-06 16:00:43 -080058 /**
59 * Lock held while the SPI is initializing.
60 */
61 private final Object initLock = new Object();
62
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080063 // Store Mac state (initialized or not initialized)
64 private boolean isInitMac;
65
66 /**
67 * Creates a new {@code Mac} instance.
Jesse Wilsonce9ec012009-08-31 15:37:14 -070068 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080069 * @param macSpi
70 * the implementation delegate.
71 * @param provider
72 * the implementation provider.
73 * @param algorithm
74 * the name of the MAC algorithm.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080075 */
76 protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
Kenny Root91e77f62014-02-06 16:00:43 -080077 this.specifiedProvider = provider;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080078 this.algorithm = algorithm;
79 this.spiImpl = macSpi;
80 this.isInitMac = false;
81 }
82
83 /**
84 * Returns the name of the MAC algorithm.
Elliott Hughesf33eae72010-05-13 12:36:25 -070085 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080086 * @return the name of the MAC algorithm.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080087 */
88 public final String getAlgorithm() {
89 return algorithm;
90 }
91
92 /**
93 * Returns the provider of this {@code Mac} instance.
Jesse Wilsonce9ec012009-08-31 15:37:14 -070094 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080095 * @return the provider of this {@code Mac} instance.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080096 */
97 public final Provider getProvider() {
Kenny Root91e77f62014-02-06 16:00:43 -080098 getSpi();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080099 return provider;
100 }
101
102 /**
103 * Creates a new {@code Mac} instance that provides the specified MAC
104 * algorithm.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700105 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800106 * @param algorithm
107 * the name of the requested MAC algorithm.
108 * @return the new {@code Mac} instance.
109 * @throws NoSuchAlgorithmException
110 * if the specified algorithm is not available by any provider.
111 * @throws NullPointerException
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700112 * if {@code algorithm} is {@code null} (instead of
113 * NoSuchAlgorithmException as in 1.4 release).
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800114 */
115 public static final Mac getInstance(String algorithm)
116 throws NoSuchAlgorithmException {
Kenny Root91e77f62014-02-06 16:00:43 -0800117 return getMac(algorithm, null);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800118 }
119
120 /**
121 * Creates a new {@code Mac} instance that provides the specified MAC
122 * algorithm from the specified provider.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700123 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800124 * @param algorithm
125 * the name of the requested MAC algorithm.
126 * @param provider
127 * the name of the provider that is providing the algorithm.
128 * @return the new {@code Mac} instance.
129 * @throws NoSuchAlgorithmException
130 * if the specified algorithm is not provided by the specified
131 * provider.
132 * @throws NoSuchProviderException
133 * if the specified provider is not available.
134 * @throws IllegalArgumentException
135 * if the specified provider name is {@code null} or empty.
136 * @throws NullPointerException
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700137 * if {@code algorithm} is {@code null} (instead of
138 * NoSuchAlgorithmException as in 1.4 release).
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800139 */
140 public static final Mac getInstance(String algorithm, String provider)
141 throws NoSuchAlgorithmException, NoSuchProviderException {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700142 if (provider == null || provider.isEmpty()) {
143 throw new IllegalArgumentException("Provider is null or empty");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800144 }
145 Provider impProvider = Security.getProvider(provider);
146 if (impProvider == null) {
147 throw new NoSuchProviderException(provider);
148 }
Kenny Root91e77f62014-02-06 16:00:43 -0800149 return getMac(algorithm, impProvider);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800150 }
151
152 /**
153 * Creates a new {@code Mac} instance that provides the specified MAC
Kenny Root0a648872014-02-05 10:09:13 -0800154 * algorithm from the specified provider. The {@code provider} supplied
155 * does not have to be registered.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700156 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800157 * @param algorithm
158 * the name of the requested MAC algorithm.
159 * @param provider
160 * the provider that is providing the algorithm.
161 * @return the new {@code Mac} instance.
162 * @throws NoSuchAlgorithmException
163 * if the specified algorithm is not provided by the specified
164 * provider.
165 * @throws IllegalArgumentException
166 * if {@code provider} is {@code null}.
167 * @throws NullPointerException
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700168 * if {@code algorithm} is {@code null} (instead of
169 * NoSuchAlgorithmException as in 1.4 release).
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800170 */
171 public static final Mac getInstance(String algorithm, Provider provider)
172 throws NoSuchAlgorithmException {
173 if (provider == null) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700174 throw new IllegalArgumentException("provider == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800175 }
Kenny Root91e77f62014-02-06 16:00:43 -0800176 return getMac(algorithm, provider);
177 }
178
179 private static Mac getMac(String algorithm, Provider provider)
180 throws NoSuchAlgorithmException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800181 if (algorithm == null) {
Kenny Root86acc042012-09-12 10:32:58 -0700182 throw new NullPointerException("algorithm == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800183 }
Kenny Root91e77f62014-02-06 16:00:43 -0800184
185 if (tryAlgorithm(null, provider, algorithm) == null) {
186 if (provider == null) {
187 throw new NoSuchAlgorithmException("No provider found for " + algorithm);
188 } else {
189 throw new NoSuchAlgorithmException("Provider " + provider.getName()
190 + " does not provide " + algorithm);
191 }
192 }
193 return new Mac(null, provider, algorithm);
194 }
195
196 private static Engine.SpiAndProvider tryAlgorithm(Key key, Provider provider, String algorithm) {
197 if (provider != null) {
198 Provider.Service service = provider.getService(SERVICE, algorithm);
199 if (service == null) {
200 return null;
201 }
202 return tryAlgorithmWithProvider(key, service);
203 }
204 ArrayList<Provider.Service> services = ENGINE.getServices(algorithm);
205 if (services == null) {
206 return null;
207 }
208 for (Provider.Service service : services) {
209 Engine.SpiAndProvider sap = tryAlgorithmWithProvider(key, service);
210 if (sap != null) {
211 return sap;
212 }
213 }
214 return null;
215 }
216
217 private static Engine.SpiAndProvider tryAlgorithmWithProvider(Key key, Provider.Service service) {
218 try {
219 if (key != null && !service.supportsParameter(key)) {
220 return null;
221 }
222
223 Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
224 if (sap.spi == null || sap.provider == null) {
225 return null;
226 }
227 if (!(sap.spi instanceof MacSpi)) {
228 return null;
229 }
230 return sap;
231 } catch (NoSuchAlgorithmException ignored) {
232 }
233 return null;
234 }
235
236 /**
237 * Makes sure a MacSpi that matches this type is selected.
238 */
239 private MacSpi getSpi(Key key) {
240 synchronized (initLock) {
241 if (spiImpl != null && provider != null && key == null) {
242 return spiImpl;
243 }
244
245 if (algorithm == null) {
246 return null;
247 }
248
249 final Engine.SpiAndProvider sap = tryAlgorithm(key, specifiedProvider, algorithm);
250 if (sap == null) {
251 throw new ProviderException("No provider for " + getAlgorithm());
252 }
253
254 /*
255 * Set our Spi if we've never been initialized or if we have the Spi
256 * specified and have a null provider.
257 */
258 if (spiImpl == null || provider != null) {
259 spiImpl = (MacSpi) sap.spi;
260 }
261 provider = sap.provider;
262
263 return spiImpl;
264 }
265 }
266
267 /**
268 * Convenience call when the Key is not available.
269 */
270 private MacSpi getSpi() {
271 return getSpi(null);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800272 }
273
274 /**
275 * Returns the length of this MAC (in bytes).
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700276 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800277 * @return the length of this MAC (in bytes).
278 */
279 public final int getMacLength() {
Kenny Root91e77f62014-02-06 16:00:43 -0800280 return getSpi().engineGetMacLength();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800281 }
282
283 /**
284 * Initializes this {@code Mac} instance with the specified key and
285 * algorithm parameters.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700286 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800287 * @param key
288 * the key to initialize this algorithm.
289 * @param params
290 * the parameters for this algorithm.
291 * @throws InvalidKeyException
292 * if the specified key cannot be used to initialize this
293 * algorithm, or it is null.
294 * @throws InvalidAlgorithmParameterException
295 * if the specified parameters cannot be used to initialize this
296 * algorithm.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800297 */
298 public final void init(Key key, AlgorithmParameterSpec params)
299 throws InvalidKeyException, InvalidAlgorithmParameterException {
300 if (key == null) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700301 throw new InvalidKeyException("key == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800302 }
Kenny Root91e77f62014-02-06 16:00:43 -0800303 getSpi(key).engineInit(key, params);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800304 isInitMac = true;
305 }
306
307 /**
308 * Initializes this {@code Mac} instance with the specified key.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700309 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800310 * @param key
311 * the key to initialize this algorithm.
312 * @throws InvalidKeyException
313 * if initialization fails because the provided key is {@code
314 * null}.
315 * @throws RuntimeException
316 * if the specified key cannot be used to initialize this
317 * algorithm.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800318 */
319 public final void init(Key key) throws InvalidKeyException {
320 if (key == null) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700321 throw new InvalidKeyException("key == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800322 }
323 try {
Kenny Root91e77f62014-02-06 16:00:43 -0800324 getSpi(key).engineInit(key, null);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800325 isInitMac = true;
326 } catch (InvalidAlgorithmParameterException e) {
327 throw new RuntimeException(e);
328 }
329 }
330
331 /**
332 * Updates this {@code Mac} instance with the specified byte.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700333 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800334 * @param input
335 * the byte
336 * @throws IllegalStateException
337 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800338 */
339 public final void update(byte input) throws IllegalStateException {
340 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700341 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800342 }
Kenny Root91e77f62014-02-06 16:00:43 -0800343 getSpi().engineUpdate(input);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800344 }
345
346 /**
347 * Updates this {@code Mac} instance with the data from the specified buffer
348 * {@code input} from the specified {@code offset} and length {@code len}.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700349 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800350 * @param input
351 * the buffer.
352 * @param offset
353 * the offset in the buffer.
354 * @param len
355 * the length of the data in the buffer.
356 * @throws IllegalStateException
357 * if this MAC is not initialized.
358 * @throws IllegalArgumentException
359 * if {@code offset} and {@code len} do not specified a valid
360 * chunk in {@code input} buffer.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800361 */
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700362 public final void update(byte[] input, int offset, int len) throws IllegalStateException {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800363 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700364 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800365 }
366 if (input == null) {
367 return;
368 }
369 if ((offset < 0) || (len < 0) || ((offset + len) > input.length)) {
Brian Carlstrom5043cc02013-01-18 12:14:47 -0800370 throw new IllegalArgumentException("Incorrect arguments."
371 + " input.length=" + input.length
372 + " offset=" + offset + ", len=" + len);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800373 }
Kenny Root91e77f62014-02-06 16:00:43 -0800374 getSpi().engineUpdate(input, offset, len);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800375 }
376
377 /**
378 * Copies the buffer provided as input for further processing.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700379 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800380 * @param input
381 * the buffer.
382 * @throws IllegalStateException
383 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800384 */
385 public final void update(byte[] input) throws IllegalStateException {
386 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700387 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800388 }
389 if (input != null) {
Kenny Root91e77f62014-02-06 16:00:43 -0800390 getSpi().engineUpdate(input, 0, input.length);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800391 }
392 }
393
394 /**
395 * Updates this {@code Mac} instance with the data from the specified
396 * buffer, starting at {@link ByteBuffer#position()}, including the next
397 * {@link ByteBuffer#remaining()} bytes.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700398 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800399 * @param input
400 * the buffer.
401 * @throws IllegalStateException
402 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800403 */
404 public final void update(ByteBuffer input) {
405 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700406 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800407 }
408 if (input != null) {
Kenny Root91e77f62014-02-06 16:00:43 -0800409 getSpi().engineUpdate(input);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800410 } else {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700411 throw new IllegalArgumentException("input == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800412 }
413 }
414
415 /**
416 * Computes the digest of this MAC based on the data previously specified in
417 * {@link #update} calls.
418 * <p>
419 * This {@code Mac} instance is reverted to its initial state and can be
420 * used to start the next MAC computation with the same parameters or
421 * initialized with different parameters.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700422 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800423 * @return the generated digest.
424 * @throws IllegalStateException
425 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800426 */
427 public final byte[] doFinal() throws IllegalStateException {
428 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700429 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800430 }
Kenny Root91e77f62014-02-06 16:00:43 -0800431 return getSpi().engineDoFinal();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800432 }
433
434 /**
435 * Computes the digest of this MAC based on the data previously specified in
436 * {@link #update} calls and stores the digest in the specified {@code
437 * output} buffer at offset {@code outOffset}.
438 * <p>
439 * This {@code Mac} instance is reverted to its initial state and can be
440 * used to start the next MAC computation with the same parameters or
441 * initialized with different parameters.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700442 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800443 * @param output
444 * the output buffer
445 * @param outOffset
446 * the offset in the output buffer
447 * @throws ShortBufferException
448 * if the specified output buffer is either too small for the
449 * digest to be stored, the specified output buffer is {@code
450 * null}, or the specified offset is negative or past the length
451 * of the output buffer.
452 * @throws IllegalStateException
453 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800454 */
455 public final void doFinal(byte[] output, int outOffset)
456 throws ShortBufferException, IllegalStateException {
457 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700458 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800459 }
460 if (output == null) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700461 throw new ShortBufferException("output == null");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800462 }
463 if ((outOffset < 0) || (outOffset >= output.length)) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700464 throw new ShortBufferException("Incorrect outOffset: " + outOffset);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800465 }
Kenny Root91e77f62014-02-06 16:00:43 -0800466 MacSpi spi = getSpi();
467 int t = spi.engineGetMacLength();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800468 if (t > (output.length - outOffset)) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700469 throw new ShortBufferException("Output buffer is short. Needed " + t + " bytes.");
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800470 }
Kenny Root91e77f62014-02-06 16:00:43 -0800471 byte[] result = spi.engineDoFinal();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800472 System.arraycopy(result, 0, output, outOffset, result.length);
473
474 }
475
476 /**
477 * Computes the digest of this MAC based on the data previously specified on
478 * {@link #update} calls and on the final bytes specified by {@code input}
479 * (or based on those bytes only).
480 * <p>
481 * This {@code Mac} instance is reverted to its initial state and can be
482 * used to start the next MAC computation with the same parameters or
483 * initialized with different parameters.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700484 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800485 * @param input
486 * the final bytes.
487 * @return the generated digest.
488 * @throws IllegalStateException
489 * if this MAC is not initialized.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800490 */
491 public final byte[] doFinal(byte[] input) throws IllegalStateException {
492 if (!isInitMac) {
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700493 throw new IllegalStateException();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800494 }
Kenny Root91e77f62014-02-06 16:00:43 -0800495 MacSpi spi = getSpi();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800496 if (input != null) {
Kenny Root91e77f62014-02-06 16:00:43 -0800497 spi.engineUpdate(input, 0, input.length);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800498 }
Kenny Root91e77f62014-02-06 16:00:43 -0800499 return spi.engineDoFinal();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800500 }
501
502 /**
503 * Resets this {@code Mac} instance to its initial state.
504 * <p>
505 * This {@code Mac} instance is reverted to its initial state and can be
506 * used to start the next MAC computation with the same parameters or
507 * initialized with different parameters.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800508 */
509 public final void reset() {
Kenny Root91e77f62014-02-06 16:00:43 -0800510 getSpi().engineReset();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800511 }
512
513 /**
514 * Clones this {@code Mac} instance and the underlying implementation.
Jesse Wilsonce9ec012009-08-31 15:37:14 -0700515 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800516 * @return the cloned instance.
517 * @throws CloneNotSupportedException
518 * if the underlying implementation does not support cloning.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800519 */
520 @Override
521 public final Object clone() throws CloneNotSupportedException {
Kenny Root91e77f62014-02-06 16:00:43 -0800522 MacSpi newSpiImpl = null;
523 final MacSpi spi = getSpi();
524 if (spi != null) {
525 newSpiImpl = (MacSpi) spi.clone();
526 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800527 Mac mac = new Mac(newSpiImpl, this.provider, this.algorithm);
Elliott Hughesf33eae72010-05-13 12:36:25 -0700528 mac.isInitMac = this.isInitMac;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800529 return mac;
530 }
Elliott Hughes80a7fba2010-05-21 16:58:35 -0700531}