blob: 1809f6d82aed8520edb167f3fc0bcdcfedff7788 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.crypto.provider;
27
28import java.security.*;
29import java.security.spec.*;
30import javax.crypto.*;
31import javax.crypto.spec.*;
32import javax.crypto.BadPaddingException;
33
34/**
35 * This class implements the AES algorithm in its various modes
36 * (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,
37 * <code>PCBC</code>) and padding schemes (<code>PKCS5Padding</code>,
38 * <code>NoPadding</code>, <code>ISO10126Padding</code>).
39 *
40 * @author Valerie Peng
41 *
42 *
43 * @see AESCrypt
44 * @see CipherBlockChaining
45 * @see ElectronicCodeBook
46 * @see CipherFeedback
47 * @see OutputFeedback
48 */
49
50public final class AESCipher extends CipherSpi {
51 /*
52 * internal CipherCore object which does the real work.
53 */
54 private CipherCore core = null;
55
56 /**
57 * Creates an instance of AES cipher with default ECB mode and
58 * PKCS5Padding.
59 *
60 * @exception SecurityException if this constructor fails to verify
61 * its own integrity
62 */
63 public AESCipher() {
64 SunJCE.ensureIntegrity(getClass());
65 core = new CipherCore(new AESCrypt(), AESConstants.AES_BLOCK_SIZE);
66 }
67
68 /**
69 * Sets the mode of this cipher.
70 *
71 * @param mode the cipher mode
72 *
73 * @exception NoSuchAlgorithmException if the requested cipher mode does
74 * not exist
75 */
76 protected void engineSetMode(String mode)
77 throws NoSuchAlgorithmException {
78 core.setMode(mode);
79 }
80
81 /**
82 * Sets the padding mechanism of this cipher.
83 *
84 * @param padding the padding mechanism
85 *
86 * @exception NoSuchPaddingException if the requested padding mechanism
87 * does not exist
88 */
89 protected void engineSetPadding(String paddingScheme)
90 throws NoSuchPaddingException {
91 core.setPadding(paddingScheme);
92 }
93
94 /**
95 * Returns the block size (in bytes).
96 *
97 * @return the block size (in bytes), or 0 if the underlying algorithm is
98 * not a block cipher
99 */
100 protected int engineGetBlockSize() {
101 return AESConstants.AES_BLOCK_SIZE;
102 }
103
104 /**
105 * Returns the length in bytes that an output buffer would need to be in
106 * order to hold the result of the next <code>update</code> or
107 * <code>doFinal</code> operation, given the input length
108 * <code>inputLen</code> (in bytes).
109 *
110 * <p>This call takes into account any unprocessed (buffered) data from a
111 * previous <code>update</code> call, and padding.
112 *
113 * <p>The actual output length of the next <code>update</code> or
114 * <code>doFinal</code> call may be smaller than the length returned by
115 * this method.
116 *
117 * @param inputLen the input length (in bytes)
118 *
119 * @return the required output buffer size (in bytes)
120 */
121 protected int engineGetOutputSize(int inputLen) {
122 return core.getOutputSize(inputLen);
123 }
124
125 /**
126 * Returns the initialization vector (IV) in a new buffer.
127 *
128 * <p>This is useful in the case where a random IV has been created
129 * (see <a href = "#init">init</a>),
130 * or in the context of password-based encryption or
131 * decryption, where the IV is derived from a user-provided password.
132 *
133 * @return the initialization vector in a new buffer, or null if the
134 * underlying algorithm does not use an IV, or if the IV has not yet
135 * been set.
136 */
137 protected byte[] engineGetIV() {
138 return core.getIV();
139 }
140
141 /**
142 * Returns the parameters used with this cipher.
143 *
144 * <p>The returned parameters may be the same that were used to initialize
145 * this cipher, or may contain the default set of parameters or a set of
146 * randomly generated parameters used by the underlying cipher
147 * implementation (provided that the underlying cipher implementation
148 * uses a default set of parameters or creates new parameters if it needs
149 * parameters but was not initialized with any).
150 *
151 * @return the parameters used with this cipher, or null if this cipher
152 * does not use any parameters.
153 */
154 protected AlgorithmParameters engineGetParameters() {
155 return core.getParameters("AES");
156 }
157
158 /**
159 * Initializes this cipher with a key and a source of randomness.
160 *
161 * <p>The cipher is initialized for one of the following four operations:
162 * encryption, decryption, key wrapping or key unwrapping, depending on
163 * the value of <code>opmode</code>.
164 *
165 * <p>If this cipher requires an initialization vector (IV), it will get
166 * it from <code>random</code>.
167 * This behaviour should only be used in encryption or key wrapping
168 * mode, however.
169 * When initializing a cipher that requires an IV for decryption or
170 * key unwrapping, the IV
171 * (same IV that was used for encryption or key wrapping) must be provided
172 * explicitly as a
173 * parameter, in order to get the correct result.
174 *
175 * <p>This method also cleans existing buffer and other related state
176 * information.
177 *
178 * @param opmode the operation mode of this cipher (this is one of
179 * the following:
180 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
181 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
182 * @param key the secret key
183 * @param random the source of randomness
184 *
185 * @exception InvalidKeyException if the given key is inappropriate for
186 * initializing this cipher
187 */
188 protected void engineInit(int opmode, Key key, SecureRandom random)
189 throws InvalidKeyException {
190 core.init(opmode, key, random);
191 }
192
193 /**
194 * Initializes this cipher with a key, a set of
195 * algorithm parameters, and a source of randomness.
196 *
197 * <p>The cipher is initialized for one of the following four operations:
198 * encryption, decryption, key wrapping or key unwrapping, depending on
199 * the value of <code>opmode</code>.
200 *
201 * <p>If this cipher (including its underlying feedback or padding scheme)
202 * requires any random bytes, it will get them from <code>random</code>.
203 *
204 * @param opmode the operation mode of this cipher (this is one of
205 * the following:
206 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
207 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
208 * @param key the encryption key
209 * @param params the algorithm parameters
210 * @param random the source of randomness
211 *
212 * @exception InvalidKeyException if the given key is inappropriate for
213 * initializing this cipher
214 * @exception InvalidAlgorithmParameterException if the given algorithm
215 * parameters are inappropriate for this cipher
216 */
217 protected void engineInit(int opmode, Key key,
218 AlgorithmParameterSpec params,
219 SecureRandom random)
220 throws InvalidKeyException, InvalidAlgorithmParameterException {
221 core.init(opmode, key, params, random);
222 }
223
224 protected void engineInit(int opmode, Key key,
225 AlgorithmParameters params,
226 SecureRandom random)
227 throws InvalidKeyException, InvalidAlgorithmParameterException {
228 core.init(opmode, key, params, random);
229 }
230
231 /**
232 * Continues a multiple-part encryption or decryption operation
233 * (depending on how this cipher was initialized), processing another data
234 * part.
235 *
236 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
237 * buffer, starting at <code>inputOffset</code>, are processed, and the
238 * result is stored in a new buffer.
239 *
240 * @param input the input buffer
241 * @param inputOffset the offset in <code>input</code> where the input
242 * starts
243 * @param inputLen the input length
244 *
245 * @return the new buffer with the result
246 *
247 * @exception IllegalStateException if this cipher is in a wrong state
248 * (e.g., has not been initialized)
249 */
250 protected byte[] engineUpdate(byte[] input, int inputOffset,
251 int inputLen) {
252 return core.update(input, inputOffset, inputLen);
253 }
254
255 /**
256 * Continues a multiple-part encryption or decryption operation
257 * (depending on how this cipher was initialized), processing another data
258 * part.
259 *
260 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
261 * buffer, starting at <code>inputOffset</code>, are processed, and the
262 * result is stored in the <code>output</code> buffer, starting at
263 * <code>outputOffset</code>.
264 *
265 * @param input the input buffer
266 * @param inputOffset the offset in <code>input</code> where the input
267 * starts
268 * @param inputLen the input length
269 * @param output the buffer for the result
270 * @param outputOffset the offset in <code>output</code> where the result
271 * is stored
272 *
273 * @return the number of bytes stored in <code>output</code>
274 *
275 * @exception ShortBufferException if the given output buffer is too small
276 * to hold the result
277 */
278 protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
279 byte[] output, int outputOffset)
280 throws ShortBufferException {
281 return core.update(input, inputOffset, inputLen, output,
282 outputOffset);
283 }
284
285 /**
286 * Encrypts or decrypts data in a single-part operation,
287 * or finishes a multiple-part operation.
288 * The data is encrypted or decrypted, depending on how this cipher was
289 * initialized.
290 *
291 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
292 * buffer, starting at <code>inputOffset</code>, and any input bytes that
293 * may have been buffered during a previous <code>update</code> operation,
294 * are processed, with padding (if requested) being applied.
295 * The result is stored in a new buffer.
296 *
297 * <p>The cipher is reset to its initial state (uninitialized) after this
298 * call.
299 *
300 * @param input the input buffer
301 * @param inputOffset the offset in <code>input</code> where the input
302 * starts
303 * @param inputLen the input length
304 *
305 * @return the new buffer with the result
306 *
307 * @exception IllegalBlockSizeException if this cipher is a block cipher,
308 * no padding has been requested (only in encryption mode), and the total
309 * input length of the data processed by this cipher is not a multiple of
310 * block size
311 * @exception BadPaddingException if this cipher is in decryption mode,
312 * and (un)padding has been requested, but the decrypted data is not
313 * bounded by the appropriate padding bytes
314 */
315 protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
316 throws IllegalBlockSizeException, BadPaddingException {
317 return core.doFinal(input, inputOffset, inputLen);
318 }
319
320 /**
321 * Encrypts or decrypts data in a single-part operation,
322 * or finishes a multiple-part operation.
323 * The data is encrypted or decrypted, depending on how this cipher was
324 * initialized.
325 *
326 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
327 * buffer, starting at <code>inputOffset</code>, and any input bytes that
328 * may have been buffered during a previous <code>update</code> operation,
329 * are processed, with padding (if requested) being applied.
330 * The result is stored in the <code>output</code> buffer, starting at
331 * <code>outputOffset</code>.
332 *
333 * <p>The cipher is reset to its initial state (uninitialized) after this
334 * call.
335 *
336 * @param input the input buffer
337 * @param inputOffset the offset in <code>input</code> where the input
338 * starts
339 * @param inputLen the input length
340 * @param output the buffer for the result
341 * @param outputOffset the offset in <code>output</code> where the result
342 * is stored
343 *
344 * @return the number of bytes stored in <code>output</code>
345 *
346 * @exception IllegalBlockSizeException if this cipher is a block cipher,
347 * no padding has been requested (only in encryption mode), and the total
348 * input length of the data processed by this cipher is not a multiple of
349 * block size
350 * @exception ShortBufferException if the given output buffer is too small
351 * to hold the result
352 * @exception BadPaddingException if this cipher is in decryption mode,
353 * and (un)padding has been requested, but the decrypted data is not
354 * bounded by the appropriate padding bytes
355 */
356 protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
357 byte[] output, int outputOffset)
358 throws IllegalBlockSizeException, ShortBufferException,
359 BadPaddingException {
360 return core.doFinal(input, inputOffset, inputLen, output,
361 outputOffset);
362 }
363
364 /**
365 * Returns the key size of the given key object.
366 *
367 * @param key the key object.
368 *
369 * @return the key size of the given key object.
370 *
371 * @exception InvalidKeyException if <code>key</code> is invalid.
372 */
373 protected int engineGetKeySize(Key key) throws InvalidKeyException {
374 byte[] encoded = key.getEncoded();
375 if (!AESCrypt.isKeySizeValid(encoded.length)) {
376 throw new InvalidKeyException("Invalid AES key length: " +
377 encoded.length + " bytes");
378 }
379 return encoded.length * 8;
380 }
381
382 /**
383 * Wrap a key.
384 *
385 * @param key the key to be wrapped.
386 *
387 * @return the wrapped key.
388 *
389 * @exception IllegalBlockSizeException if this cipher is a block
390 * cipher, no padding has been requested, and the length of the
391 * encoding of the key to be wrapped is not a
392 * multiple of the block size.
393 *
394 * @exception InvalidKeyException if it is impossible or unsafe to
395 * wrap the key with this cipher (e.g., a hardware protected key is
396 * being passed to a software only cipher).
397 */
398 protected byte[] engineWrap(Key key)
399 throws IllegalBlockSizeException, InvalidKeyException {
400 return core.wrap(key);
401 }
402
403 /**
404 * Unwrap a previously wrapped key.
405 *
406 * @param wrappedKey the key to be unwrapped.
407 *
408 * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
409 *
410 * @param wrappedKeyType the type of the wrapped key.
411 * This is one of <code>Cipher.SECRET_KEY</code>,
412 * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
413 *
414 * @return the unwrapped key.
415 *
416 * @exception NoSuchAlgorithmException if no installed providers
417 * can create keys of type <code>wrappedKeyType</code> for the
418 * <code>wrappedKeyAlgorithm</code>.
419 *
420 * @exception InvalidKeyException if <code>wrappedKey</code> does not
421 * represent a wrapped key of type <code>wrappedKeyType</code> for
422 * the <code>wrappedKeyAlgorithm</code>.
423 */
424 protected Key engineUnwrap(byte[] wrappedKey,
425 String wrappedKeyAlgorithm,
426 int wrappedKeyType)
427 throws InvalidKeyException, NoSuchAlgorithmException {
428 return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
429 wrappedKeyType);
430 }
431}