Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/crypto/CipherSpi.java
38829 views
1
/*
2
* Copyright (c) 1997, 2018, 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>AES</i>), and may be followed by a feedback mode and
63
* padding scheme.
64
*
65
* <p> A transformation is of the form:
66
*
67
* <ul>
68
* <li>"<i>algorithm/mode/padding</i>" or
69
*
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:
76
*
77
* <pre>
78
* Cipher c = Cipher.getInstance("<i>AES/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>AES/ECB/PKCS5Padding</i>, one that implements
129
* <i>AES/CBC/PKCS5Padding</i>, one that implements
130
* <i>AES/CFB/PKCS5Padding</i>, and yet another one that implements
131
* <i>AES/OFB/PKCS5Padding</i>. That provider would have the following
132
* <code>Cipher</code> properties in its master class:
133
*
134
* <ul>
135
*
136
* <li>
137
* <pre>
138
* <code>Cipher.</code><i>AES/ECB/PKCS5Padding</i>
139
* </pre>
140
*
141
* <li>
142
* <pre>
143
* <code>Cipher.</code><i>AES/CBC/PKCS5Padding</i>
144
* </pre>
145
*
146
* <li>
147
* <pre>
148
* <code>Cipher.</code><i>AES/CFB/PKCS5Padding</i>
149
* </pre>
150
*
151
* <li>
152
* <pre>
153
* <code>Cipher.</code><i>AES/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>AES</i> class that subclasses from <code>CipherSpi</code>.
162
* That provider would have the following
163
* <code>Cipher</code> properties in its master class:
164
*
165
* <ul>
166
*
167
* <li>
168
* <pre>
169
* <code>Cipher.</code><i>AES</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.
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.
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.
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
* @throws UnsupportedOperationException if {@code opmode} is
351
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
352
* by the cipher.
353
*/
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.
405
* @throws UnsupportedOperationException if {@code opmode} is
406
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
407
* by the cipher.
408
*/
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.
461
* @throws UnsupportedOperationException if {@code opmode} is
462
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
463
* by the cipher.
464
*/
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
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
int total = 0;
767
byte[] inArray, outArray;
768
if (a2) { // output has an accessible byte[]
769
outArray = output.array();
770
int outPos = output.position();
771
int outOfs = output.arrayOffset() + outPos;
772
773
if (a1) { // input also has an accessible byte[]
774
inArray = input.array();
775
int inOfs = input.arrayOffset() + inPos;
776
if (isUpdate) {
777
total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
778
} else {
779
total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
780
}
781
input.position(inLimit);
782
} else { // input does not have accessible byte[]
783
inArray = new byte[getTempArraySize(inLen)];
784
do {
785
int chunk = Math.min(inLen, inArray.length);
786
if (chunk > 0) {
787
input.get(inArray, 0, chunk);
788
}
789
int n;
790
if (isUpdate || (inLen > chunk)) {
791
n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
792
} else {
793
n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
794
}
795
total += n;
796
outOfs += n;
797
inLen -= chunk;
798
} while (inLen > 0);
799
}
800
output.position(outPos + total);
801
} else { // output does not have an accessible byte[]
802
if (a1) { // but input has an accessible byte[]
803
inArray = input.array();
804
int inOfs = input.arrayOffset() + inPos;
805
if (isUpdate) {
806
outArray = engineUpdate(inArray, inOfs, inLen);
807
} else {
808
outArray = engineDoFinal(inArray, inOfs, inLen);
809
}
810
input.position(inLimit);
811
if (outArray != null && outArray.length != 0) {
812
output.put(outArray);
813
total = outArray.length;
814
}
815
} else { // input also does not have an accessible byte[]
816
inArray = new byte[getTempArraySize(inLen)];
817
do {
818
int chunk = Math.min(inLen, inArray.length);
819
if (chunk > 0) {
820
input.get(inArray, 0, chunk);
821
}
822
int n;
823
if (isUpdate || (inLen > chunk)) {
824
outArray = engineUpdate(inArray, 0, chunk);
825
} else {
826
outArray = engineDoFinal(inArray, 0, chunk);
827
}
828
if (outArray != null && outArray.length != 0) {
829
output.put(outArray);
830
total += outArray.length;
831
}
832
inLen -= chunk;
833
} while (inLen > 0);
834
}
835
}
836
return total;
837
}
838
839
/**
840
* Wrap a key.
841
*
842
* <p>This concrete method has been added to this previously-defined
843
* abstract class. (For backwards compatibility, it cannot be abstract.)
844
* It may be overridden by a provider to wrap a key.
845
* Such an override is expected to throw an IllegalBlockSizeException or
846
* InvalidKeyException (under the specified circumstances),
847
* if the given key cannot be wrapped.
848
* If this method is not overridden, it always throws an
849
* UnsupportedOperationException.
850
*
851
* @param key the key to be wrapped.
852
*
853
* @return the wrapped key.
854
*
855
* @exception IllegalBlockSizeException if this cipher is a block cipher,
856
* no padding has been requested, and the length of the encoding of the
857
* key to be wrapped is not a multiple of the block size.
858
*
859
* @exception InvalidKeyException if it is impossible or unsafe to
860
* wrap the key with this cipher (e.g., a hardware protected key is
861
* being passed to a software-only cipher).
862
*
863
* @throws UnsupportedOperationException if this method is not supported.
864
*/
865
protected byte[] engineWrap(Key key)
866
throws IllegalBlockSizeException, InvalidKeyException
867
{
868
throw new UnsupportedOperationException();
869
}
870
871
/**
872
* Unwrap a previously wrapped key.
873
*
874
* <p>This concrete method has been added to this previously-defined
875
* abstract class. (For backwards compatibility, it cannot be abstract.)
876
* It may be overridden by a provider to unwrap a previously wrapped key.
877
* Such an override is expected to throw an InvalidKeyException if
878
* the given wrapped key cannot be unwrapped.
879
* If this method is not overridden, it always throws an
880
* UnsupportedOperationException.
881
*
882
* @param wrappedKey the key to be unwrapped.
883
*
884
* @param wrappedKeyAlgorithm the algorithm associated with the wrapped
885
* key.
886
*
887
* @param wrappedKeyType the type of the wrapped key. This is one of
888
* <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
889
* <code>PUBLIC_KEY</code>.
890
*
891
* @return the unwrapped key.
892
*
893
* @exception NoSuchAlgorithmException if no installed providers
894
* can create keys of type <code>wrappedKeyType</code> for the
895
* <code>wrappedKeyAlgorithm</code>.
896
*
897
* @exception InvalidKeyException if <code>wrappedKey</code> does not
898
* represent a wrapped key of type <code>wrappedKeyType</code> for
899
* the <code>wrappedKeyAlgorithm</code>.
900
*
901
* @throws UnsupportedOperationException if this method is not supported.
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
}
992
993