History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/CipherSpi.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/crypto/CipherSpi.java+991−0
@@ -0,0 +1,991 @@
1+/*
2+ * Copyright (c) 1997, 2011, 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+/**
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+ *
65+ * <p> A transformation is of the form:<p>
66+ *
67+ * <ul>
68+ * <li>"<i>algorithm/mode/padding</i>" or
69+ * <p>
70+ * <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).
75+ * For example, the following is a valid transformation:<p>
76+ *
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
132+ * <code>Cipher</code> properties in its master class:<p>
133+ *
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
163+ * <code>Cipher</code> properties in its master class:<p>
164+ *
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.
200+ * <p>If the answer is NO, go to the next step.<p>
201+ * <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.
206+ * <p>If the answer is NO, go to the next step.<p>
207+ * <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.
213+ * <p>If the answer is NO, go to the next step.<p>
214+ * <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+
230+public 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.
350+ */
351+ protected abstract void engineInit(int opmode, Key key,
352+ SecureRandom random)
353+ throws InvalidKeyException;
354+
355+ /**
356+ * Initializes this cipher with a key, a set of
357+ * algorithm parameters, and a source of randomness.
358+ *
359+ * <p>The cipher is initialized for one of the following four operations:
360+ * encryption, decryption, key wrapping or key unwrapping, depending on
361+ * the value of <code>opmode</code>.
362+ *
363+ * <p>If this cipher requires any algorithm parameters and
364+ * <code>params</code> is null, the underlying cipher implementation is
365+ * supposed to generate the required parameters itself (using
366+ * provider-specific default or random values) if it is being
367+ * initialized for encryption or key wrapping, and raise an
368+ * <code>InvalidAlgorithmParameterException</code> if it is being
369+ * initialized for decryption or key unwrapping.
370+ * The generated parameters can be retrieved using
371+ * {@link #engineGetParameters() engineGetParameters} or
372+ * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
373+ *
374+ * <p>If this cipher requires algorithm parameters that cannot be
375+ * derived from the input parameters, and there are no reasonable
376+ * provider-specific default values, initialization will
377+ * necessarily fail.
378+ *
379+ * <p>If this cipher (including its underlying feedback or padding scheme)
380+ * requires any random bytes (e.g., for parameter generation), it will get
381+ * them from <code>random</code>.
382+ *
383+ * <p>Note that when a Cipher object is initialized, it loses all
384+ * previously-acquired state. In other words, initializing a Cipher is
385+ * equivalent to creating a new instance of that Cipher and initializing
386+ * it.
387+ *
388+ * @param opmode the operation mode of this cipher (this is one of
389+ * the following:
390+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
391+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
392+ * @param key the encryption key
393+ * @param params the algorithm parameters
394+ * @param random the source of randomness
395+ *
396+ * @exception InvalidKeyException if the given key is inappropriate for
397+ * initializing this cipher
398+ * @exception InvalidAlgorithmParameterException if the given algorithm
399+ * parameters are inappropriate for this cipher,
400+ * or if this cipher requires
401+ * algorithm parameters and <code>params</code> is null.
402+ */
403+ protected abstract void engineInit(int opmode, Key key,
404+ AlgorithmParameterSpec params,
405+ SecureRandom random)
406+ throws InvalidKeyException, InvalidAlgorithmParameterException;
407+
408+ /**
409+ * Initializes this cipher with a key, a set of
410+ * algorithm parameters, and a source of randomness.
411+ *
412+ * <p>The cipher is initialized for one of the following four operations:
413+ * encryption, decryption, key wrapping or key unwrapping, depending on
414+ * the value of <code>opmode</code>.
415+ *
416+ * <p>If this cipher requires any algorithm parameters and
417+ * <code>params</code> is null, the underlying cipher implementation is
418+ * supposed to generate the required parameters itself (using
419+ * provider-specific default or random values) if it is being
420+ * initialized for encryption or key wrapping, and raise an
421+ * <code>InvalidAlgorithmParameterException</code> if it is being
422+ * initialized for decryption or key unwrapping.
423+ * The generated parameters can be retrieved using
424+ * {@link #engineGetParameters() engineGetParameters} or
425+ * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
426+ *
427+ * <p>If this cipher requires algorithm parameters that cannot be
428+ * derived from the input parameters, and there are no reasonable
429+ * provider-specific default values, initialization will
430+ * necessarily fail.
431+ *
432+ * <p>If this cipher (including its underlying feedback or padding scheme)
433+ * requires any random bytes (e.g., for parameter generation), it will get
434+ * them from <code>random</code>.
435+ *
436+ * <p>Note that when a Cipher object is initialized, it loses all
437+ * previously-acquired state. In other words, initializing a Cipher is
438+ * equivalent to creating a new instance of that Cipher and initializing
439+ * it.
440+ *
441+ * @param opmode the operation mode of this cipher (this is one of
442+ * the following:
443+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
444+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
445+ * @param key the encryption key
446+ * @param params the algorithm parameters
447+ * @param random the source of randomness
448+ *
449+ * @exception InvalidKeyException if the given key is inappropriate for
450+ * initializing this cipher
451+ * @exception InvalidAlgorithmParameterException if the given algorithm
452+ * parameters are inappropriate for this cipher,
453+ * or if this cipher requires
454+ * algorithm parameters and <code>params</code> is null.
455+ */
456+ protected abstract void engineInit(int opmode, Key key,
457+ AlgorithmParameters params,
458+ SecureRandom random)
459+ throws InvalidKeyException, InvalidAlgorithmParameterException;
460+
461+ /**
462+ * Continues a multiple-part encryption or decryption operation
463+ * (depending on how this cipher was initialized), processing another data
464+ * part.
465+ *
466+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
467+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
468+ * and the result is stored in a new buffer.
469+ *
470+ * @param input the input buffer
471+ * @param inputOffset the offset in <code>input</code> where the input
472+ * starts
473+ * @param inputLen the input length
474+ *
475+ * @return the new buffer with the result, or null if the underlying
476+ * cipher is a block cipher and the input data is too short to result in a
477+ * new block.
478+ */
479+ protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
480+ int inputLen);
481+
482+ /**
483+ * Continues a multiple-part encryption or decryption operation
484+ * (depending on how this cipher was initialized), processing another data
485+ * part.
486+ *
487+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
488+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
489+ * and the result is stored in the <code>output</code> buffer, starting at
490+ * <code>outputOffset</code> inclusive.
491+ *
492+ * <p>If the <code>output</code> buffer is too small to hold the result,
493+ * a <code>ShortBufferException</code> is thrown.
494+ *
495+ * @param input the input buffer
496+ * @param inputOffset the offset in <code>input</code> where the input
497+ * starts
498+ * @param inputLen the input length
499+ * @param output the buffer for the result
500+ * @param outputOffset the offset in <code>output</code> where the result
501+ * is stored
502+ *
503+ * @return the number of bytes stored in <code>output</code>
504+ *
505+ * @exception ShortBufferException if the given output buffer is too small
506+ * to hold the result
507+ */
508+ protected abstract int engineUpdate(byte[] input, int inputOffset,
509+ int inputLen, byte[] output,
510+ int outputOffset)
511+ throws ShortBufferException;
512+
513+ /**
514+ * Continues a multiple-part encryption or decryption operation
515+ * (depending on how this cipher was initialized), processing another data
516+ * part.
517+ *
518+ * <p>All <code>input.remaining()</code> bytes starting at
519+ * <code>input.position()</code> are processed. The result is stored
520+ * in the output buffer.
521+ * Upon return, the input buffer's position will be equal
522+ * to its limit; its limit will not have changed. The output buffer's
523+ * position will have advanced by n, where n is the value returned
524+ * by this method; the output buffer's limit will not have changed.
525+ *
526+ * <p>If <code>output.remaining()</code> bytes are insufficient to
527+ * hold the result, a <code>ShortBufferException</code> is thrown.
528+ *
529+ * <p>Subclasses should consider overriding this method if they can
530+ * process ByteBuffers more efficiently than byte arrays.
531+ *
532+ * @param input the input ByteBuffer
533+ * @param output the output ByteByffer
534+ *
535+ * @return the number of bytes stored in <code>output</code>
536+ *
537+ * @exception ShortBufferException if there is insufficient space in the
538+ * output buffer
539+ *
540+ * @throws NullPointerException if either parameter is <CODE>null</CODE>
541+ * @since 1.5
542+ */
543+ protected int engineUpdate(ByteBuffer input, ByteBuffer output)
544+ throws ShortBufferException {
545+ try {
546+ return bufferCrypt(input, output, true);
547+ } catch (IllegalBlockSizeException e) {
548+ // never thrown for engineUpdate()
549+ throw new ProviderException("Internal error in update()");
550+ } catch (BadPaddingException e) {
551+ // never thrown for engineUpdate()
552+ throw new ProviderException("Internal error in update()");
553+ }
554+ }
555+
556+ /**
557+ * Encrypts or decrypts data in a single-part operation,
558+ * or finishes a multiple-part operation.
559+ * The data is encrypted or decrypted, depending on how this cipher was
560+ * initialized.
561+ *
562+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
563+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
564+ * bytes that may have been buffered during a previous <code>update</code>
565+ * operation, are processed, with padding (if requested) being applied.
566+ * If an AEAD mode such as GCM/CCM is being used, the authentication
567+ * tag is appended in the case of encryption, or verified in the
568+ * case of decryption.
569+ * The result is stored in a new buffer.
570+ *
571+ * <p>Upon finishing, this method resets this cipher object to the state
572+ * it was in when previously initialized via a call to
573+ * <code>engineInit</code>.
574+ * That is, the object is reset and available to encrypt or decrypt
575+ * (depending on the operation mode that was specified in the call to
576+ * <code>engineInit</code>) more data.
577+ *
578+ * <p>Note: if any exception is thrown, this cipher object may need to
579+ * be reset before it can be used again.
580+ *
581+ * @param input the input buffer
582+ * @param inputOffset the offset in <code>input</code> where the input
583+ * starts
584+ * @param inputLen the input length
585+ *
586+ * @return the new buffer with the result
587+ *
588+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
589+ * no padding has been requested (only in encryption mode), and the total
590+ * input length of the data processed by this cipher is not a multiple of
591+ * block size; or if this encryption algorithm is unable to
592+ * process the input data provided.
593+ * @exception BadPaddingException if this cipher is in decryption mode,
594+ * and (un)padding has been requested, but the decrypted data is not
595+ * bounded by the appropriate padding bytes
596+ * @exception AEADBadTagException if this cipher is decrypting in an
597+ * AEAD mode (such as GCM/CCM), and the received authentication tag
598+ * does not match the calculated value
599+ */
600+ protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
601+ int inputLen)
602+ throws IllegalBlockSizeException, BadPaddingException;
603+
604+ /**
605+ * Encrypts or decrypts data in a single-part operation,
606+ * or finishes a multiple-part operation.
607+ * The data is encrypted or decrypted, depending on how this cipher was
608+ * initialized.
609+ *
610+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
611+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
612+ * bytes that may have been buffered during a previous <code>update</code>
613+ * operation, are processed, with padding (if requested) being applied.
614+ * If an AEAD mode such as GCM/CCM is being used, the authentication
615+ * tag is appended in the case of encryption, or verified in the
616+ * case of decryption.
617+ * The result is stored in the <code>output</code> buffer, starting at
618+ * <code>outputOffset</code> inclusive.
619+ *
620+ * <p>If the <code>output</code> buffer is too small to hold the result,
621+ * a <code>ShortBufferException</code> is thrown.
622+ *
623+ * <p>Upon finishing, this method resets this cipher object to the state
624+ * it was in when previously initialized via a call to
625+ * <code>engineInit</code>.
626+ * That is, the object is reset and available to encrypt or decrypt
627+ * (depending on the operation mode that was specified in the call to
628+ * <code>engineInit</code>) more data.
629+ *
630+ * <p>Note: if any exception is thrown, this cipher object may need to
631+ * be reset before it can be used again.
632+ *
633+ * @param input the input buffer
634+ * @param inputOffset the offset in <code>input</code> where the input
635+ * starts
636+ * @param inputLen the input length
637+ * @param output the buffer for the result
638+ * @param outputOffset the offset in <code>output</code> where the result
639+ * is stored
640+ *
641+ * @return the number of bytes stored in <code>output</code>
642+ *
643+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
644+ * no padding has been requested (only in encryption mode), and the total
645+ * input length of the data processed by this cipher is not a multiple of
646+ * block size; or if this encryption algorithm is unable to
647+ * process the input data provided.
648+ * @exception ShortBufferException if the given output buffer is too small
649+ * to hold the result
650+ * @exception BadPaddingException if this cipher is in decryption mode,
651+ * and (un)padding has been requested, but the decrypted data is not
652+ * bounded by the appropriate padding bytes
653+ * @exception AEADBadTagException if this cipher is decrypting in an
654+ * AEAD mode (such as GCM/CCM), and the received authentication tag
655+ * does not match the calculated value
656+ */
657+ protected abstract int engineDoFinal(byte[] input, int inputOffset,
658+ int inputLen, byte[] output,
659+ int outputOffset)
660+ throws ShortBufferException, IllegalBlockSizeException,
661+ BadPaddingException;
662+
663+ /**
664+ * Encrypts or decrypts data in a single-part operation,
665+ * or finishes a multiple-part operation.
666+ * The data is encrypted or decrypted, depending on how this cipher was
667+ * initialized.
668+ *
669+ * <p>All <code>input.remaining()</code> bytes starting at
670+ * <code>input.position()</code> are processed.
671+ * If an AEAD mode such as GCM/CCM is being used, the authentication
672+ * tag is appended in the case of encryption, or verified in the
673+ * case of decryption.
674+ * The result is stored in the output buffer.
675+ * Upon return, the input buffer's position will be equal
676+ * to its limit; its limit will not have changed. The output buffer's
677+ * position will have advanced by n, where n is the value returned
678+ * by this method; the output buffer's limit will not have changed.
679+ *
680+ * <p>If <code>output.remaining()</code> bytes are insufficient to
681+ * hold the result, a <code>ShortBufferException</code> is thrown.
682+ *
683+ * <p>Upon finishing, this method resets this cipher object to the state
684+ * it was in when previously initialized via a call to
685+ * <code>engineInit</code>.
686+ * That is, the object is reset and available to encrypt or decrypt
687+ * (depending on the operation mode that was specified in the call to
688+ * <code>engineInit</code>) more data.
689+ *
690+ * <p>Note: if any exception is thrown, this cipher object may need to
691+ * be reset before it can be used again.
692+ *
693+ * <p>Subclasses should consider overriding this method if they can
694+ * process ByteBuffers more efficiently than byte arrays.
695+ *
696+ * @param input the input ByteBuffer
697+ * @param output the output ByteByffer
698+ *
699+ * @return the number of bytes stored in <code>output</code>
700+ *
701+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
702+ * no padding has been requested (only in encryption mode), and the total
703+ * input length of the data processed by this cipher is not a multiple of
704+ * block size; or if this encryption algorithm is unable to
705+ * process the input data provided.
706+ * @exception ShortBufferException if there is insufficient space in the
707+ * output buffer
708+ * @exception BadPaddingException if this cipher is in decryption mode,
709+ * and (un)padding has been requested, but the decrypted data is not
710+ * bounded by the appropriate padding bytes
711+ * @exception AEADBadTagException if this cipher is decrypting in an
712+ * AEAD mode (such as GCM/CCM), and the received authentication tag
713+ * does not match the calculated value
714+ *
715+ * @throws NullPointerException if either parameter is <CODE>null</CODE>
716+ * @since 1.5
717+ */
718+ protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
719+ throws ShortBufferException, IllegalBlockSizeException,
720+ BadPaddingException {
721+ return bufferCrypt(input, output, false);
722+ }
723+
724+ // copied from sun.security.jca.JCAUtil
725+ // will be changed to reference that method once that code has been
726+ // integrated and promoted
727+ static int getTempArraySize(int totalSize) {
728+ return Math.min(4096, totalSize);
729+ }
730+
731+ /**
732+ * Implementation for encryption using ByteBuffers. Used for both
733+ * engineUpdate() and engineDoFinal().
734+ */
735+ private int bufferCrypt(ByteBuffer input, ByteBuffer output,
736+ boolean isUpdate) throws ShortBufferException,
737+ IllegalBlockSizeException, BadPaddingException {
738+ if ((input == null) || (output == null)) {
739+ throw new NullPointerException
740+ ("Input and output buffers must not be null");
741+ }
742+ int inPos = input.position();
743+ int inLimit = input.limit();
744+ int inLen = inLimit - inPos;
745+ if (isUpdate && (inLen == 0)) {
746+ return 0;
747+ }
748+ int outLenNeeded = engineGetOutputSize(inLen);
749+ if (output.remaining() < outLenNeeded) {
750+ throw new ShortBufferException("Need at least " + outLenNeeded
751+ + " bytes of space in output buffer");
752+ }
753+
754+ boolean a1 = input.hasArray();
755+ boolean a2 = output.hasArray();
756+
757+ if (a1 && a2) {
758+ byte[] inArray = input.array();
759+ int inOfs = input.arrayOffset() + inPos;
760+ byte[] outArray = output.array();
761+ int outPos = output.position();
762+ int outOfs = output.arrayOffset() + outPos;
763+ int n;
764+ if (isUpdate) {
765+ n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
766+ } else {
767+ n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
768+ }
769+ input.position(inLimit);
770+ output.position(outPos + n);
771+ return n;
772+ } else if (!a1 && a2) {
773+ int outPos = output.position();
774+ byte[] outArray = output.array();
775+ int outOfs = output.arrayOffset() + outPos;
776+ byte[] inArray = new byte[getTempArraySize(inLen)];
777+ int total = 0;
778+ while (inLen > 0) {
779+ int chunk = Math.min(inLen, inArray.length);
780+ input.get(inArray, 0, chunk);
781+ int n;
782+ if (isUpdate || (inLen != chunk)) {
783+ n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
784+ } else {
785+ n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
786+ }
787+ total += n;
788+ outOfs += n;
789+ inLen -= chunk;
790+ }
791+ output.position(outPos + total);
792+ return total;
793+ } else { // output is not backed by an accessible byte[]
794+ byte[] inArray;
795+ int inOfs;
796+ if (a1) {
797+ inArray = input.array();
798+ inOfs = input.arrayOffset() + inPos;
799+ } else {
800+ inArray = new byte[getTempArraySize(inLen)];
801+ inOfs = 0;
802+ }
803+ byte[] outArray = new byte[getTempArraySize(outLenNeeded)];
804+ int outSize = outArray.length;
805+ int total = 0;
806+ boolean resized = false;
807+ while (inLen > 0) {
808+ int chunk = Math.min(inLen, outSize);
809+ if ((a1 == false) && (resized == false)) {
810+ input.get(inArray, 0, chunk);
811+ inOfs = 0;
812+ }
813+ try {
814+ int n;
815+ if (isUpdate || (inLen != chunk)) {
816+ n = engineUpdate(inArray, inOfs, chunk, outArray, 0);
817+ } else {
818+ n = engineDoFinal(inArray, inOfs, chunk, outArray, 0);
819+ }
820+ resized = false;
821+ inOfs += chunk;
822+ inLen -= chunk;
823+ output.put(outArray, 0, n);
824+ total += n;
825+ } catch (ShortBufferException e) {
826+ if (resized) {
827+ // we just resized the output buffer, but it still
828+ // did not work. Bug in the provider, abort
829+ throw (ProviderException)new ProviderException
830+ ("Could not determine buffer size").initCause(e);
831+ }
832+ // output buffer is too small, realloc and try again
833+ resized = true;
834+ int newOut = engineGetOutputSize(chunk);
835+ outArray = new byte[newOut];
836+ }
837+ }
838+ input.position(inLimit);
839+ return total;
840+ }
841+ }
842+
843+ /**
844+ * Wrap a key.
845+ *
846+ * <p>This concrete method has been added to this previously-defined
847+ * abstract class. (For backwards compatibility, it cannot be abstract.)
848+ * It may be overridden by a provider to wrap a key.
849+ * Such an override is expected to throw an IllegalBlockSizeException or
850+ * InvalidKeyException (under the specified circumstances),
851+ * if the given key cannot be wrapped.
852+ * If this method is not overridden, it always throws an
853+ * UnsupportedOperationException.
854+ *
855+ * @param key the key to be wrapped.
856+ *
857+ * @return the wrapped key.
858+ *
859+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
860+ * no padding has been requested, and the length of the encoding of the
861+ * key to be wrapped is not a multiple of the block size.
862+ *
863+ * @exception InvalidKeyException if it is impossible or unsafe to
864+ * wrap the key with this cipher (e.g., a hardware protected key is
865+ * being passed to a software-only cipher).
866+ */
867+ protected byte[] engineWrap(Key key)
868+ throws IllegalBlockSizeException, InvalidKeyException
869+ {
870+ throw new UnsupportedOperationException();
871+ }
872+
873+ /**
874+ * Unwrap a previously wrapped key.
875+ *
876+ * <p>This concrete method has been added to this previously-defined
877+ * abstract class. (For backwards compatibility, it cannot be abstract.)
878+ * It may be overridden by a provider to unwrap a previously wrapped key.
879+ * Such an override is expected to throw an InvalidKeyException if
880+ * the given wrapped key cannot be unwrapped.
881+ * If this method is not overridden, it always throws an
882+ * UnsupportedOperationException.
883+ *
884+ * @param wrappedKey the key to be unwrapped.
885+ *
886+ * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
887+ * key.
888+ *
889+ * @param wrappedKeyType the type of the wrapped key. This is one of
890+ * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
891+ * <code>PUBLIC_KEY</code>.
892+ *
893+ * @return the unwrapped key.
894+ *
895+ * @exception NoSuchAlgorithmException if no installed providers
896+ * can create keys of type <code>wrappedKeyType</code> for the
897+ * <code>wrappedKeyAlgorithm</code>.
898+ *
899+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
900+ * represent a wrapped key of type <code>wrappedKeyType</code> for
901+ * the <code>wrappedKeyAlgorithm</code>.
902+ */
903+ protected Key engineUnwrap(byte[] wrappedKey,
904+ String wrappedKeyAlgorithm,
905+ int wrappedKeyType)
906+ throws InvalidKeyException, NoSuchAlgorithmException
907+ {
908+ throw new UnsupportedOperationException();
909+ }
910+
911+ /**
912+ * Returns the key size of the given key object in bits.
913+ * <p>This concrete method has been added to this previously-defined
914+ * abstract class. It throws an <code>UnsupportedOperationException</code>
915+ * if it is not overridden by the provider.
916+ *
917+ * @param key the key object.
918+ *
919+ * @return the key size of the given key object.
920+ *
921+ * @exception InvalidKeyException if <code>key</code> is invalid.
922+ */
923+ protected int engineGetKeySize(Key key)
924+ throws InvalidKeyException
925+ {
926+ throw new UnsupportedOperationException();
927+ }
928+
929+ /**
930+ * Continues a multi-part update of the Additional Authentication
931+ * Data (AAD), using a subset of the provided buffer.
932+ * <p>
933+ * Calls to this method provide AAD to the cipher when operating in
934+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
935+ * either GCM or CCM mode, all AAD must be supplied before beginning
936+ * operations on the ciphertext (via the {@code update} and {@code
937+ * doFinal} methods).
938+ *
939+ * @param src the buffer containing the AAD
940+ * @param offset the offset in {@code src} where the AAD input starts
941+ * @param len the number of AAD bytes
942+ *
943+ * @throws IllegalStateException if this cipher is in a wrong state
944+ * (e.g., has not been initialized), does not accept AAD, or if
945+ * operating in either GCM or CCM mode and one of the {@code update}
946+ * methods has already been called for the active
947+ * encryption/decryption operation
948+ * @throws UnsupportedOperationException if this method
949+ * has not been overridden by an implementation
950+ *
951+ * @since 1.7
952+ */
953+ protected void engineUpdateAAD(byte[] src, int offset, int len) {
954+ throw new UnsupportedOperationException(
955+ "The underlying Cipher implementation "
956+ + "does not support this method");
957+ }
958+
959+ /**
960+ * Continues a multi-part update of the Additional Authentication
961+ * Data (AAD).
962+ * <p>
963+ * Calls to this method provide AAD to the cipher when operating in
964+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
965+ * either GCM or CCM mode, all AAD must be supplied before beginning
966+ * operations on the ciphertext (via the {@code update} and {@code
967+ * doFinal} methods).
968+ * <p>
969+ * All {@code src.remaining()} bytes starting at
970+ * {@code src.position()} are processed.
971+ * Upon return, the input buffer's position will be equal
972+ * to its limit; its limit will not have changed.
973+ *
974+ * @param src the buffer containing the AAD
975+ *
976+ * @throws IllegalStateException if this cipher is in a wrong state
977+ * (e.g., has not been initialized), does not accept AAD, or if
978+ * operating in either GCM or CCM mode and one of the {@code update}
979+ * methods has already been called for the active
980+ * encryption/decryption operation
981+ * @throws UnsupportedOperationException if this method
982+ * has not been overridden by an implementation
983+ *
984+ * @since 1.7
985+ */
986+ protected void engineUpdateAAD(ByteBuffer src) {
987+ throw new UnsupportedOperationException(
988+ "The underlying Cipher implementation "
989+ + "does not support this method");
990+ }
991+}