summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/javax/crypto/Mac.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/javax/crypto/Mac.java')
-rw-r--r--luni/src/main/java/javax/crypto/Mac.java431
1 files changed, 431 insertions, 0 deletions
diff --git a/luni/src/main/java/javax/crypto/Mac.java b/luni/src/main/java/javax/crypto/Mac.java
new file mode 100644
index 0000000..94ea20e
--- /dev/null
+++ b/luni/src/main/java/javax/crypto/Mac.java
@@ -0,0 +1,431 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.crypto;
+
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.apache.harmony.crypto.internal.nls.Messages;
+import org.apache.harmony.security.fortress.Engine;
+
+
+/**
+ * This class provides the public API for <i>Message Authentication Code</i>
+ * (MAC) algorithms.
+ */
+public class Mac implements Cloneable {
+
+ //Used to access common engine functionality
+ private static final Engine engine = new Engine("Mac"); //$NON-NLS-1$
+
+ // Store used provider
+ private final Provider provider;
+
+ // Store used spi implementation
+ private final MacSpi spiImpl;
+
+ // Store used algorithm name
+ private final String algorithm;
+
+ // Store Mac state (initialized or not initialized)
+ private boolean isInitMac;
+
+ /**
+ * Creates a new {@code Mac} instance.
+ *
+ * @param macSpi
+ * the implementation delegate.
+ * @param provider
+ * the implementation provider.
+ * @param algorithm
+ * the name of the MAC algorithm.
+ */
+ protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
+ this.provider = provider;
+ this.algorithm = algorithm;
+ this.spiImpl = macSpi;
+ this.isInitMac = false;
+ }
+
+ /**
+ * Returns the name of the MAC algorithm.
+ *
+ * @return the name of the MAC algorithm.
+ */
+ public final String getAlgorithm() {
+ return algorithm;
+ }
+
+ /**
+ * Returns the provider of this {@code Mac} instance.
+ *
+ * @return the provider of this {@code Mac} instance.
+ */
+ public final Provider getProvider() {
+ return provider;
+ }
+
+ /**
+ * Creates a new {@code Mac} instance that provides the specified MAC
+ * algorithm.
+ *
+ * @param algorithm
+ * the name of the requested MAC algorithm.
+ * @return the new {@code Mac} instance.
+ * @throws NoSuchAlgorithmException
+ * if the specified algorithm is not available by any provider.
+ * @throws NullPointerException
+ * if {@code algorithm} is {@code null} (instead of
+ * NoSuchAlgorithmException as in 1.4 release).
+ */
+ public static final Mac getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ if (algorithm == null) {
+ throw new NullPointerException(Messages.getString("crypto.02")); //$NON-NLS-1$
+ }
+ synchronized (engine) {
+ engine.getInstance(algorithm, null);
+ return new Mac((MacSpi) engine.spi, engine.provider, algorithm);
+ }
+ }
+
+ /**
+ * Creates a new {@code Mac} instance that provides the specified MAC
+ * algorithm from the specified provider.
+ *
+ * @param algorithm
+ * the name of the requested MAC algorithm.
+ * @param provider
+ * the name of the provider that is providing the algorithm.
+ * @return the new {@code Mac} instance.
+ * @throws NoSuchAlgorithmException
+ * if the specified algorithm is not provided by the specified
+ * provider.
+ * @throws NoSuchProviderException
+ * if the specified provider is not available.
+ * @throws IllegalArgumentException
+ * if the specified provider name is {@code null} or empty.
+ * @throws NullPointerException
+ * if {@code algorithm} is {@code null} (instead of
+ * NoSuchAlgorithmException as in 1.4 release).
+ */
+ public static final Mac getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ if ((provider == null) || (provider.length() == 0)) {
+ throw new IllegalArgumentException(Messages.getString("crypto.03")); //$NON-NLS-1$
+ }
+ Provider impProvider = Security.getProvider(provider);
+ if (impProvider == null) {
+ throw new NoSuchProviderException(provider);
+ }
+ return getInstance(algorithm, impProvider);
+ }
+
+ /**
+ * Creates a new {@code Mac} instance that provides the specified MAC
+ * algorithm from the specified provider.
+ *
+ * @param algorithm
+ * the name of the requested MAC algorithm.
+ * @param provider
+ * the provider that is providing the algorithm.
+ * @return the new {@code Mac} instance.
+ * @throws NoSuchAlgorithmException
+ * if the specified algorithm is not provided by the specified
+ * provider.
+ * @throws IllegalArgumentException
+ * if {@code provider} is {@code null}.
+ * @throws NullPointerException
+ * if {@code algorithm} is {@code null} (instead of
+ * NoSuchAlgorithmException as in 1.4 release).
+ */
+ public static final Mac getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ if (provider == null) {
+ throw new IllegalArgumentException(Messages.getString("crypto.04")); //$NON-NLS-1$
+ }
+ if (algorithm == null) {
+ throw new NullPointerException(Messages.getString("crypto.02")); //$NON-NLS-1$
+ }
+ synchronized (engine) {
+ engine.getInstance(algorithm, provider, null);
+ return new Mac((MacSpi) engine.spi, provider, algorithm);
+ }
+ }
+
+ /**
+ * Returns the length of this MAC (in bytes).
+ *
+ * @return the length of this MAC (in bytes).
+ */
+ public final int getMacLength() {
+ return spiImpl.engineGetMacLength();
+ }
+
+ /**
+ * Initializes this {@code Mac} instance with the specified key and
+ * algorithm parameters.
+ *
+ * @param key
+ * the key to initialize this algorithm.
+ * @param params
+ * the parameters for this algorithm.
+ * @throws InvalidKeyException
+ * if the specified key cannot be used to initialize this
+ * algorithm, or it is null.
+ * @throws InvalidAlgorithmParameterException
+ * if the specified parameters cannot be used to initialize this
+ * algorithm.
+ */
+ public final void init(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (key == null) {
+ throw new InvalidKeyException(Messages.getString("crypto.05")); //$NON-NLS-1$
+ }
+ spiImpl.engineInit(key, params);
+ isInitMac = true;
+ }
+
+ /**
+ * Initializes this {@code Mac} instance with the specified key.
+ *
+ * @param key
+ * the key to initialize this algorithm.
+ * @throws InvalidKeyException
+ * if initialization fails because the provided key is {@code
+ * null}.
+ * @throws RuntimeException
+ * if the specified key cannot be used to initialize this
+ * algorithm.
+ */
+ public final void init(Key key) throws InvalidKeyException {
+ if (key == null) {
+ throw new InvalidKeyException(Messages.getString("crypto.05")); //$NON-NLS-1$
+ }
+ try {
+ spiImpl.engineInit(key, null);
+ isInitMac = true;
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Updates this {@code Mac} instance with the specified byte.
+ *
+ * @param input
+ * the byte
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final void update(byte input) throws IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ spiImpl.engineUpdate(input);
+ }
+
+ /**
+ * Updates this {@code Mac} instance with the data from the specified buffer
+ * {@code input} from the specified {@code offset} and length {@code len}.
+ *
+ * @param input
+ * the buffer.
+ * @param offset
+ * the offset in the buffer.
+ * @param len
+ * the length of the data in the buffer.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ * @throws IllegalArgumentException
+ * if {@code offset} and {@code len} do not specified a valid
+ * chunk in {@code input} buffer.
+ */
+ public final void update(byte[] input, int offset, int len)
+ throws IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ if (input == null) {
+ return;
+ }
+ if ((offset < 0) || (len < 0) || ((offset + len) > input.length)) {
+ throw new IllegalArgumentException(Messages.getString("crypto.06")); //$NON-NLS-1$
+ }
+ spiImpl.engineUpdate(input, offset, len);
+ }
+
+ /**
+ * Copies the buffer provided as input for further processing.
+ *
+ * @param input
+ * the buffer.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final void update(byte[] input) throws IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ if (input != null) {
+ spiImpl.engineUpdate(input, 0, input.length);
+ }
+ }
+
+ /**
+ * Updates this {@code Mac} instance with the data from the specified
+ * buffer, starting at {@link ByteBuffer#position()}, including the next
+ * {@link ByteBuffer#remaining()} bytes.
+ *
+ * @param input
+ * the buffer.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final void update(ByteBuffer input) {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ if (input != null) {
+ spiImpl.engineUpdate(input);
+ } else {
+ throw new IllegalArgumentException(Messages.getString("crypto.07")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Computes the digest of this MAC based on the data previously specified in
+ * {@link #update} calls.
+ * <p>
+ * This {@code Mac} instance is reverted to its initial state and can be
+ * used to start the next MAC computation with the same parameters or
+ * initialized with different parameters.
+ *
+ * @return the generated digest.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final byte[] doFinal() throws IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ return spiImpl.engineDoFinal();
+ }
+
+ /**
+ * Computes the digest of this MAC based on the data previously specified in
+ * {@link #update} calls and stores the digest in the specified {@code
+ * output} buffer at offset {@code outOffset}.
+ * <p>
+ * This {@code Mac} instance is reverted to its initial state and can be
+ * used to start the next MAC computation with the same parameters or
+ * initialized with different parameters.
+ *
+ * @param output
+ * the output buffer
+ * @param outOffset
+ * the offset in the output buffer
+ * @throws ShortBufferException
+ * if the specified output buffer is either too small for the
+ * digest to be stored, the specified output buffer is {@code
+ * null}, or the specified offset is negative or past the length
+ * of the output buffer.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final void doFinal(byte[] output, int outOffset)
+ throws ShortBufferException, IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.01"));
+ }
+ if (output == null) {
+ throw new ShortBufferException(Messages.getString("crypto.08")); //$NON-NLS-1$
+ }
+ if ((outOffset < 0) || (outOffset >= output.length)) {
+ throw new ShortBufferException(Messages.getString("crypto.09", //$NON-NLS-1$
+ Integer.toString(outOffset)));
+ }
+ int t = spiImpl.engineGetMacLength();
+ if (t > (output.length - outOffset)) {
+ throw new ShortBufferException(
+ Messages.getString("crypto.0A", //$NON-NLS-1$
+ Integer.toString(t)));
+ }
+ byte[] result = spiImpl.engineDoFinal();
+ System.arraycopy(result, 0, output, outOffset, result.length);
+
+ }
+
+ /**
+ * Computes the digest of this MAC based on the data previously specified on
+ * {@link #update} calls and on the final bytes specified by {@code input}
+ * (or based on those bytes only).
+ * <p>
+ * This {@code Mac} instance is reverted to its initial state and can be
+ * used to start the next MAC computation with the same parameters or
+ * initialized with different parameters.
+ *
+ * @param input
+ * the final bytes.
+ * @return the generated digest.
+ * @throws IllegalStateException
+ * if this MAC is not initialized.
+ */
+ public final byte[] doFinal(byte[] input) throws IllegalStateException {
+ if (!isInitMac) {
+ throw new IllegalStateException(Messages.getString("crypto.0B")); //$NON-NLS-1$
+ }
+ if (input != null) {
+ spiImpl.engineUpdate(input, 0, input.length);
+ }
+ return spiImpl.engineDoFinal();
+ }
+
+ /**
+ * Resets this {@code Mac} instance to its initial state.
+ * <p>
+ * This {@code Mac} instance is reverted to its initial state and can be
+ * used to start the next MAC computation with the same parameters or
+ * initialized with different parameters.
+ */
+ public final void reset() {
+ spiImpl.engineReset();
+ }
+
+ /**
+ * Clones this {@code Mac} instance and the underlying implementation.
+ *
+ * @return the cloned instance.
+ * @throws CloneNotSupportedException
+ * if the underlying implementation does not support cloning.
+ */
+ @Override
+ public final Object clone() throws CloneNotSupportedException {
+ MacSpi newSpiImpl = (MacSpi)spiImpl.clone();
+ Mac mac = new Mac(newSpiImpl, this.provider, this.algorithm);
+ mac.isInitMac = this.isInitMac;
+ return mac;
+ }
+} \ No newline at end of file