Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java
67854 views
1
/*
2
* Copyright (c) 2002, 2021, 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 com.sun.crypto.provider;
27
28
import javax.crypto.BadPaddingException;
29
import javax.crypto.CipherSpi;
30
import javax.crypto.IllegalBlockSizeException;
31
import javax.crypto.NoSuchPaddingException;
32
import javax.crypto.ShortBufferException;
33
import java.nio.ByteBuffer;
34
import java.security.AlgorithmParameters;
35
import java.security.GeneralSecurityException;
36
import java.security.InvalidAlgorithmParameterException;
37
import java.security.InvalidKeyException;
38
import java.security.Key;
39
import java.security.NoSuchAlgorithmException;
40
import java.security.ProviderException;
41
import java.security.SecureRandom;
42
import java.security.spec.AlgorithmParameterSpec;
43
import java.util.Arrays;
44
45
/**
46
* This class implements the AES algorithm in its various modes
47
* (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,
48
* <code>PCBC</code>) and padding schemes (<code>PKCS5Padding</code>,
49
* <code>NoPadding</code>, <code>ISO10126Padding</code>).
50
*
51
* @author Valerie Peng
52
*
53
*
54
* @see AESCrypt
55
* @see CipherBlockChaining
56
* @see ElectronicCodeBook
57
* @see CipherFeedback
58
* @see OutputFeedback
59
*/
60
61
abstract class AESCipher extends CipherSpi {
62
public static final class General extends AESCipher {
63
public General() {
64
super(-1);
65
}
66
}
67
abstract static class OidImpl extends AESCipher {
68
protected OidImpl(int keySize, String mode, String padding) {
69
super(keySize);
70
try {
71
engineSetMode(mode);
72
engineSetPadding(padding);
73
} catch (GeneralSecurityException gse) {
74
// internal error; re-throw as provider exception
75
ProviderException pe =new ProviderException("Internal Error");
76
pe.initCause(gse);
77
throw pe;
78
}
79
}
80
}
81
public static final class AES128_ECB_NoPadding extends OidImpl {
82
public AES128_ECB_NoPadding() {
83
super(16, "ECB", "NOPADDING");
84
}
85
}
86
public static final class AES192_ECB_NoPadding extends OidImpl {
87
public AES192_ECB_NoPadding() {
88
super(24, "ECB", "NOPADDING");
89
}
90
}
91
public static final class AES256_ECB_NoPadding extends OidImpl {
92
public AES256_ECB_NoPadding() {
93
super(32, "ECB", "NOPADDING");
94
}
95
}
96
public static final class AES128_CBC_NoPadding extends OidImpl {
97
public AES128_CBC_NoPadding() {
98
super(16, "CBC", "NOPADDING");
99
}
100
}
101
public static final class AES192_CBC_NoPadding extends OidImpl {
102
public AES192_CBC_NoPadding() {
103
super(24, "CBC", "NOPADDING");
104
}
105
}
106
public static final class AES256_CBC_NoPadding extends OidImpl {
107
public AES256_CBC_NoPadding() {
108
super(32, "CBC", "NOPADDING");
109
}
110
}
111
public static final class AES128_OFB_NoPadding extends OidImpl {
112
public AES128_OFB_NoPadding() {
113
super(16, "OFB", "NOPADDING");
114
}
115
}
116
public static final class AES192_OFB_NoPadding extends OidImpl {
117
public AES192_OFB_NoPadding() {
118
super(24, "OFB", "NOPADDING");
119
}
120
}
121
public static final class AES256_OFB_NoPadding extends OidImpl {
122
public AES256_OFB_NoPadding() {
123
super(32, "OFB", "NOPADDING");
124
}
125
}
126
public static final class AES128_CFB_NoPadding extends OidImpl {
127
public AES128_CFB_NoPadding() {
128
super(16, "CFB", "NOPADDING");
129
}
130
}
131
public static final class AES192_CFB_NoPadding extends OidImpl {
132
public AES192_CFB_NoPadding() {
133
super(24, "CFB", "NOPADDING");
134
}
135
}
136
public static final class AES256_CFB_NoPadding extends OidImpl {
137
public AES256_CFB_NoPadding() {
138
super(32, "CFB", "NOPADDING");
139
}
140
}
141
142
// utility method used by AESCipher and AESWrapCipher
143
static final void checkKeySize(Key key, int fixedKeySize)
144
throws InvalidKeyException {
145
if (fixedKeySize != -1) {
146
if (key == null) {
147
throw new InvalidKeyException("The key must not be null");
148
}
149
byte[] value = key.getEncoded();
150
if (value == null) {
151
throw new InvalidKeyException("Key encoding must not be null");
152
} else {
153
Arrays.fill(value, (byte)0);
154
if (value.length != fixedKeySize) {
155
throw new InvalidKeyException("The key must be " +
156
fixedKeySize + " bytes");
157
}
158
}
159
}
160
}
161
162
/*
163
* internal CipherCore object which does the real work.
164
*/
165
private CipherCore core = null;
166
167
/*
168
* needed to support AES oids which associates a fixed key size
169
* to the cipher object.
170
*/
171
private final int fixedKeySize; // in bytes, -1 if no restriction
172
173
174
/**
175
* Creates an instance of AES cipher with default ECB mode and
176
* PKCS5Padding.
177
*/
178
protected AESCipher(int keySize) {
179
core = new CipherCore(new AESCrypt(), AESConstants.AES_BLOCK_SIZE);
180
fixedKeySize = keySize;
181
}
182
183
/**
184
* Sets the mode of this cipher.
185
*
186
* @param mode the cipher mode
187
*
188
* @exception NoSuchAlgorithmException if the requested cipher mode does
189
* not exist
190
*/
191
protected void engineSetMode(String mode)
192
throws NoSuchAlgorithmException {
193
core.setMode(mode);
194
}
195
196
/**
197
* Sets the padding mechanism of this cipher.
198
*
199
* @param paddingScheme the padding mechanism
200
*
201
* @exception NoSuchPaddingException if the requested padding mechanism
202
* does not exist
203
*/
204
protected void engineSetPadding(String paddingScheme)
205
throws NoSuchPaddingException {
206
core.setPadding(paddingScheme);
207
}
208
209
/**
210
* Returns the block size (in bytes).
211
*
212
* @return the block size (in bytes), or 0 if the underlying algorithm is
213
* not a block cipher
214
*/
215
protected int engineGetBlockSize() {
216
return AESConstants.AES_BLOCK_SIZE;
217
}
218
219
/**
220
* Returns the length in bytes that an output buffer would need to be in
221
* order to hold the result of the next <code>update</code> or
222
* <code>doFinal</code> operation, given the input length
223
* <code>inputLen</code> (in bytes).
224
*
225
* <p>This call takes into account any unprocessed (buffered) data from a
226
* previous <code>update</code> call, and padding.
227
*
228
* <p>The actual output length of the next <code>update</code> or
229
* <code>doFinal</code> call may be smaller than the length returned by
230
* this method.
231
*
232
* @param inputLen the input length (in bytes)
233
*
234
* @return the required output buffer size (in bytes)
235
*/
236
protected int engineGetOutputSize(int inputLen) {
237
return core.getOutputSize(inputLen);
238
}
239
240
/**
241
* Returns the initialization vector (IV) in a new buffer.
242
*
243
* <p>This is useful in the case where a random IV has been created
244
* (see <a href = "#init">init</a>),
245
* or in the context of password-based encryption or
246
* decryption, where the IV is derived from a user-provided password.
247
*
248
* @return the initialization vector in a new buffer, or null if the
249
* underlying algorithm does not use an IV, or if the IV has not yet
250
* been set.
251
*/
252
protected byte[] engineGetIV() {
253
return core.getIV();
254
}
255
256
/**
257
* Returns the parameters used with this cipher.
258
*
259
* <p>The returned parameters may be the same that were used to initialize
260
* this cipher, or may contain the default set of parameters or a set of
261
* randomly generated parameters used by the underlying cipher
262
* implementation (provided that the underlying cipher implementation
263
* uses a default set of parameters or creates new parameters if it needs
264
* parameters but was not initialized with any).
265
*
266
* @return the parameters used with this cipher, or null if this cipher
267
* does not use any parameters.
268
*/
269
protected AlgorithmParameters engineGetParameters() {
270
return core.getParameters("AES");
271
}
272
273
/**
274
* Initializes this cipher with a key and a source of randomness.
275
*
276
* <p>The cipher is initialized for one of the following four operations:
277
* encryption, decryption, key wrapping or key unwrapping, depending on
278
* the value of <code>opmode</code>.
279
*
280
* <p>If this cipher requires an initialization vector (IV), it will get
281
* it from <code>random</code>.
282
* This behaviour should only be used in encryption or key wrapping
283
* mode, however.
284
* When initializing a cipher that requires an IV for decryption or
285
* key unwrapping, the IV
286
* (same IV that was used for encryption or key wrapping) must be provided
287
* explicitly as a
288
* parameter, in order to get the correct result.
289
*
290
* <p>This method also cleans existing buffer and other related state
291
* information.
292
*
293
* @param opmode the operation mode of this cipher (this is one of
294
* the following:
295
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
296
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
297
* @param key the secret key
298
* @param random the source of randomness
299
*
300
* @exception InvalidKeyException if the given key is inappropriate for
301
* initializing this cipher
302
*/
303
protected void engineInit(int opmode, Key key, SecureRandom random)
304
throws InvalidKeyException {
305
checkKeySize(key, fixedKeySize);
306
core.init(opmode, key, random);
307
}
308
309
/**
310
* Initializes this cipher with a key, a set of
311
* algorithm parameters, and a source of randomness.
312
*
313
* <p>The cipher is initialized for one of the following four operations:
314
* encryption, decryption, key wrapping or key unwrapping, depending on
315
* the value of <code>opmode</code>.
316
*
317
* <p>If this cipher (including its underlying feedback or padding scheme)
318
* requires any random bytes, it will get them from <code>random</code>.
319
*
320
* @param opmode the operation mode of this cipher (this is one of
321
* the following:
322
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
323
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
324
* @param key the encryption key
325
* @param params the algorithm parameters
326
* @param random the source of randomness
327
*
328
* @exception InvalidKeyException if the given key is inappropriate for
329
* initializing this cipher
330
* @exception InvalidAlgorithmParameterException if the given algorithm
331
* parameters are inappropriate for this cipher
332
*/
333
protected void engineInit(int opmode, Key key,
334
AlgorithmParameterSpec params,
335
SecureRandom random)
336
throws InvalidKeyException, InvalidAlgorithmParameterException {
337
checkKeySize(key, fixedKeySize);
338
core.init(opmode, key, params, random);
339
}
340
341
protected void engineInit(int opmode, Key key,
342
AlgorithmParameters params,
343
SecureRandom random)
344
throws InvalidKeyException, InvalidAlgorithmParameterException {
345
checkKeySize(key, fixedKeySize);
346
core.init(opmode, key, params, random);
347
}
348
349
/**
350
* Continues a multiple-part encryption or decryption operation
351
* (depending on how this cipher was initialized), processing another data
352
* part.
353
*
354
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
355
* buffer, starting at <code>inputOffset</code>, are processed, and the
356
* result is stored in a new buffer.
357
*
358
* @param input the input buffer
359
* @param inputOffset the offset in <code>input</code> where the input
360
* starts
361
* @param inputLen the input length
362
*
363
* @return the new buffer with the result
364
*
365
* @exception IllegalStateException if this cipher is in a wrong state
366
* (e.g., has not been initialized)
367
*/
368
protected byte[] engineUpdate(byte[] input, int inputOffset,
369
int inputLen) {
370
return core.update(input, inputOffset, inputLen);
371
}
372
373
/**
374
* Continues a multiple-part encryption or decryption operation
375
* (depending on how this cipher was initialized), processing another data
376
* part.
377
*
378
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
379
* buffer, starting at <code>inputOffset</code>, are processed, and the
380
* result is stored in the <code>output</code> buffer, starting at
381
* <code>outputOffset</code>.
382
*
383
* @param input the input buffer
384
* @param inputOffset the offset in <code>input</code> where the input
385
* starts
386
* @param inputLen the input length
387
* @param output the buffer for the result
388
* @param outputOffset the offset in <code>output</code> where the result
389
* is stored
390
*
391
* @return the number of bytes stored in <code>output</code>
392
*
393
* @exception ShortBufferException if the given output buffer is too small
394
* to hold the result
395
*/
396
protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
397
byte[] output, int outputOffset)
398
throws ShortBufferException {
399
return core.update(input, inputOffset, inputLen, output,
400
outputOffset);
401
}
402
403
404
/**
405
* Encrypts or decrypts data in a single-part operation,
406
* or finishes a multiple-part operation.
407
* The data is encrypted or decrypted, depending on how this cipher was
408
* initialized.
409
*
410
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
411
* buffer, starting at <code>inputOffset</code>, and any input bytes that
412
* may have been buffered during a previous <code>update</code> operation,
413
* are processed, with padding (if requested) being applied.
414
* The result is stored in a new buffer.
415
*
416
* <p>The cipher is reset to its initial state (uninitialized) after this
417
* call.
418
*
419
* @param input the input buffer
420
* @param inputOffset the offset in <code>input</code> where the input
421
* starts
422
* @param inputLen the input length
423
*
424
* @return the new buffer with the result
425
*
426
* @exception IllegalBlockSizeException if this cipher is a block cipher,
427
* no padding has been requested (only in encryption mode), and the total
428
* input length of the data processed by this cipher is not a multiple of
429
* block size
430
* @exception BadPaddingException if this cipher is in decryption mode,
431
* and (un)padding has been requested, but the decrypted data is not
432
* bounded by the appropriate padding bytes
433
*/
434
protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
435
throws IllegalBlockSizeException, BadPaddingException {
436
byte[] out = core.doFinal(input, inputOffset, inputLen);
437
return out;
438
}
439
440
/**
441
* Encrypts or decrypts data in a single-part operation,
442
* or finishes a multiple-part operation.
443
* The data is encrypted or decrypted, depending on how this cipher was
444
* initialized.
445
*
446
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
447
* buffer, starting at <code>inputOffset</code>, and any input bytes that
448
* may have been buffered during a previous <code>update</code> operation,
449
* are processed, with padding (if requested) being applied.
450
* The result is stored in the <code>output</code> buffer, starting at
451
* <code>outputOffset</code>.
452
*
453
* <p>The cipher is reset to its initial state (uninitialized) after this
454
* call.
455
*
456
* @param input the input buffer
457
* @param inputOffset the offset in <code>input</code> where the input
458
* starts
459
* @param inputLen the input length
460
* @param output the buffer for the result
461
* @param outputOffset the offset in <code>output</code> where the result
462
* is stored
463
*
464
* @return the number of bytes stored in <code>output</code>
465
*
466
* @exception IllegalBlockSizeException if this cipher is a block cipher,
467
* no padding has been requested (only in encryption mode), and the total
468
* input length of the data processed by this cipher is not a multiple of
469
* block size
470
* @exception ShortBufferException if the given output buffer is too small
471
* to hold the result
472
* @exception BadPaddingException if this cipher is in decryption mode,
473
* and (un)padding has been requested, but the decrypted data is not
474
* bounded by the appropriate padding bytes
475
*/
476
protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
477
byte[] output, int outputOffset)
478
throws IllegalBlockSizeException, ShortBufferException,
479
BadPaddingException {
480
int outLen = core.doFinal(input, inputOffset, inputLen, output,
481
outputOffset);
482
return outLen;
483
}
484
485
/**
486
* Returns the key size of the given key object.
487
*
488
* @param key the key object.
489
*
490
* @return the key size of the given key object.
491
*
492
* @exception InvalidKeyException if <code>key</code> is invalid.
493
*/
494
protected int engineGetKeySize(Key key) throws InvalidKeyException {
495
byte[] encoded = key.getEncoded();
496
Arrays.fill(encoded, (byte)0);
497
if (!AESCrypt.isKeySizeValid(encoded.length)) {
498
throw new InvalidKeyException("Invalid AES key length: " +
499
encoded.length + " bytes");
500
}
501
return Math.multiplyExact(encoded.length, 8);
502
}
503
504
/**
505
* Wrap a key.
506
*
507
* @param key the key to be wrapped.
508
*
509
* @return the wrapped key.
510
*
511
* @exception IllegalBlockSizeException if this cipher is a block
512
* cipher, no padding has been requested, and the length of the
513
* encoding of the key to be wrapped is not a
514
* multiple of the block size.
515
*
516
* @exception InvalidKeyException if it is impossible or unsafe to
517
* wrap the key with this cipher (e.g., a hardware protected key is
518
* being passed to a software only cipher).
519
*/
520
protected byte[] engineWrap(Key key)
521
throws IllegalBlockSizeException, InvalidKeyException {
522
return core.wrap(key);
523
}
524
525
/**
526
* Unwrap a previously wrapped key.
527
*
528
* @param wrappedKey the key to be unwrapped.
529
*
530
* @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
531
*
532
* @param wrappedKeyType the type of the wrapped key.
533
* This is one of <code>Cipher.SECRET_KEY</code>,
534
* <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
535
*
536
* @return the unwrapped key.
537
*
538
* @exception NoSuchAlgorithmException if no installed providers
539
* can create keys of type <code>wrappedKeyType</code> for the
540
* <code>wrappedKeyAlgorithm</code>.
541
*
542
* @exception InvalidKeyException if <code>wrappedKey</code> does not
543
* represent a wrapped key of type <code>wrappedKeyType</code> for
544
* the <code>wrappedKeyAlgorithm</code>.
545
*/
546
protected Key engineUnwrap(byte[] wrappedKey,
547
String wrappedKeyAlgorithm,
548
int wrappedKeyType)
549
throws InvalidKeyException, NoSuchAlgorithmException {
550
return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
551
wrappedKeyType);
552
}
553
554
/**
555
* Finalize crypto operation with ByteBuffers
556
*
557
* @param input the input ByteBuffer
558
* @param output the output ByteBuffer
559
*
560
* @return output length
561
* @throws ShortBufferException
562
* @throws IllegalBlockSizeException
563
* @throws BadPaddingException
564
*/
565
@Override
566
protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
567
throws ShortBufferException, IllegalBlockSizeException,
568
BadPaddingException {
569
return super.engineDoFinal(input, output);
570
}
571
}
572
573