Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-aarch32-jdk8u
Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
83409 views
1
/*
2
* Copyright (c) 2003, 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
package sun.security.pkcs11;
26
27
import java.nio.ByteBuffer;
28
import java.util.Arrays;
29
import java.util.Locale;
30
31
import java.security.*;
32
import java.security.spec.*;
33
34
import javax.crypto.*;
35
import javax.crypto.spec.*;
36
37
import sun.nio.ch.DirectBuffer;
38
import sun.security.jca.JCAUtil;
39
import sun.security.pkcs11.wrapper.*;
40
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
41
42
/**
43
* Cipher implementation class. This class currently supports
44
* DES, DESede, AES, ARCFOUR, and Blowfish.
45
*
46
* This class is designed to support ECB, CBC, CTR with NoPadding
47
* and ECB, CBC with PKCS5Padding. It will use its own padding impl
48
* if the native mechanism does not support padding.
49
*
50
* Note that PKCS#11 currently only supports ECB, CBC, and CTR.
51
* There are no provisions for other modes such as CFB, OFB, and PCBC.
52
*
53
* @author Andreas Sterbenz
54
* @since 1.5
55
*/
56
final class P11Cipher extends CipherSpi {
57
58
// mode constant for ECB mode
59
private final static int MODE_ECB = 3;
60
// mode constant for CBC mode
61
private final static int MODE_CBC = 4;
62
// mode constant for CTR mode
63
private final static int MODE_CTR = 5;
64
65
// padding constant for NoPadding
66
private final static int PAD_NONE = 5;
67
// padding constant for PKCS5Padding
68
private final static int PAD_PKCS5 = 6;
69
70
private static interface Padding {
71
// ENC: format the specified buffer with padding bytes and return the
72
// actual padding length
73
int setPaddingBytes(byte[] paddingBuffer, int padLen);
74
75
// DEC: return the length of trailing padding bytes given the specified
76
// padded data
77
int unpad(byte[] paddedData, int len)
78
throws BadPaddingException, IllegalBlockSizeException;
79
}
80
81
private static class PKCS5Padding implements Padding {
82
83
private final int blockSize;
84
85
PKCS5Padding(int blockSize)
86
throws NoSuchPaddingException {
87
if (blockSize == 0) {
88
throw new NoSuchPaddingException
89
("PKCS#5 padding not supported with stream ciphers");
90
}
91
this.blockSize = blockSize;
92
}
93
94
public int setPaddingBytes(byte[] paddingBuffer, int padLen) {
95
Arrays.fill(paddingBuffer, 0, padLen, (byte) (padLen & 0x007f));
96
return padLen;
97
}
98
99
public int unpad(byte[] paddedData, int len)
100
throws BadPaddingException, IllegalBlockSizeException {
101
if ((len < 1) || (len % blockSize != 0)) {
102
throw new IllegalBlockSizeException
103
("Input length must be multiples of " + blockSize);
104
}
105
byte padValue = paddedData[len - 1];
106
if (padValue < 1 || padValue > blockSize) {
107
throw new BadPaddingException("Invalid pad value!");
108
}
109
// sanity check padding bytes
110
int padStartIndex = len - padValue;
111
for (int i = padStartIndex; i < len; i++) {
112
if (paddedData[i] != padValue) {
113
throw new BadPaddingException("Invalid pad bytes!");
114
}
115
}
116
return padValue;
117
}
118
}
119
120
// token instance
121
private final Token token;
122
123
// algorithm name
124
private final String algorithm;
125
126
// name of the key algorithm, e.g. DES instead of algorithm DES/CBC/...
127
private final String keyAlgorithm;
128
129
// mechanism id
130
private final long mechanism;
131
132
// associated session, if any
133
private Session session;
134
135
// key, if init() was called
136
private P11Key p11Key;
137
138
// flag indicating whether an operation is initialized
139
private boolean initialized;
140
141
// falg indicating encrypt or decrypt mode
142
private boolean encrypt;
143
144
// mode, one of MODE_* above (MODE_ECB for stream ciphers)
145
private int blockMode;
146
147
// block size, 0 for stream ciphers
148
private final int blockSize;
149
150
// padding type, on of PAD_* above (PAD_NONE for stream ciphers)
151
private int paddingType;
152
153
// when the padding is requested but unsupported by the native mechanism,
154
// we use the following to do padding and necessary data buffering.
155
// padding object which generate padding and unpad the decrypted data
156
private Padding paddingObj;
157
// buffer for holding back the block which contains padding bytes
158
private byte[] padBuffer;
159
private int padBufferLen;
160
161
// original IV, if in MODE_CBC or MODE_CTR
162
private byte[] iv;
163
164
// number of bytes buffered internally by the native mechanism and padBuffer
165
// if we do the padding
166
private int bytesBuffered;
167
168
// length of key size in bytes; currently only used by AES given its oid
169
// specification mandates a fixed size of the key
170
private int fixedKeySize = -1;
171
172
P11Cipher(Token token, String algorithm, long mechanism)
173
throws PKCS11Exception, NoSuchAlgorithmException {
174
super();
175
this.token = token;
176
this.algorithm = algorithm;
177
this.mechanism = mechanism;
178
179
String algoParts[] = algorithm.split("/");
180
181
if (algoParts[0].startsWith("AES")) {
182
blockSize = 16;
183
int index = algoParts[0].indexOf('_');
184
if (index != -1) {
185
// should be well-formed since we specify what we support
186
fixedKeySize = Integer.parseInt(algoParts[0].substring(index+1))/8;
187
}
188
keyAlgorithm = "AES";
189
} else {
190
keyAlgorithm = algoParts[0];
191
if (keyAlgorithm.equals("RC4") ||
192
keyAlgorithm.equals("ARCFOUR")) {
193
blockSize = 0;
194
} else { // DES, DESede, Blowfish
195
blockSize = 8;
196
}
197
}
198
this.blockMode =
199
(algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
200
String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
201
String paddingStr =
202
(algoParts.length > 2 ? algoParts[2] : defPadding);
203
try {
204
engineSetPadding(paddingStr);
205
} catch (NoSuchPaddingException nspe) {
206
// should not happen
207
throw new ProviderException(nspe);
208
}
209
}
210
211
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
212
// Disallow change of mode for now since currently it's explicitly
213
// defined in transformation strings
214
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
215
}
216
217
private int parseMode(String mode) throws NoSuchAlgorithmException {
218
mode = mode.toUpperCase(Locale.ENGLISH);
219
int result;
220
if (mode.equals("ECB")) {
221
result = MODE_ECB;
222
} else if (mode.equals("CBC")) {
223
if (blockSize == 0) {
224
throw new NoSuchAlgorithmException
225
("CBC mode not supported with stream ciphers");
226
}
227
result = MODE_CBC;
228
} else if (mode.equals("CTR")) {
229
result = MODE_CTR;
230
} else {
231
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
232
}
233
return result;
234
}
235
236
// see JCE spec
237
protected void engineSetPadding(String padding)
238
throws NoSuchPaddingException {
239
paddingObj = null;
240
padBuffer = null;
241
padding = padding.toUpperCase(Locale.ENGLISH);
242
if (padding.equals("NOPADDING")) {
243
paddingType = PAD_NONE;
244
} else if (padding.equals("PKCS5PADDING")) {
245
if (this.blockMode == MODE_CTR) {
246
throw new NoSuchPaddingException
247
("PKCS#5 padding not supported with CTR mode");
248
}
249
paddingType = PAD_PKCS5;
250
if (mechanism != CKM_DES_CBC_PAD && mechanism != CKM_DES3_CBC_PAD &&
251
mechanism != CKM_AES_CBC_PAD) {
252
// no native padding support; use our own padding impl
253
paddingObj = new PKCS5Padding(blockSize);
254
padBuffer = new byte[blockSize];
255
}
256
} else {
257
throw new NoSuchPaddingException("Unsupported padding " + padding);
258
}
259
}
260
261
// see JCE spec
262
protected int engineGetBlockSize() {
263
return blockSize;
264
}
265
266
// see JCE spec
267
protected int engineGetOutputSize(int inputLen) {
268
return doFinalLength(inputLen);
269
}
270
271
// see JCE spec
272
protected byte[] engineGetIV() {
273
return (iv == null) ? null : iv.clone();
274
}
275
276
// see JCE spec
277
protected AlgorithmParameters engineGetParameters() {
278
if (iv == null) {
279
return null;
280
}
281
IvParameterSpec ivSpec = new IvParameterSpec(iv);
282
try {
283
AlgorithmParameters params =
284
AlgorithmParameters.getInstance(keyAlgorithm,
285
P11Util.getSunJceProvider());
286
params.init(ivSpec);
287
return params;
288
} catch (GeneralSecurityException e) {
289
// NoSuchAlgorithmException, NoSuchProviderException
290
// InvalidParameterSpecException
291
throw new ProviderException("Could not encode parameters", e);
292
}
293
}
294
295
// see JCE spec
296
protected void engineInit(int opmode, Key key, SecureRandom random)
297
throws InvalidKeyException {
298
try {
299
implInit(opmode, key, null, random);
300
} catch (InvalidAlgorithmParameterException e) {
301
throw new InvalidKeyException("init() failed", e);
302
}
303
}
304
305
// see JCE spec
306
protected void engineInit(int opmode, Key key,
307
AlgorithmParameterSpec params, SecureRandom random)
308
throws InvalidKeyException, InvalidAlgorithmParameterException {
309
byte[] ivValue;
310
if (params != null) {
311
if (params instanceof IvParameterSpec == false) {
312
throw new InvalidAlgorithmParameterException
313
("Only IvParameterSpec supported");
314
}
315
IvParameterSpec ivSpec = (IvParameterSpec) params;
316
ivValue = ivSpec.getIV();
317
} else {
318
ivValue = null;
319
}
320
implInit(opmode, key, ivValue, random);
321
}
322
323
// see JCE spec
324
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
325
SecureRandom random)
326
throws InvalidKeyException, InvalidAlgorithmParameterException {
327
byte[] ivValue;
328
if (params != null) {
329
try {
330
IvParameterSpec ivSpec =
331
params.getParameterSpec(IvParameterSpec.class);
332
ivValue = ivSpec.getIV();
333
} catch (InvalidParameterSpecException e) {
334
throw new InvalidAlgorithmParameterException
335
("Could not decode IV", e);
336
}
337
} else {
338
ivValue = null;
339
}
340
implInit(opmode, key, ivValue, random);
341
}
342
343
// actual init() implementation
344
private void implInit(int opmode, Key key, byte[] iv,
345
SecureRandom random)
346
throws InvalidKeyException, InvalidAlgorithmParameterException {
347
reset(true);
348
if (fixedKeySize != -1 &&
349
((key instanceof P11Key) ? ((P11Key) key).length() >> 3 :
350
key.getEncoded().length) != fixedKeySize) {
351
throw new InvalidKeyException("Key size is invalid");
352
}
353
switch (opmode) {
354
case Cipher.ENCRYPT_MODE:
355
encrypt = true;
356
break;
357
case Cipher.DECRYPT_MODE:
358
encrypt = false;
359
break;
360
default:
361
throw new InvalidAlgorithmParameterException
362
("Unsupported mode: " + opmode);
363
}
364
if (blockMode == MODE_ECB) { // ECB or stream cipher
365
if (iv != null) {
366
if (blockSize == 0) {
367
throw new InvalidAlgorithmParameterException
368
("IV not used with stream ciphers");
369
} else {
370
throw new InvalidAlgorithmParameterException
371
("IV not used in ECB mode");
372
}
373
}
374
} else { // MODE_CBC or MODE_CTR
375
if (iv == null) {
376
if (encrypt == false) {
377
String exMsg =
378
(blockMode == MODE_CBC ?
379
"IV must be specified for decryption in CBC mode" :
380
"IV must be specified for decryption in CTR mode");
381
throw new InvalidAlgorithmParameterException(exMsg);
382
}
383
// generate random IV
384
if (random == null) {
385
random = JCAUtil.getSecureRandom();
386
}
387
iv = new byte[blockSize];
388
random.nextBytes(iv);
389
} else {
390
if (iv.length != blockSize) {
391
throw new InvalidAlgorithmParameterException
392
("IV length must match block size");
393
}
394
}
395
}
396
this.iv = iv;
397
p11Key = P11SecretKeyFactory.convertKey(token, key, keyAlgorithm);
398
try {
399
initialize();
400
} catch (PKCS11Exception e) {
401
throw new InvalidKeyException("Could not initialize cipher", e);
402
}
403
}
404
405
// reset the states to the pre-initialized values
406
// need to be called after doFinal or prior to re-init
407
private void reset(boolean doCancel) {
408
if (!initialized) {
409
return;
410
}
411
initialized = false;
412
413
try {
414
if (session == null) {
415
return;
416
}
417
418
if (doCancel && token.explicitCancel) {
419
cancelOperation();
420
}
421
} finally {
422
p11Key.releaseKeyID();
423
session = token.releaseSession(session);
424
bytesBuffered = 0;
425
padBufferLen = 0;
426
}
427
}
428
429
private void cancelOperation() {
430
token.ensureValid();
431
// cancel operation by finishing it; avoid killSession as some
432
// hardware vendors may require re-login
433
try {
434
int bufLen = doFinalLength(0);
435
byte[] buffer = new byte[bufLen];
436
if (encrypt) {
437
token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
438
} else {
439
token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
440
}
441
} catch (PKCS11Exception e) {
442
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
443
// Cancel Operation may be invoked after an error on a PKCS#11
444
// call. If the operation inside the token was already cancelled,
445
// do not fail here. This is part of a defensive mechanism for
446
// PKCS#11 libraries that do not strictly follow the standard.
447
return;
448
}
449
if (encrypt) {
450
throw new ProviderException("Cancel failed", e);
451
}
452
// ignore failure for decryption
453
}
454
}
455
456
private void ensureInitialized() throws PKCS11Exception {
457
if (!initialized) {
458
initialize();
459
}
460
}
461
462
private void initialize() throws PKCS11Exception {
463
if (p11Key == null) {
464
throw new ProviderException(
465
"Operation cannot be performed without"
466
+ " calling engineInit first");
467
}
468
token.ensureValid();
469
long p11KeyID = p11Key.getKeyID();
470
try {
471
if (session == null) {
472
session = token.getOpSession();
473
}
474
CK_MECHANISM mechParams = (blockMode == MODE_CTR?
475
new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
476
new CK_MECHANISM(mechanism, iv));
477
if (encrypt) {
478
token.p11.C_EncryptInit(session.id(), mechParams, p11KeyID);
479
} else {
480
token.p11.C_DecryptInit(session.id(), mechParams, p11KeyID);
481
}
482
} catch (PKCS11Exception e) {
483
p11Key.releaseKeyID();
484
session = token.releaseSession(session);
485
throw e;
486
}
487
initialized = true;
488
bytesBuffered = 0;
489
padBufferLen = 0;
490
}
491
492
// if update(inLen) is called, how big does the output buffer have to be?
493
private int updateLength(int inLen) {
494
if (inLen <= 0) {
495
return 0;
496
}
497
498
int result = inLen + bytesBuffered;
499
if (blockSize != 0 && blockMode != MODE_CTR) {
500
// minus the number of bytes in the last incomplete block.
501
result -= (result & (blockSize - 1));
502
}
503
return result;
504
}
505
506
// if doFinal(inLen) is called, how big does the output buffer have to be?
507
private int doFinalLength(int inLen) {
508
if (inLen < 0) {
509
return 0;
510
}
511
512
int result = inLen + bytesBuffered;
513
if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
514
// add the number of bytes to make the last block complete.
515
result += (blockSize - (result & (blockSize - 1)));
516
}
517
return result;
518
}
519
520
// see JCE spec
521
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
522
try {
523
byte[] out = new byte[updateLength(inLen)];
524
int n = engineUpdate(in, inOfs, inLen, out, 0);
525
return P11Util.convert(out, 0, n);
526
} catch (ShortBufferException e) {
527
// convert since the output length is calculated by updateLength()
528
throw new ProviderException(e);
529
}
530
}
531
532
// see JCE spec
533
protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
534
int outOfs) throws ShortBufferException {
535
int outLen = out.length - outOfs;
536
return implUpdate(in, inOfs, inLen, out, outOfs, outLen);
537
}
538
539
// see JCE spec
540
@Override
541
protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
542
throws ShortBufferException {
543
return implUpdate(inBuffer, outBuffer);
544
}
545
546
// see JCE spec
547
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
548
throws IllegalBlockSizeException, BadPaddingException {
549
try {
550
byte[] out = new byte[doFinalLength(inLen)];
551
int n = engineDoFinal(in, inOfs, inLen, out, 0);
552
return P11Util.convert(out, 0, n);
553
} catch (ShortBufferException e) {
554
// convert since the output length is calculated by doFinalLength()
555
throw new ProviderException(e);
556
}
557
}
558
559
// see JCE spec
560
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
561
int outOfs) throws ShortBufferException, IllegalBlockSizeException,
562
BadPaddingException {
563
int n = 0;
564
if ((inLen != 0) && (in != null)) {
565
n = engineUpdate(in, inOfs, inLen, out, outOfs);
566
outOfs += n;
567
}
568
n += implDoFinal(out, outOfs, out.length - outOfs);
569
return n;
570
}
571
572
// see JCE spec
573
@Override
574
protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
575
throws ShortBufferException, IllegalBlockSizeException,
576
BadPaddingException {
577
int n = engineUpdate(inBuffer, outBuffer);
578
n += implDoFinal(outBuffer);
579
return n;
580
}
581
582
private int implUpdate(byte[] in, int inOfs, int inLen,
583
byte[] out, int outOfs, int outLen) throws ShortBufferException {
584
if (outLen < updateLength(inLen)) {
585
throw new ShortBufferException();
586
}
587
try {
588
ensureInitialized();
589
int k = 0;
590
if (encrypt) {
591
k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
592
0, out, outOfs, outLen);
593
} else {
594
int newPadBufferLen = 0;
595
if (paddingObj != null) {
596
if (padBufferLen != 0) {
597
// NSS throws up when called with data not in multiple
598
// of blocks. Try to work around this by holding the
599
// extra data in padBuffer.
600
if (padBufferLen != padBuffer.length) {
601
int bufCapacity = padBuffer.length - padBufferLen;
602
if (inLen > bufCapacity) {
603
bufferInputBytes(in, inOfs, bufCapacity);
604
inOfs += bufCapacity;
605
inLen -= bufCapacity;
606
} else {
607
bufferInputBytes(in, inOfs, inLen);
608
return 0;
609
}
610
}
611
k = token.p11.C_DecryptUpdate(session.id(),
612
0, padBuffer, 0, padBufferLen,
613
0, out, outOfs, outLen);
614
padBufferLen = 0;
615
}
616
newPadBufferLen = inLen & (blockSize - 1);
617
if (newPadBufferLen == 0) {
618
newPadBufferLen = padBuffer.length;
619
}
620
inLen -= newPadBufferLen;
621
}
622
if (inLen > 0) {
623
k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
624
inLen, 0, out, (outOfs + k), (outLen - k));
625
}
626
// update 'padBuffer' if using our own padding impl.
627
if (paddingObj != null) {
628
bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
629
}
630
}
631
bytesBuffered += (inLen - k);
632
return k;
633
} catch (PKCS11Exception e) {
634
if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
635
throw (ShortBufferException)
636
(new ShortBufferException().initCause(e));
637
}
638
// Some implementations such as the NSS Software Token do not
639
// cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate
640
// failure (as required by the PKCS#11 standard). See JDK-8258833
641
// for further information.
642
reset(true);
643
throw new ProviderException("update() failed", e);
644
}
645
}
646
647
private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
648
throws ShortBufferException {
649
int inLen = inBuffer.remaining();
650
if (inLen <= 0) {
651
return 0;
652
}
653
654
int outLen = outBuffer.remaining();
655
if (outLen < updateLength(inLen)) {
656
throw new ShortBufferException();
657
}
658
int origPos = inBuffer.position();
659
try {
660
ensureInitialized();
661
662
long inAddr = 0;
663
int inOfs = 0;
664
byte[] inArray = null;
665
666
if (inBuffer instanceof DirectBuffer) {
667
inAddr = ((DirectBuffer) inBuffer).address();
668
inOfs = origPos;
669
} else if (inBuffer.hasArray()) {
670
inArray = inBuffer.array();
671
inOfs = (origPos + inBuffer.arrayOffset());
672
}
673
674
long outAddr = 0;
675
int outOfs = 0;
676
byte[] outArray = null;
677
if (outBuffer instanceof DirectBuffer) {
678
outAddr = ((DirectBuffer) outBuffer).address();
679
outOfs = outBuffer.position();
680
} else {
681
if (outBuffer.hasArray()) {
682
outArray = outBuffer.array();
683
outOfs = (outBuffer.position() + outBuffer.arrayOffset());
684
} else {
685
outArray = new byte[outLen];
686
}
687
}
688
689
int k = 0;
690
if (encrypt) {
691
if (inAddr == 0 && inArray == null) {
692
inArray = new byte[inLen];
693
inBuffer.get(inArray);
694
} else {
695
inBuffer.position(origPos + inLen);
696
}
697
k = token.p11.C_EncryptUpdate(session.id(),
698
inAddr, inArray, inOfs, inLen,
699
outAddr, outArray, outOfs, outLen);
700
} else {
701
int newPadBufferLen = 0;
702
if (paddingObj != null) {
703
if (padBufferLen != 0) {
704
// NSS throws up when called with data not in multiple
705
// of blocks. Try to work around this by holding the
706
// extra data in padBuffer.
707
if (padBufferLen != padBuffer.length) {
708
int bufCapacity = padBuffer.length - padBufferLen;
709
if (inLen > bufCapacity) {
710
bufferInputBytes(inBuffer, bufCapacity);
711
inOfs += bufCapacity;
712
inLen -= bufCapacity;
713
} else {
714
bufferInputBytes(inBuffer, inLen);
715
return 0;
716
}
717
}
718
k = token.p11.C_DecryptUpdate(session.id(), 0,
719
padBuffer, 0, padBufferLen, outAddr, outArray,
720
outOfs, outLen);
721
padBufferLen = 0;
722
}
723
newPadBufferLen = inLen & (blockSize - 1);
724
if (newPadBufferLen == 0) {
725
newPadBufferLen = padBuffer.length;
726
}
727
inLen -= newPadBufferLen;
728
}
729
if (inLen > 0) {
730
if (inAddr == 0 && inArray == null) {
731
inArray = new byte[inLen];
732
inBuffer.get(inArray);
733
} else {
734
inBuffer.position(inBuffer.position() + inLen);
735
}
736
k += token.p11.C_DecryptUpdate(session.id(), inAddr,
737
inArray, inOfs, inLen, outAddr, outArray,
738
(outOfs + k), (outLen - k));
739
}
740
// update 'padBuffer' if using our own padding impl.
741
if (paddingObj != null && newPadBufferLen != 0) {
742
bufferInputBytes(inBuffer, newPadBufferLen);
743
}
744
}
745
bytesBuffered += (inLen - k);
746
if (!(outBuffer instanceof DirectBuffer) &&
747
!outBuffer.hasArray()) {
748
outBuffer.put(outArray, outOfs, k);
749
} else {
750
outBuffer.position(outBuffer.position() + k);
751
}
752
return k;
753
} catch (PKCS11Exception e) {
754
// Reset input buffer to its original position for
755
inBuffer.position(origPos);
756
if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
757
throw (ShortBufferException)
758
(new ShortBufferException().initCause(e));
759
}
760
// Some implementations such as the NSS Software Token do not
761
// cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate
762
// failure (as required by the PKCS#11 standard). See JDK-8258833
763
// for further information.
764
reset(true);
765
throw new ProviderException("update() failed", e);
766
}
767
}
768
769
private int implDoFinal(byte[] out, int outOfs, int outLen)
770
throws ShortBufferException, IllegalBlockSizeException,
771
BadPaddingException {
772
int requiredOutLen = doFinalLength(0);
773
if (outLen < requiredOutLen) {
774
throw new ShortBufferException();
775
}
776
boolean doCancel = true;
777
try {
778
ensureInitialized();
779
int k = 0;
780
if (encrypt) {
781
if (paddingObj != null) {
782
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
783
requiredOutLen - bytesBuffered);
784
k = token.p11.C_EncryptUpdate(session.id(),
785
0, padBuffer, 0, actualPadLen,
786
0, out, outOfs, outLen);
787
}
788
// Some implementations such as the NSS Software Token do not
789
// cancel the operation upon a C_EncryptUpdate failure (as
790
// required by the PKCS#11 standard). Cancel is not needed
791
// only after this point. See JDK-8258833 for further
792
// information.
793
doCancel = false;
794
k += token.p11.C_EncryptFinal(session.id(),
795
0, out, (outOfs + k), (outLen - k));
796
} else {
797
// Special handling to match SunJCE provider behavior
798
if (bytesBuffered == 0 && padBufferLen == 0) {
799
return 0;
800
}
801
if (paddingObj != null) {
802
if (padBufferLen != 0) {
803
k = token.p11.C_DecryptUpdate(session.id(), 0,
804
padBuffer, 0, padBufferLen, 0, padBuffer, 0,
805
padBuffer.length);
806
}
807
// Some implementations such as the NSS Software Token do not
808
// cancel the operation upon a C_DecryptUpdate failure (as
809
// required by the PKCS#11 standard). Cancel is not needed
810
// only after this point. See JDK-8258833 for further
811
// information.
812
doCancel = false;
813
k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
814
padBuffer.length - k);
815
816
int actualPadLen = paddingObj.unpad(padBuffer, k);
817
k -= actualPadLen;
818
System.arraycopy(padBuffer, 0, out, outOfs, k);
819
} else {
820
doCancel = false;
821
k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
822
outLen);
823
}
824
}
825
return k;
826
} catch (PKCS11Exception e) {
827
handleException(e);
828
throw new ProviderException("doFinal() failed", e);
829
} finally {
830
reset(doCancel);
831
}
832
}
833
834
private int implDoFinal(ByteBuffer outBuffer)
835
throws ShortBufferException, IllegalBlockSizeException,
836
BadPaddingException {
837
int outLen = outBuffer.remaining();
838
int requiredOutLen = doFinalLength(0);
839
if (outLen < requiredOutLen) {
840
throw new ShortBufferException();
841
}
842
843
boolean doCancel = true;
844
try {
845
ensureInitialized();
846
847
long outAddr = 0;
848
byte[] outArray = null;
849
int outOfs = 0;
850
if (outBuffer instanceof DirectBuffer) {
851
outAddr = ((DirectBuffer) outBuffer).address();
852
outOfs = outBuffer.position();
853
} else {
854
if (outBuffer.hasArray()) {
855
outArray = outBuffer.array();
856
outOfs = outBuffer.position() + outBuffer.arrayOffset();
857
} else {
858
outArray = new byte[outLen];
859
}
860
}
861
862
int k = 0;
863
864
if (encrypt) {
865
if (paddingObj != null) {
866
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
867
requiredOutLen - bytesBuffered);
868
k = token.p11.C_EncryptUpdate(session.id(),
869
0, padBuffer, 0, actualPadLen,
870
outAddr, outArray, outOfs, outLen);
871
}
872
// Some implementations such as the NSS Software Token do not
873
// cancel the operation upon a C_EncryptUpdate failure (as
874
// required by the PKCS#11 standard). Cancel is not needed
875
// only after this point. See JDK-8258833 for further
876
// information.
877
doCancel = false;
878
k += token.p11.C_EncryptFinal(session.id(),
879
outAddr, outArray, (outOfs + k), (outLen - k));
880
} else {
881
// Special handling to match SunJCE provider behavior
882
if (bytesBuffered == 0 && padBufferLen == 0) {
883
return 0;
884
}
885
886
if (paddingObj != null) {
887
if (padBufferLen != 0) {
888
k = token.p11.C_DecryptUpdate(session.id(),
889
0, padBuffer, 0, padBufferLen,
890
0, padBuffer, 0, padBuffer.length);
891
padBufferLen = 0;
892
}
893
// Some implementations such as the NSS Software Token do not
894
// cancel the operation upon a C_DecryptUpdate failure (as
895
// required by the PKCS#11 standard). Cancel is not needed
896
// only after this point. See JDK-8258833 for further
897
// information.
898
doCancel = false;
899
k += token.p11.C_DecryptFinal(session.id(),
900
0, padBuffer, k, padBuffer.length - k);
901
902
int actualPadLen = paddingObj.unpad(padBuffer, k);
903
k -= actualPadLen;
904
outArray = padBuffer;
905
outOfs = 0;
906
} else {
907
doCancel = false;
908
k = token.p11.C_DecryptFinal(session.id(),
909
outAddr, outArray, outOfs, outLen);
910
}
911
}
912
if ((!encrypt && paddingObj != null) ||
913
(!(outBuffer instanceof DirectBuffer) &&
914
!outBuffer.hasArray())) {
915
outBuffer.put(outArray, outOfs, k);
916
} else {
917
outBuffer.position(outBuffer.position() + k);
918
}
919
return k;
920
} catch (PKCS11Exception e) {
921
handleException(e);
922
throw new ProviderException("doFinal() failed", e);
923
} finally {
924
reset(doCancel);
925
}
926
}
927
928
private void handleException(PKCS11Exception e)
929
throws ShortBufferException, IllegalBlockSizeException {
930
long errorCode = e.getErrorCode();
931
if (errorCode == CKR_BUFFER_TOO_SMALL) {
932
throw (ShortBufferException)
933
(new ShortBufferException().initCause(e));
934
} else if (errorCode == CKR_DATA_LEN_RANGE ||
935
errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
936
throw (IllegalBlockSizeException)
937
(new IllegalBlockSizeException(e.toString()).initCause(e));
938
}
939
}
940
941
// see JCE spec
942
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
943
InvalidKeyException {
944
// XXX key wrapping
945
throw new UnsupportedOperationException("engineWrap()");
946
}
947
948
// see JCE spec
949
protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
950
int wrappedKeyType)
951
throws InvalidKeyException, NoSuchAlgorithmException {
952
// XXX key unwrapping
953
throw new UnsupportedOperationException("engineUnwrap()");
954
}
955
956
// see JCE spec
957
@Override
958
protected int engineGetKeySize(Key key) throws InvalidKeyException {
959
int n = P11SecretKeyFactory.convertKey
960
(token, key, keyAlgorithm).length();
961
return n;
962
}
963
964
private final void bufferInputBytes(byte[] in, int inOfs, int len) {
965
System.arraycopy(in, inOfs, padBuffer, padBufferLen, len);
966
padBufferLen += len;
967
bytesBuffered += len;
968
}
969
970
private final void bufferInputBytes(ByteBuffer inBuffer, int len) {
971
inBuffer.get(padBuffer, padBufferLen, len);
972
padBufferLen += len;
973
bytesBuffered += len;
974
}
975
}
976
977