blob: ce7258157d57e3d01bce14a4939941cf1a7c361a [file] [log] [blame]
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +00001/*
Sergio Giro5e0de5a2016-09-14 18:57:26 +01002 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +00003 * 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.crypto;
27
28import java.util.StringTokenizer;
29import java.util.NoSuchElementException;
30import java.security.AlgorithmParameters;
31import java.security.Provider;
32import java.security.Key;
33import java.security.SecureRandom;
34import java.security.NoSuchAlgorithmException;
35import java.security.NoSuchProviderException;
36import java.security.InvalidKeyException;
37import java.security.InvalidAlgorithmParameterException;
38import java.security.ProviderException;
39import java.security.spec.AlgorithmParameterSpec;
40
41import java.nio.ByteBuffer;
42
43/**
44 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
45 * for the <code>Cipher</code> class.
46 * All the abstract methods in this class must be implemented by each
47 * cryptographic service provider who wishes to supply the implementation
48 * of a particular cipher algorithm.
49 *
50 * <p>In order to create an instance of <code>Cipher</code>, which
51 * encapsulates an instance of this <code>CipherSpi</code> class, an
52 * application calls one of the
53 * {@link Cipher#getInstance(java.lang.String) getInstance}
54 * factory methods of the
55 * {@link Cipher Cipher} engine class and specifies the requested
56 * <i>transformation</i>.
57 * Optionally, the application may also specify the name of a provider.
58 *
59 * <p>A <i>transformation</i> is a string that describes the operation (or
60 * set of operations) to be performed on the given input, to produce some
61 * output. A transformation always includes the name of a cryptographic
62 * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
63 * padding scheme.
64 *
Sergio Giro5e0de5a2016-09-14 18:57:26 +010065 * <p> A transformation is of the form:
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +000066 *
67 * <ul>
68 * <li>"<i>algorithm/mode/padding</i>" or
Sergio Giro5e0de5a2016-09-14 18:57:26 +010069 *
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +000070 * <li>"<i>algorithm</i>"
71 * </ul>
72 *
73 * <P> (in the latter case,
74 * provider-specific default values for the mode and padding scheme are used).
Sergio Giro5e0de5a2016-09-14 18:57:26 +010075 * For example, the following is a valid transformation:
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +000076 *
77 * <pre>
78 * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
79 * </pre>
80 *
81 * <p>A provider may supply a separate class for each combination
82 * of <i>algorithm/mode/padding</i>, or may decide to provide more generic
83 * classes representing sub-transformations corresponding to
84 * <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
85 * (note the double slashes),
86 * in which case the requested mode and/or padding are set automatically by
87 * the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
88 * the {@link #engineSetMode(java.lang.String) engineSetMode} and
89 * {@link #engineSetPadding(java.lang.String) engineSetPadding}
90 * methods of the provider's subclass of <code>CipherSpi</code>.
91 *
92 * <p>A <code>Cipher</code> property in a provider master class may have one of
93 * the following formats:
94 *
95 * <ul>
96 *
97 * <li>
98 * <pre>
99 * // provider's subclass of "CipherSpi" implements "algName" with
100 * // pluggable mode and padding
101 * <code>Cipher.</code><i>algName</i>
102 * </pre>
103 *
104 * <li>
105 * <pre>
106 * // provider's subclass of "CipherSpi" implements "algName" in the
107 * // specified "mode", with pluggable padding
108 * <code>Cipher.</code><i>algName/mode</i>
109 * </pre>
110 *
111 * <li>
112 * <pre>
113 * // provider's subclass of "CipherSpi" implements "algName" with the
114 * // specified "padding", with pluggable mode
115 * <code>Cipher.</code><i>algName//padding</i>
116 * </pre>
117 *
118 * <li>
119 * <pre>
120 * // provider's subclass of "CipherSpi" implements "algName" with the
121 * // specified "mode" and "padding"
122 * <code>Cipher.</code><i>algName/mode/padding</i>
123 * </pre>
124 *
125 * </ul>
126 *
127 * <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
128 * that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
129 * <i>DES/CBC/PKCS5Padding</i>, one that implements
130 * <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
131 * <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100132 * <code>Cipher</code> properties in its master class:
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000133 *
134 * <ul>
135 *
136 * <li>
137 * <pre>
138 * <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
139 * </pre>
140 *
141 * <li>
142 * <pre>
143 * <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
144 * </pre>
145 *
146 * <li>
147 * <pre>
148 * <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
149 * </pre>
150 *
151 * <li>
152 * <pre>
153 * <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
154 * </pre>
155 *
156 * </ul>
157 *
158 * <p>Another provider may implement a class for each of the above modes
159 * (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
160 * and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
161 * and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
162 * That provider would have the following
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100163 * <code>Cipher</code> properties in its master class:
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000164 *
165 * <ul>
166 *
167 * <li>
168 * <pre>
169 * <code>Cipher.</code><i>DES</i>
170 * </pre>
171 *
172 * </ul>
173 *
174 * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
175 * engine class follows these rules in order to instantiate a provider's
176 * implementation of <code>CipherSpi</code> for a
177 * transformation of the form "<i>algorithm</i>":
178 *
179 * <ol>
180 * <li>
181 * Check if the provider has registered a subclass of <code>CipherSpi</code>
182 * for the specified "<i>algorithm</i>".
183 * <p>If the answer is YES, instantiate this
184 * class, for whose mode and padding scheme default values (as supplied by
185 * the provider) are used.
186 * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
187 * exception.
188 * </ol>
189 *
190 * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
191 * engine class follows these rules in order to instantiate a provider's
192 * implementation of <code>CipherSpi</code> for a
193 * transformation of the form "<i>algorithm/mode/padding</i>":
194 *
195 * <ol>
196 * <li>
197 * Check if the provider has registered a subclass of <code>CipherSpi</code>
198 * for the specified "<i>algorithm/mode/padding</i>" transformation.
199 * <p>If the answer is YES, instantiate it.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100200 * <p>If the answer is NO, go to the next step.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000201 * <li>
202 * Check if the provider has registered a subclass of <code>CipherSpi</code>
203 * for the sub-transformation "<i>algorithm/mode</i>".
204 * <p>If the answer is YES, instantiate it, and call
205 * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100206 * <p>If the answer is NO, go to the next step.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000207 * <li>
208 * Check if the provider has registered a subclass of <code>CipherSpi</code>
209 * for the sub-transformation "<i>algorithm//padding</i>" (note the double
210 * slashes).
211 * <p>If the answer is YES, instantiate it, and call
212 * <code>engineSetMode(<i>mode</i>)</code> on the new instance.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100213 * <p>If the answer is NO, go to the next step.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000214 * <li>
215 * Check if the provider has registered a subclass of <code>CipherSpi</code>
216 * for the sub-transformation "<i>algorithm</i>".
217 * <p>If the answer is YES, instantiate it, and call
218 * <code>engineSetMode(<i>mode</i>)</code> and
219 * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
220 * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
221 * exception.
222 * </ol>
223 *
224 * @author Jan Luehe
225 * @see KeyGenerator
226 * @see SecretKey
227 * @since 1.4
228 */
229
230public abstract class CipherSpi {
231
232 /**
233 * Sets the mode of this cipher.
234 *
235 * @param mode the cipher mode
236 *
237 * @exception NoSuchAlgorithmException if the requested cipher mode does
238 * not exist
239 */
240 protected abstract void engineSetMode(String mode)
241 throws NoSuchAlgorithmException;
242
243 /**
244 * Sets the padding mechanism of this cipher.
245 *
246 * @param padding the padding mechanism
247 *
248 * @exception NoSuchPaddingException if the requested padding mechanism
249 * does not exist
250 */
251 protected abstract void engineSetPadding(String padding)
252 throws NoSuchPaddingException;
253
254 /**
255 * Returns the block size (in bytes).
256 *
257 * @return the block size (in bytes), or 0 if the underlying algorithm is
258 * not a block cipher
259 */
260 protected abstract int engineGetBlockSize();
261
262 /**
263 * Returns the length in bytes that an output buffer would
264 * need to be in order to hold the result of the next <code>update</code>
265 * or <code>doFinal</code> operation, given the input length
266 * <code>inputLen</code> (in bytes).
267 *
268 * <p>This call takes into account any unprocessed (buffered) data from a
269 * previous <code>update</code> call, padding, and AEAD tagging.
270 *
271 * <p>The actual output length of the next <code>update</code> or
272 * <code>doFinal</code> call may be smaller than the length returned by
273 * this method.
274 *
275 * @param inputLen the input length (in bytes)
276 *
277 * @return the required output buffer size (in bytes)
278 */
279 protected abstract int engineGetOutputSize(int inputLen);
280
281 /**
282 * Returns the initialization vector (IV) in a new buffer.
283 *
284 * <p> This is useful in the context of password-based encryption or
285 * decryption, where the IV is derived from a user-provided passphrase.
286 *
287 * @return the initialization vector in a new buffer, or null if the
288 * underlying algorithm does not use an IV, or if the IV has not yet
289 * been set.
290 */
291 protected abstract byte[] engineGetIV();
292
293 /**
294 * Returns the parameters used with this cipher.
295 *
296 * <p>The returned parameters may be the same that were used to initialize
297 * this cipher, or may contain a combination of default and random
298 * parameter values used by the underlying cipher implementation if this
299 * cipher requires algorithm parameters but was not initialized with any.
300 *
301 * @return the parameters used with this cipher, or null if this cipher
302 * does not use any parameters.
303 */
304 protected abstract AlgorithmParameters engineGetParameters();
305
306 /**
307 * Initializes this cipher with a key and a source
308 * of randomness.
309 *
310 * <p>The cipher is initialized for one of the following four operations:
311 * encryption, decryption, key wrapping or key unwrapping, depending on
312 * the value of <code>opmode</code>.
313 *
314 * <p>If this cipher requires any algorithm parameters that cannot be
315 * derived from the given <code>key</code>, the underlying cipher
316 * implementation is supposed to generate the required parameters itself
317 * (using provider-specific default or random values) if it is being
318 * initialized for encryption or key wrapping, and raise an
319 * <code>InvalidKeyException</code> if it is being
320 * initialized for decryption or key unwrapping.
321 * The generated parameters can be retrieved using
322 * {@link #engineGetParameters() engineGetParameters} or
323 * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
324 *
325 * <p>If this cipher requires algorithm parameters that cannot be
326 * derived from the input parameters, and there are no reasonable
327 * provider-specific default values, initialization will
328 * necessarily fail.
329 *
330 * <p>If this cipher (including its underlying feedback or padding scheme)
331 * requires any random bytes (e.g., for parameter generation), it will get
332 * them from <code>random</code>.
333 *
334 * <p>Note that when a Cipher object is initialized, it loses all
335 * previously-acquired state. In other words, initializing a Cipher is
336 * equivalent to creating a new instance of that Cipher and initializing
337 * it.
338 *
339 * @param opmode the operation mode of this cipher (this is one of
340 * the following:
341 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
342 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
343 * @param key the encryption key
344 * @param random the source of randomness
345 *
346 * @exception InvalidKeyException if the given key is inappropriate for
347 * initializing this cipher, or requires
348 * algorithm parameters that cannot be
349 * determined from the given key.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100350 * @throws UnsupportedOperationException if {@code opmode} is
351 * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
352 * by the cipher.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000353 */
354 protected abstract void engineInit(int opmode, Key key,
355 SecureRandom random)
356 throws InvalidKeyException;
357
358 /**
359 * Initializes this cipher with a key, a set of
360 * algorithm parameters, and a source of randomness.
361 *
362 * <p>The cipher is initialized for one of the following four operations:
363 * encryption, decryption, key wrapping or key unwrapping, depending on
364 * the value of <code>opmode</code>.
365 *
366 * <p>If this cipher requires any algorithm parameters and
367 * <code>params</code> is null, the underlying cipher implementation is
368 * supposed to generate the required parameters itself (using
369 * provider-specific default or random values) if it is being
370 * initialized for encryption or key wrapping, and raise an
371 * <code>InvalidAlgorithmParameterException</code> if it is being
372 * initialized for decryption or key unwrapping.
373 * The generated parameters can be retrieved using
374 * {@link #engineGetParameters() engineGetParameters} or
375 * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
376 *
377 * <p>If this cipher requires algorithm parameters that cannot be
378 * derived from the input parameters, and there are no reasonable
379 * provider-specific default values, initialization will
380 * necessarily fail.
381 *
382 * <p>If this cipher (including its underlying feedback or padding scheme)
383 * requires any random bytes (e.g., for parameter generation), it will get
384 * them from <code>random</code>.
385 *
386 * <p>Note that when a Cipher object is initialized, it loses all
387 * previously-acquired state. In other words, initializing a Cipher is
388 * equivalent to creating a new instance of that Cipher and initializing
389 * it.
390 *
391 * @param opmode the operation mode of this cipher (this is one of
392 * the following:
393 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
394 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
395 * @param key the encryption key
396 * @param params the algorithm parameters
397 * @param random the source of randomness
398 *
399 * @exception InvalidKeyException if the given key is inappropriate for
400 * initializing this cipher
401 * @exception InvalidAlgorithmParameterException if the given algorithm
402 * parameters are inappropriate for this cipher,
403 * or if this cipher requires
404 * algorithm parameters and <code>params</code> is null.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100405 * @throws UnsupportedOperationException if {@code opmode} is
406 * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
407 * by the cipher.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000408 */
409 protected abstract void engineInit(int opmode, Key key,
410 AlgorithmParameterSpec params,
411 SecureRandom random)
412 throws InvalidKeyException, InvalidAlgorithmParameterException;
413
414 /**
415 * Initializes this cipher with a key, a set of
416 * algorithm parameters, and a source of randomness.
417 *
418 * <p>The cipher is initialized for one of the following four operations:
419 * encryption, decryption, key wrapping or key unwrapping, depending on
420 * the value of <code>opmode</code>.
421 *
422 * <p>If this cipher requires any algorithm parameters and
423 * <code>params</code> is null, the underlying cipher implementation is
424 * supposed to generate the required parameters itself (using
425 * provider-specific default or random values) if it is being
426 * initialized for encryption or key wrapping, and raise an
427 * <code>InvalidAlgorithmParameterException</code> if it is being
428 * initialized for decryption or key unwrapping.
429 * The generated parameters can be retrieved using
430 * {@link #engineGetParameters() engineGetParameters} or
431 * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
432 *
433 * <p>If this cipher requires algorithm parameters that cannot be
434 * derived from the input parameters, and there are no reasonable
435 * provider-specific default values, initialization will
436 * necessarily fail.
437 *
438 * <p>If this cipher (including its underlying feedback or padding scheme)
439 * requires any random bytes (e.g., for parameter generation), it will get
440 * them from <code>random</code>.
441 *
442 * <p>Note that when a Cipher object is initialized, it loses all
443 * previously-acquired state. In other words, initializing a Cipher is
444 * equivalent to creating a new instance of that Cipher and initializing
445 * it.
446 *
447 * @param opmode the operation mode of this cipher (this is one of
448 * the following:
449 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
450 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
451 * @param key the encryption key
452 * @param params the algorithm parameters
453 * @param random the source of randomness
454 *
455 * @exception InvalidKeyException if the given key is inappropriate for
456 * initializing this cipher
457 * @exception InvalidAlgorithmParameterException if the given algorithm
458 * parameters are inappropriate for this cipher,
459 * or if this cipher requires
460 * algorithm parameters and <code>params</code> is null.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100461 * @throws UnsupportedOperationException if {@code opmode} is
462 * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
463 * by the cipher.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000464 */
465 protected abstract void engineInit(int opmode, Key key,
466 AlgorithmParameters params,
467 SecureRandom random)
468 throws InvalidKeyException, InvalidAlgorithmParameterException;
469
470 /**
471 * Continues a multiple-part encryption or decryption operation
472 * (depending on how this cipher was initialized), processing another data
473 * part.
474 *
475 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
476 * buffer, starting at <code>inputOffset</code> inclusive, are processed,
477 * and the result is stored in a new buffer.
478 *
479 * @param input the input buffer
480 * @param inputOffset the offset in <code>input</code> where the input
481 * starts
482 * @param inputLen the input length
483 *
484 * @return the new buffer with the result, or null if the underlying
485 * cipher is a block cipher and the input data is too short to result in a
486 * new block.
487 */
488 protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
489 int inputLen);
490
491 /**
492 * Continues a multiple-part encryption or decryption operation
493 * (depending on how this cipher was initialized), processing another data
494 * part.
495 *
496 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
497 * buffer, starting at <code>inputOffset</code> inclusive, are processed,
498 * and the result is stored in the <code>output</code> buffer, starting at
499 * <code>outputOffset</code> inclusive.
500 *
501 * <p>If the <code>output</code> buffer is too small to hold the result,
502 * a <code>ShortBufferException</code> is thrown.
503 *
504 * @param input the input buffer
505 * @param inputOffset the offset in <code>input</code> where the input
506 * starts
507 * @param inputLen the input length
508 * @param output the buffer for the result
509 * @param outputOffset the offset in <code>output</code> where the result
510 * is stored
511 *
512 * @return the number of bytes stored in <code>output</code>
513 *
514 * @exception ShortBufferException if the given output buffer is too small
515 * to hold the result
516 */
517 protected abstract int engineUpdate(byte[] input, int inputOffset,
518 int inputLen, byte[] output,
519 int outputOffset)
520 throws ShortBufferException;
521
522 /**
523 * Continues a multiple-part encryption or decryption operation
524 * (depending on how this cipher was initialized), processing another data
525 * part.
526 *
527 * <p>All <code>input.remaining()</code> bytes starting at
528 * <code>input.position()</code> are processed. The result is stored
529 * in the output buffer.
530 * Upon return, the input buffer's position will be equal
531 * to its limit; its limit will not have changed. The output buffer's
532 * position will have advanced by n, where n is the value returned
533 * by this method; the output buffer's limit will not have changed.
534 *
535 * <p>If <code>output.remaining()</code> bytes are insufficient to
536 * hold the result, a <code>ShortBufferException</code> is thrown.
537 *
538 * <p>Subclasses should consider overriding this method if they can
539 * process ByteBuffers more efficiently than byte arrays.
540 *
541 * @param input the input ByteBuffer
542 * @param output the output ByteByffer
543 *
544 * @return the number of bytes stored in <code>output</code>
545 *
546 * @exception ShortBufferException if there is insufficient space in the
547 * output buffer
548 *
549 * @throws NullPointerException if either parameter is <CODE>null</CODE>
550 * @since 1.5
551 */
552 protected int engineUpdate(ByteBuffer input, ByteBuffer output)
553 throws ShortBufferException {
554 try {
555 return bufferCrypt(input, output, true);
556 } catch (IllegalBlockSizeException e) {
557 // never thrown for engineUpdate()
558 throw new ProviderException("Internal error in update()");
559 } catch (BadPaddingException e) {
560 // never thrown for engineUpdate()
561 throw new ProviderException("Internal error in update()");
562 }
563 }
564
565 /**
566 * Encrypts or decrypts data in a single-part operation,
567 * or finishes a multiple-part operation.
568 * The data is encrypted or decrypted, depending on how this cipher was
569 * initialized.
570 *
571 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
572 * buffer, starting at <code>inputOffset</code> inclusive, and any input
573 * bytes that may have been buffered during a previous <code>update</code>
574 * operation, are processed, with padding (if requested) being applied.
575 * If an AEAD mode such as GCM/CCM is being used, the authentication
576 * tag is appended in the case of encryption, or verified in the
577 * case of decryption.
578 * The result is stored in a new buffer.
579 *
580 * <p>Upon finishing, this method resets this cipher object to the state
581 * it was in when previously initialized via a call to
582 * <code>engineInit</code>.
583 * That is, the object is reset and available to encrypt or decrypt
584 * (depending on the operation mode that was specified in the call to
585 * <code>engineInit</code>) more data.
586 *
587 * <p>Note: if any exception is thrown, this cipher object may need to
588 * be reset before it can be used again.
589 *
590 * @param input the input buffer
591 * @param inputOffset the offset in <code>input</code> where the input
592 * starts
593 * @param inputLen the input length
594 *
595 * @return the new buffer with the result
596 *
597 * @exception IllegalBlockSizeException if this cipher is a block cipher,
598 * no padding has been requested (only in encryption mode), and the total
599 * input length of the data processed by this cipher is not a multiple of
600 * block size; or if this encryption algorithm is unable to
601 * process the input data provided.
602 * @exception BadPaddingException if this cipher is in decryption mode,
603 * and (un)padding has been requested, but the decrypted data is not
604 * bounded by the appropriate padding bytes
605 * @exception AEADBadTagException if this cipher is decrypting in an
606 * AEAD mode (such as GCM/CCM), and the received authentication tag
607 * does not match the calculated value
608 */
609 protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
610 int inputLen)
611 throws IllegalBlockSizeException, BadPaddingException;
612
613 /**
614 * Encrypts or decrypts data in a single-part operation,
615 * or finishes a multiple-part operation.
616 * The data is encrypted or decrypted, depending on how this cipher was
617 * initialized.
618 *
619 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
620 * buffer, starting at <code>inputOffset</code> inclusive, and any input
621 * bytes that may have been buffered during a previous <code>update</code>
622 * operation, are processed, with padding (if requested) being applied.
623 * If an AEAD mode such as GCM/CCM is being used, the authentication
624 * tag is appended in the case of encryption, or verified in the
625 * case of decryption.
626 * The result is stored in the <code>output</code> buffer, starting at
627 * <code>outputOffset</code> inclusive.
628 *
629 * <p>If the <code>output</code> buffer is too small to hold the result,
630 * a <code>ShortBufferException</code> is thrown.
631 *
632 * <p>Upon finishing, this method resets this cipher object to the state
633 * it was in when previously initialized via a call to
634 * <code>engineInit</code>.
635 * That is, the object is reset and available to encrypt or decrypt
636 * (depending on the operation mode that was specified in the call to
637 * <code>engineInit</code>) more data.
638 *
639 * <p>Note: if any exception is thrown, this cipher object may need to
640 * be reset before it can be used again.
641 *
642 * @param input the input buffer
643 * @param inputOffset the offset in <code>input</code> where the input
644 * starts
645 * @param inputLen the input length
646 * @param output the buffer for the result
647 * @param outputOffset the offset in <code>output</code> where the result
648 * is stored
649 *
650 * @return the number of bytes stored in <code>output</code>
651 *
652 * @exception IllegalBlockSizeException if this cipher is a block cipher,
653 * no padding has been requested (only in encryption mode), and the total
654 * input length of the data processed by this cipher is not a multiple of
655 * block size; or if this encryption algorithm is unable to
656 * process the input data provided.
657 * @exception ShortBufferException if the given output buffer is too small
658 * to hold the result
659 * @exception BadPaddingException if this cipher is in decryption mode,
660 * and (un)padding has been requested, but the decrypted data is not
661 * bounded by the appropriate padding bytes
662 * @exception AEADBadTagException if this cipher is decrypting in an
663 * AEAD mode (such as GCM/CCM), and the received authentication tag
664 * does not match the calculated value
665 */
666 protected abstract int engineDoFinal(byte[] input, int inputOffset,
667 int inputLen, byte[] output,
668 int outputOffset)
669 throws ShortBufferException, IllegalBlockSizeException,
670 BadPaddingException;
671
672 /**
673 * Encrypts or decrypts data in a single-part operation,
674 * or finishes a multiple-part operation.
675 * The data is encrypted or decrypted, depending on how this cipher was
676 * initialized.
677 *
678 * <p>All <code>input.remaining()</code> bytes starting at
679 * <code>input.position()</code> are processed.
680 * If an AEAD mode such as GCM/CCM is being used, the authentication
681 * tag is appended in the case of encryption, or verified in the
682 * case of decryption.
683 * The result is stored in the output buffer.
684 * Upon return, the input buffer's position will be equal
685 * to its limit; its limit will not have changed. The output buffer's
686 * position will have advanced by n, where n is the value returned
687 * by this method; the output buffer's limit will not have changed.
688 *
689 * <p>If <code>output.remaining()</code> bytes are insufficient to
690 * hold the result, a <code>ShortBufferException</code> is thrown.
691 *
692 * <p>Upon finishing, this method resets this cipher object to the state
693 * it was in when previously initialized via a call to
694 * <code>engineInit</code>.
695 * That is, the object is reset and available to encrypt or decrypt
696 * (depending on the operation mode that was specified in the call to
697 * <code>engineInit</code>) more data.
698 *
699 * <p>Note: if any exception is thrown, this cipher object may need to
700 * be reset before it can be used again.
701 *
702 * <p>Subclasses should consider overriding this method if they can
703 * process ByteBuffers more efficiently than byte arrays.
704 *
705 * @param input the input ByteBuffer
706 * @param output the output ByteByffer
707 *
708 * @return the number of bytes stored in <code>output</code>
709 *
710 * @exception IllegalBlockSizeException if this cipher is a block cipher,
711 * no padding has been requested (only in encryption mode), and the total
712 * input length of the data processed by this cipher is not a multiple of
713 * block size; or if this encryption algorithm is unable to
714 * process the input data provided.
715 * @exception ShortBufferException if there is insufficient space in the
716 * output buffer
717 * @exception BadPaddingException if this cipher is in decryption mode,
718 * and (un)padding has been requested, but the decrypted data is not
719 * bounded by the appropriate padding bytes
720 * @exception AEADBadTagException if this cipher is decrypting in an
721 * AEAD mode (such as GCM/CCM), and the received authentication tag
722 * does not match the calculated value
723 *
724 * @throws NullPointerException if either parameter is <CODE>null</CODE>
725 * @since 1.5
726 */
727 protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
728 throws ShortBufferException, IllegalBlockSizeException,
729 BadPaddingException {
730 return bufferCrypt(input, output, false);
731 }
732
733 // copied from sun.security.jca.JCAUtil
734 // will be changed to reference that method once that code has been
735 // integrated and promoted
736 static int getTempArraySize(int totalSize) {
737 return Math.min(4096, totalSize);
738 }
739
740 /**
741 * Implementation for encryption using ByteBuffers. Used for both
742 * engineUpdate() and engineDoFinal().
743 */
744 private int bufferCrypt(ByteBuffer input, ByteBuffer output,
745 boolean isUpdate) throws ShortBufferException,
746 IllegalBlockSizeException, BadPaddingException {
747 if ((input == null) || (output == null)) {
748 throw new NullPointerException
749 ("Input and output buffers must not be null");
750 }
751 int inPos = input.position();
752 int inLimit = input.limit();
753 int inLen = inLimit - inPos;
754 if (isUpdate && (inLen == 0)) {
755 return 0;
756 }
757 int outLenNeeded = engineGetOutputSize(inLen);
758 if (output.remaining() < outLenNeeded) {
759 throw new ShortBufferException("Need at least " + outLenNeeded
760 + " bytes of space in output buffer");
761 }
762
763 boolean a1 = input.hasArray();
764 boolean a2 = output.hasArray();
765
766 if (a1 && a2) {
767 byte[] inArray = input.array();
768 int inOfs = input.arrayOffset() + inPos;
769 byte[] outArray = output.array();
770 int outPos = output.position();
771 int outOfs = output.arrayOffset() + outPos;
772 int n;
773 if (isUpdate) {
774 n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
775 } else {
776 n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
777 }
778 input.position(inLimit);
779 output.position(outPos + n);
780 return n;
781 } else if (!a1 && a2) {
782 int outPos = output.position();
783 byte[] outArray = output.array();
784 int outOfs = output.arrayOffset() + outPos;
785 byte[] inArray = new byte[getTempArraySize(inLen)];
786 int total = 0;
787 do {
788 int chunk = Math.min(inLen, inArray.length);
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100789 if (chunk > 0) {
790 input.get(inArray, 0, chunk);
791 }
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000792 int n;
793 if (isUpdate || (inLen != chunk)) {
794 n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
795 } else {
796 n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
797 }
798 total += n;
799 outOfs += n;
800 inLen -= chunk;
801 } while (inLen > 0);
802 output.position(outPos + total);
803 return total;
804 } else { // output is not backed by an accessible byte[]
805 byte[] inArray;
806 int inOfs;
807 if (a1) {
808 inArray = input.array();
809 inOfs = input.arrayOffset() + inPos;
810 } else {
811 inArray = new byte[getTempArraySize(inLen)];
812 inOfs = 0;
813 }
814 byte[] outArray = new byte[getTempArraySize(outLenNeeded)];
815 int outSize = outArray.length;
816 int total = 0;
817 boolean resized = false;
818 do {
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100819 int chunk =
820 Math.min(inLen, (outSize == 0? inArray.length : outSize));
821 if (!a1 && !resized && chunk > 0) {
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000822 input.get(inArray, 0, chunk);
823 inOfs = 0;
824 }
825 try {
826 int n;
827 if (isUpdate || (inLen != chunk)) {
828 n = engineUpdate(inArray, inOfs, chunk, outArray, 0);
829 } else {
830 n = engineDoFinal(inArray, inOfs, chunk, outArray, 0);
831 }
832 resized = false;
833 inOfs += chunk;
834 inLen -= chunk;
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100835 if (n > 0) {
836 output.put(outArray, 0, n);
837 total += n;
838 }
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000839 } catch (ShortBufferException e) {
840 if (resized) {
841 // we just resized the output buffer, but it still
842 // did not work. Bug in the provider, abort
843 throw (ProviderException)new ProviderException
844 ("Could not determine buffer size").initCause(e);
845 }
846 // output buffer is too small, realloc and try again
847 resized = true;
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100848 outSize = engineGetOutputSize(chunk);
849 outArray = new byte[outSize];
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000850 }
851 } while (inLen > 0);
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100852 if (a1) {
853 input.position(inLimit);
854 }
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000855 return total;
856 }
857 }
858
859 /**
860 * Wrap a key.
861 *
862 * <p>This concrete method has been added to this previously-defined
863 * abstract class. (For backwards compatibility, it cannot be abstract.)
864 * It may be overridden by a provider to wrap a key.
865 * Such an override is expected to throw an IllegalBlockSizeException or
866 * InvalidKeyException (under the specified circumstances),
867 * if the given key cannot be wrapped.
868 * If this method is not overridden, it always throws an
869 * UnsupportedOperationException.
870 *
871 * @param key the key to be wrapped.
872 *
873 * @return the wrapped key.
874 *
875 * @exception IllegalBlockSizeException if this cipher is a block cipher,
876 * no padding has been requested, and the length of the encoding of the
877 * key to be wrapped is not a multiple of the block size.
878 *
879 * @exception InvalidKeyException if it is impossible or unsafe to
880 * wrap the key with this cipher (e.g., a hardware protected key is
881 * being passed to a software-only cipher).
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100882 *
883 * @throws UnsupportedOperationException if this method is not supported.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000884 */
885 protected byte[] engineWrap(Key key)
886 throws IllegalBlockSizeException, InvalidKeyException
887 {
888 throw new UnsupportedOperationException();
889 }
890
891 /**
892 * Unwrap a previously wrapped key.
893 *
894 * <p>This concrete method has been added to this previously-defined
895 * abstract class. (For backwards compatibility, it cannot be abstract.)
896 * It may be overridden by a provider to unwrap a previously wrapped key.
897 * Such an override is expected to throw an InvalidKeyException if
898 * the given wrapped key cannot be unwrapped.
899 * If this method is not overridden, it always throws an
900 * UnsupportedOperationException.
901 *
902 * @param wrappedKey the key to be unwrapped.
903 *
904 * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
905 * key.
906 *
907 * @param wrappedKeyType the type of the wrapped key. This is one of
908 * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
909 * <code>PUBLIC_KEY</code>.
910 *
911 * @return the unwrapped key.
912 *
913 * @exception NoSuchAlgorithmException if no installed providers
914 * can create keys of type <code>wrappedKeyType</code> for the
915 * <code>wrappedKeyAlgorithm</code>.
916 *
917 * @exception InvalidKeyException if <code>wrappedKey</code> does not
918 * represent a wrapped key of type <code>wrappedKeyType</code> for
919 * the <code>wrappedKeyAlgorithm</code>.
Sergio Giro5e0de5a2016-09-14 18:57:26 +0100920 *
921 * @throws UnsupportedOperationException if this method is not supported.
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +0000922 */
923 protected Key engineUnwrap(byte[] wrappedKey,
924 String wrappedKeyAlgorithm,
925 int wrappedKeyType)
926 throws InvalidKeyException, NoSuchAlgorithmException
927 {
928 throw new UnsupportedOperationException();
929 }
930
931 /**
932 * Returns the key size of the given key object in bits.
933 * <p>This concrete method has been added to this previously-defined
934 * abstract class. It throws an <code>UnsupportedOperationException</code>
935 * if it is not overridden by the provider.
936 *
937 * @param key the key object.
938 *
939 * @return the key size of the given key object.
940 *
941 * @exception InvalidKeyException if <code>key</code> is invalid.
942 */
943 protected int engineGetKeySize(Key key)
944 throws InvalidKeyException
945 {
946 throw new UnsupportedOperationException();
947 }
948
949 /**
950 * Continues a multi-part update of the Additional Authentication
951 * Data (AAD), using a subset of the provided buffer.
952 * <p>
953 * Calls to this method provide AAD to the cipher when operating in
954 * modes such as AEAD (GCM/CCM). If this cipher is operating in
955 * either GCM or CCM mode, all AAD must be supplied before beginning
956 * operations on the ciphertext (via the {@code update} and {@code
957 * doFinal} methods).
958 *
959 * @param src the buffer containing the AAD
960 * @param offset the offset in {@code src} where the AAD input starts
961 * @param len the number of AAD bytes
962 *
963 * @throws IllegalStateException if this cipher is in a wrong state
964 * (e.g., has not been initialized), does not accept AAD, or if
965 * operating in either GCM or CCM mode and one of the {@code update}
966 * methods has already been called for the active
967 * encryption/decryption operation
968 * @throws UnsupportedOperationException if this method
969 * has not been overridden by an implementation
970 *
971 * @since 1.7
972 */
973 protected void engineUpdateAAD(byte[] src, int offset, int len) {
974 throw new UnsupportedOperationException(
975 "The underlying Cipher implementation "
976 + "does not support this method");
977 }
978
979 /**
980 * Continues a multi-part update of the Additional Authentication
981 * Data (AAD).
982 * <p>
983 * Calls to this method provide AAD to the cipher when operating in
984 * modes such as AEAD (GCM/CCM). If this cipher is operating in
985 * either GCM or CCM mode, all AAD must be supplied before beginning
986 * operations on the ciphertext (via the {@code update} and {@code
987 * doFinal} methods).
988 * <p>
989 * All {@code src.remaining()} bytes starting at
990 * {@code src.position()} are processed.
991 * Upon return, the input buffer's position will be equal
992 * to its limit; its limit will not have changed.
993 *
994 * @param src the buffer containing the AAD
995 *
996 * @throws IllegalStateException if this cipher is in a wrong state
997 * (e.g., has not been initialized), does not accept AAD, or if
998 * operating in either GCM or CCM mode and one of the {@code update}
999 * methods has already been called for the active
1000 * encryption/decryption operation
1001 * @throws UnsupportedOperationException if this method
1002 * has not been overridden by an implementation
1003 *
1004 * @since 1.7
1005 */
1006 protected void engineUpdateAAD(ByteBuffer src) {
1007 throw new UnsupportedOperationException(
1008 "The underlying Cipher implementation "
1009 + "does not support this method");
1010 }
1011}