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