Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / crypto / Mac.java
blob9bbd68c21d5489dbd0269f7a521f12e2b8103b41
1 /* Mac.java -- The message authentication code interface.
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.crypto;
41 import gnu.java.security.Engine;
43 import java.lang.reflect.InvocationTargetException;
44 import java.security.InvalidAlgorithmParameterException;
45 import java.security.InvalidKeyException;
46 import java.security.Key;
47 import java.security.NoSuchAlgorithmException;
48 import java.security.NoSuchProviderException;
49 import java.security.Provider;
50 import java.security.Security;
51 import java.security.spec.AlgorithmParameterSpec;
53 /**
54 * This class implements a "message authentication code" (MAC), a method
55 * to ensure the integrity of data transmitted between two parties who
56 * share a common secret key.
58 * <p>The best way to describe a MAC is as a <i>keyed one-way hash
59 * function</i>, which looks like:
61 * <blockquote><p><code>D = MAC(K, M)</code></blockquote>
63 * <p>where <code>K</code> is the key, <code>M</code> is the message,
64 * and <code>D</code> is the resulting digest. One party will usually
65 * send the concatenation <code>M || D</code> to the other party, who
66 * will then verify <code>D</code> by computing <code>D'</code> in a
67 * similar fashion. If <code>D == D'</code>, then the message is assumed
68 * to be authentic.
70 * @author Casey Marshall (csm@gnu.org)
72 public class Mac implements Cloneable
75 // Fields.
76 // ------------------------------------------------------------------------
78 private static final String SERVICE = "Mac";
80 /** The underlying MAC implementation. */
81 private MacSpi macSpi;
83 /** The provider we got our implementation from. */
84 private Provider provider;
86 /** The name of the algorithm. */
87 private String algorithm;
89 /** Whether or not we've been initialized. */
90 private boolean virgin;
92 // Constructor.
93 // ------------------------------------------------------------------------
95 /**
96 * Creates a new Mac instance.
98 * @param macSpi The underlying MAC implementation.
99 * @param provider The provider of this implementation.
100 * @param algorithm The name of this MAC algorithm.
102 protected Mac(MacSpi macSpi, Provider provider, String algorithm)
104 this.macSpi = macSpi;
105 this.provider = provider;
106 this.algorithm = algorithm;
107 virgin = true;
110 // Class methods.
111 // ------------------------------------------------------------------------
114 * Get an instance of the named algorithm from the first provider with
115 * an appropriate implementation.
117 * @param algorithm The name of the algorithm.
118 * @return An appropriate Mac instance, if the specified algorithm
119 * is implemented by a provider.
120 * @throws java.security.NoSuchAlgorithmException If no implementation
121 * of the named algorithm is installed.
123 public static final Mac getInstance(String algorithm)
124 throws NoSuchAlgorithmException
126 Provider[] provs = Security.getProviders();
127 String msg = "";
128 for (int i = 0; i < provs.length; i++)
132 return getInstance(algorithm, provs[i]);
134 catch (NoSuchAlgorithmException nsae)
136 msg = nsae.getMessage();
139 throw new NoSuchAlgorithmException(msg);
143 * Get an instance of the named algorithm from the named provider.
145 * @param algorithm The name of the algorithm.
146 * @param provider The name of the provider.
147 * @return An appropriate Mac instance, if the specified algorithm is
148 * implemented by the named provider.
149 * @throws java.security.NoSuchAlgorithmException If the named provider
150 * has no implementation of the algorithm.
151 * @throws java.security.NoSuchProviderException If the named provider
152 * does not exist.
154 public static final Mac getInstance(String algorithm, String provider)
155 throws NoSuchAlgorithmException, NoSuchProviderException
157 Provider p = Security.getProvider(provider);
158 if (p == null)
160 throw new NoSuchProviderException(provider);
162 return getInstance(algorithm, p);
166 * Get an instance of the named algorithm from a provider.
168 * @param algorithm The name of the algorithm.
169 * @param provider The provider.
170 * @return An appropriate Mac instance, if the specified algorithm is
171 * implemented by the provider.
172 * @throws java.security.NoSuchAlgorithmException If the provider
173 * has no implementation of the algorithm.
175 public static final Mac getInstance(String algorithm, Provider provider)
176 throws NoSuchAlgorithmException
180 return new Mac((MacSpi) Engine.getInstance(SERVICE, algorithm, provider),
181 provider, algorithm);
183 catch (InvocationTargetException ite)
185 if (ite.getCause() == null)
186 throw new NoSuchAlgorithmException(algorithm);
187 if (ite.getCause() instanceof NoSuchAlgorithmException)
188 throw (NoSuchAlgorithmException) ite.getCause();
189 throw new NoSuchAlgorithmException(algorithm);
191 catch (ClassCastException cce)
193 throw new NoSuchAlgorithmException(algorithm);
197 // Instance methods.
198 // ------------------------------------------------------------------------
201 * Finishes the computation of a MAC and returns the digest.
203 * <p>After this method succeeds, it may be used again as just after a
204 * call to <code>init</code>, and can compute another MAC using the
205 * same key and parameters.
207 * @return The message authentication code.
208 * @throws java.lang.IllegalStateException If this instnace has not
209 * been initialized.
211 public final byte[] doFinal() throws IllegalStateException
213 if (virgin)
215 throw new IllegalStateException("not initialized");
217 byte[] digest = macSpi.engineDoFinal();
218 reset();
219 return digest;
223 * Finishes the computation of a MAC with a final byte array (or
224 * computes a MAC over those bytes only) and returns the digest.
226 * <p>After this method succeeds, it may be used again as just after a
227 * call to <code>init</code>, and can compute another MAC using the
228 * same key and parameters.
230 * @param input The bytes to add.
231 * @return The message authentication code.
232 * @throws java.lang.IllegalStateException If this instnace has not
233 * been initialized.
235 public final byte[] doFinal(byte[] input) throws IllegalStateException
237 update(input);
238 byte[] digest = macSpi.engineDoFinal();
239 reset();
240 return digest;
244 * Finishes the computation of a MAC and places the result into the
245 * given array.
247 * <p>After this method succeeds, it may be used again as just after a
248 * call to <code>init</code>, and can compute another MAC using the
249 * same key and parameters.
251 * @param output The destination for the result.
252 * @param outOffset The index in the output array to start.
253 * @return The message authentication code.
254 * @throws java.lang.IllegalStateException If this instnace has not
255 * been initialized.
256 * @throws javax.crypto.ShortBufferException If <code>output</code> is
257 * not large enough to hold the result.
259 public final void doFinal(byte[] output, int outOffset)
260 throws IllegalStateException, ShortBufferException
262 if (virgin)
264 throw new IllegalStateException("not initialized");
266 if (output.length - outOffset < getMacLength())
268 throw new ShortBufferException();
270 byte[] mac = macSpi.engineDoFinal();
271 System.arraycopy(mac, 0, output, outOffset, getMacLength());
272 reset();
276 * Returns the name of this MAC algorithm.
278 * @return The MAC name.
280 public final String getAlgorithm()
282 return algorithm;
286 * Get the size of the MAC. This is the size of the array returned by
287 * {@link #doFinal()} and {@link #doFinal(byte[])}, and the minimum
288 * number of bytes that must be available in the byte array passed to
289 * {@link #doFinal(byte[],int)}.
291 * @return The MAC length.
293 public final int getMacLength()
295 return macSpi.engineGetMacLength();
299 * Get the provider of the underlying implementation.
301 * @return The provider.
303 public final Provider getProvider()
305 return provider;
309 * Initialize this MAC with a key and no parameters.
311 * @param key The key to initialize this instance with.
312 * @throws java.security.InvalidKeyException If the key is
313 * unacceptable.
315 public final void init(Key key) throws InvalidKeyException
319 init(key, null);
321 catch (InvalidAlgorithmParameterException iape)
323 throw new IllegalArgumentException(algorithm + " needs parameters");
328 * Initialize this MAC with a key and parameters.
330 * @param key The key to initialize this instance with.
331 * @param params The algorithm-specific parameters.
332 * @throws java.security.InvalidAlgorithmParameterException If the
333 * algorithm parameters are unacceptable.
334 * @throws java.security.InvalidKeyException If the key is
335 * unacceptable.
337 public final void init(Key key, AlgorithmParameterSpec params)
338 throws InvalidAlgorithmParameterException, InvalidKeyException
340 macSpi.engineInit(key, params);
341 virgin = false; // w00t!
345 * Reset this instance. A call to this method returns this instance
346 * back to the state it was in just after it was initialized.
348 public final void reset()
350 macSpi.engineReset();
354 * Update the computation with a single byte.
356 * @param input The next byte.
357 * @throws java.lang.IllegalStateException If this instance has not
358 * been initialized.
360 public final void update(byte input) throws IllegalStateException
362 if (virgin)
364 throw new IllegalStateException("not initialized");
366 macSpi.engineUpdate(input);
370 * Update the computation with a byte array.
372 * @param input The next bytes.
373 * @throws java.lang.IllegalStateException If this instance has not
374 * been initialized.
376 public final void update(byte[] input) throws IllegalStateException
378 update(input, 0, input.length);
382 * Update the computation with a portion of a byte array.
384 * @param input The next bytes.
385 * @param offset The index in <code>input</code> to start.
386 * @param length The number of bytes to update.
387 * @throws java.lang.IllegalStateException If this instance has not
388 * been initialized.
390 public final void update(byte[] input, int offset, int length)
391 throws IllegalStateException
393 if (virgin)
395 throw new IllegalStateException("not initialized");
397 macSpi.engineUpdate(input, offset, length);
401 * Clone this instance, if the underlying implementation supports it.
403 * @return A clone of this instance.
404 * @throws java.lang.CloneNotSupportedException If the underlying
405 * implementation is not cloneable.
407 public final Object clone() throws CloneNotSupportedException
409 Mac result = new Mac((MacSpi) macSpi.clone(), provider, algorithm);
410 result.virgin = virgin;
411 return result;