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