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/sun/security/pkcs11/P11PSSSignature.java
38919 views
1
/*
2
* Copyright (c) 2019, 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 sun.security.pkcs11;
27
28
import java.io.ByteArrayOutputStream;
29
import java.io.IOException;
30
import java.nio.ByteBuffer;
31
import sun.nio.ch.DirectBuffer;
32
33
import java.util.Hashtable;
34
import java.util.Arrays;
35
import java.security.*;
36
import java.security.spec.AlgorithmParameterSpec;
37
import java.security.spec.MGF1ParameterSpec;
38
import java.security.spec.PSSParameterSpec;
39
import java.security.interfaces.*;
40
import sun.security.pkcs11.wrapper.*;
41
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
42
43
44
/**
45
* RSASSA-PSS Signature implementation class. This class currently supports the
46
* following algorithms:
47
*
48
* . RSA-PSS:
49
* . RSASSA-PSS
50
* . SHA1withRSASSA-PSS
51
* . SHA224withRSASSA-PSS
52
* . SHA256withRSASSA-PSS
53
* . SHA384withRSASSA-PSS
54
* . SHA512withRSASSA-PSS
55
*
56
* Note that the underlying PKCS#11 token may support complete signature
57
* algorithm (e.g. CKM_<md>_RSA_PKCS_PSS), or it may just
58
* implement the signature algorithm without hashing (i.e. CKM_RSA_PKCS_PSS).
59
* This class uses what is available and adds whatever extra processing
60
* is needed.
61
*
62
* @since 13
63
*/
64
final class P11PSSSignature extends SignatureSpi {
65
66
private final static boolean DEBUG = false;
67
68
// mappings of digest algorithms and their output length in bytes
69
private static final Hashtable<String, Integer> DIGEST_LENGTHS =
70
new Hashtable<String, Integer>();
71
72
static {
73
DIGEST_LENGTHS.put("SHA-1", 20);
74
DIGEST_LENGTHS.put("SHA", 20);
75
DIGEST_LENGTHS.put("SHA1", 20);
76
DIGEST_LENGTHS.put("SHA-224", 28);
77
DIGEST_LENGTHS.put("SHA224", 28);
78
DIGEST_LENGTHS.put("SHA-256", 32);
79
DIGEST_LENGTHS.put("SHA256", 32);
80
DIGEST_LENGTHS.put("SHA-384", 48);
81
DIGEST_LENGTHS.put("SHA384", 48);
82
DIGEST_LENGTHS.put("SHA-512", 64);
83
DIGEST_LENGTHS.put("SHA512", 64);
84
DIGEST_LENGTHS.put("SHA-512/224", 28);
85
DIGEST_LENGTHS.put("SHA512/224", 28);
86
DIGEST_LENGTHS.put("SHA-512/256", 32);
87
DIGEST_LENGTHS.put("SHA512/256", 32);
88
}
89
90
// utility method for comparing digest algorithms
91
// NOTE that first argument is assumed to be standard digest name
92
private static boolean isDigestEqual(String stdAlg, String givenAlg) {
93
if (stdAlg == null || givenAlg == null) return false;
94
95
if (givenAlg.indexOf("-") != -1) {
96
return stdAlg.equalsIgnoreCase(givenAlg);
97
} else {
98
if (stdAlg.equals("SHA-1")) {
99
return (givenAlg.equalsIgnoreCase("SHA")
100
|| givenAlg.equalsIgnoreCase("SHA1"));
101
} else {
102
StringBuilder sb = new StringBuilder(givenAlg);
103
// case-insensitive check
104
if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) {
105
givenAlg = sb.insert(3, "-").toString();
106
return stdAlg.equalsIgnoreCase(givenAlg);
107
} else {
108
throw new ProviderException("Unsupported digest algorithm "
109
+ givenAlg);
110
}
111
}
112
}
113
}
114
115
// token instance
116
private final Token token;
117
118
// algorithm name
119
private final String algorithm;
120
121
// name of the key algorithm, currently just RSA
122
private static final String KEY_ALGO = "RSA";
123
124
// mechanism id
125
private final CK_MECHANISM mechanism;
126
127
// type, one of T_* below
128
private final int type;
129
130
// key instance used, if init*() was called
131
private P11Key p11Key = null;
132
133
// PSS parameters and the flag controlling its access
134
private PSSParameterSpec sigParams = null;
135
private boolean isActive = false;
136
137
// message digest alg, if implied by the algorithm name
138
private final String mdAlg;
139
140
// message digest, if we do the digesting ourselves
141
private MessageDigest md = null;
142
143
// associated session, if any
144
private Session session;
145
146
// mode, one of M_* below
147
private int mode;
148
149
// flag indicating whether an operation is initialized
150
private boolean initialized = false;
151
152
// buffer, for update(byte)
153
private final byte[] buffer = new byte[1];
154
155
// total number of bytes processed in current operation
156
private int bytesProcessed = 0;
157
158
// constant for signing mode
159
private final static int M_SIGN = 1;
160
// constant for verification mode
161
private final static int M_VERIFY = 2;
162
163
// constant for type digesting, we do the hashing ourselves
164
private final static int T_DIGEST = 1;
165
// constant for type update, token does everything
166
private final static int T_UPDATE = 2;
167
168
P11PSSSignature(Token token, String algorithm, long mechId)
169
throws NoSuchAlgorithmException, PKCS11Exception {
170
super();
171
this.token = token;
172
this.algorithm = algorithm;
173
this.mechanism = new CK_MECHANISM(mechId);
174
int idx = algorithm.indexOf("with");
175
this.mdAlg = (idx == -1? null : algorithm.substring(0, idx));
176
switch ((int)mechId) {
177
case (int)CKM_SHA1_RSA_PKCS_PSS:
178
case (int)CKM_SHA224_RSA_PKCS_PSS:
179
case (int)CKM_SHA256_RSA_PKCS_PSS:
180
case (int)CKM_SHA384_RSA_PKCS_PSS:
181
case (int)CKM_SHA512_RSA_PKCS_PSS:
182
type = T_UPDATE;
183
break;
184
case (int)CKM_RSA_PKCS_PSS:
185
type = T_DIGEST;
186
break;
187
default:
188
throw new ProviderException("Unsupported mechanism: " + mechId);
189
}
190
this.md = null;
191
}
192
193
private void ensureInitialized() throws SignatureException {
194
token.ensureValid();
195
if (this.p11Key == null) {
196
throw new SignatureException("Missing key");
197
}
198
if (this.sigParams == null) {
199
if (this.mdAlg == null) {
200
// PSS Parameters are required for signature verification
201
throw new SignatureException
202
("Parameters required for RSASSA-PSS signature");
203
} else {
204
int saltLen = DIGEST_LENGTHS.get(this.mdAlg).intValue();
205
// generate default params for both sign and verify?
206
this.sigParams = new PSSParameterSpec(this.mdAlg,
207
"MGF1", new MGF1ParameterSpec(this.mdAlg),
208
saltLen, PSSParameterSpec.TRAILER_FIELD_BC);
209
this.mechanism.setParameter(new CK_RSA_PKCS_PSS_PARAMS(
210
this.mdAlg, "MGF1", this.mdAlg,
211
DIGEST_LENGTHS.get(this.mdAlg).intValue()));
212
}
213
}
214
215
if (initialized == false) {
216
initialize();
217
}
218
}
219
220
// reset the states to the pre-initialized values
221
private void reset(boolean doCancel) {
222
if (!initialized) {
223
return;
224
}
225
initialized = false;
226
227
try {
228
if (session == null) {
229
return;
230
}
231
232
if (doCancel && token.explicitCancel) {
233
cancelOperation();
234
}
235
} finally {
236
p11Key.releaseKeyID();
237
mechanism.freeHandle();
238
session = token.releaseSession(session);
239
isActive = false;
240
}
241
}
242
243
private void cancelOperation() {
244
token.ensureValid();
245
if (DEBUG) System.out.print("Cancelling operation");
246
247
// cancel operation by finishing it; avoid killSession as some
248
// hardware vendors may require re-login
249
try {
250
if (mode == M_SIGN) {
251
if (type == T_UPDATE) {
252
if (DEBUG) System.out.println(" by C_SignFinal");
253
token.p11.C_SignFinal(session.id(), 0);
254
} else {
255
byte[] digest =
256
(md == null? new byte[0] : md.digest());
257
if (DEBUG) System.out.println(" by C_Sign");
258
token.p11.C_Sign(session.id(), digest);
259
}
260
} else { // M_VERIFY
261
byte[] signature =
262
new byte[(p11Key.length() + 7) >> 3];
263
if (type == T_UPDATE) {
264
if (DEBUG) System.out.println(" by C_VerifyFinal");
265
token.p11.C_VerifyFinal(session.id(), signature);
266
} else {
267
byte[] digest =
268
(md == null? new byte[0] : md.digest());
269
if (DEBUG) System.out.println(" by C_Verify");
270
token.p11.C_Verify(session.id(), digest, signature);
271
}
272
}
273
} catch (PKCS11Exception e) {
274
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
275
// Cancel Operation may be invoked after an error on a PKCS#11
276
// call. If the operation inside the token was already cancelled,
277
// do not fail here. This is part of a defensive mechanism for
278
// PKCS#11 libraries that do not strictly follow the standard.
279
return;
280
}
281
if (mode == M_SIGN) {
282
throw new ProviderException("cancel failed", e);
283
}
284
// ignore failure for verification
285
}
286
}
287
288
// assumes current state is initialized == false
289
private void initialize() {
290
if (DEBUG) System.out.println("Initializing");
291
292
if (p11Key == null) {
293
throw new ProviderException(
294
"No Key found, call initSign/initVerify first");
295
}
296
297
long keyID = p11Key.getKeyID();
298
try {
299
if (session == null) {
300
session = token.getOpSession();
301
}
302
if (mode == M_SIGN) {
303
token.p11.C_SignInit(session.id(), mechanism, keyID);
304
} else {
305
token.p11.C_VerifyInit(session.id(), mechanism, keyID);
306
}
307
} catch (PKCS11Exception e) {
308
p11Key.releaseKeyID();
309
session = token.releaseSession(session);
310
throw new ProviderException("Initialization failed", e);
311
}
312
if (bytesProcessed != 0) {
313
bytesProcessed = 0;
314
if (md != null) {
315
md.reset();
316
}
317
}
318
initialized = true;
319
isActive = false;
320
if (DEBUG) System.out.println("Initialized");
321
}
322
323
private void checkKeySize(Key key) throws InvalidKeyException {
324
if (DEBUG) System.out.print("Checking Key");
325
326
if (!key.getAlgorithm().equals(KEY_ALGO)) {
327
throw new InvalidKeyException("Only " + KEY_ALGO +
328
" keys are supported");
329
}
330
331
CK_MECHANISM_INFO mechInfo = null;
332
try {
333
mechInfo = token.getMechanismInfo(mechanism.mechanism);
334
} catch (PKCS11Exception e) {
335
// should not happen, ignore for now
336
if (DEBUG) {
337
System.out.println("Unexpected exception");
338
e.printStackTrace();
339
}
340
}
341
342
int keySize = 0; // in bytes
343
if (mechInfo != null) {
344
// check against available native info
345
int minKeySize = (int) mechInfo.ulMinKeySize;
346
int maxKeySize = (int) mechInfo.ulMaxKeySize;
347
if (key instanceof P11Key) {
348
keySize = (((P11Key) key).length() + 7) >> 3;
349
} else if (key instanceof RSAKey) {
350
keySize = ((RSAKey) key).getModulus().bitLength() >> 3;
351
} else {
352
throw new InvalidKeyException("Unrecognized key type " + key);
353
}
354
if ((minKeySize != -1) && (keySize < minKeySize)) {
355
throw new InvalidKeyException(KEY_ALGO +
356
" key must be at least " + minKeySize + " bytes");
357
}
358
if ((maxKeySize != -1) && (keySize > maxKeySize)) {
359
throw new InvalidKeyException(KEY_ALGO +
360
" key must be at most " + maxKeySize + " bytes");
361
}
362
}
363
if (this.sigParams != null) {
364
String digestAlg = this.sigParams.getDigestAlgorithm();
365
int sLen = this.sigParams.getSaltLength();
366
int hLen = DIGEST_LENGTHS.get(digestAlg).intValue();
367
int minKeyLen = Math.addExact(Math.addExact(sLen, hLen), 2);
368
369
if (keySize < minKeyLen) {
370
throw new InvalidKeyException
371
("Key is too short for current params, need min " + minKeyLen);
372
}
373
}
374
}
375
376
private void setSigParams(AlgorithmParameterSpec p)
377
throws InvalidAlgorithmParameterException {
378
if (p == null) {
379
throw new InvalidAlgorithmParameterException("PSS Parameter required");
380
}
381
if (!(p instanceof PSSParameterSpec)) {
382
throw new InvalidAlgorithmParameterException
383
("Only PSSParameterSpec is supported");
384
}
385
// no need to validate again if same as current signature parameters
386
PSSParameterSpec params = (PSSParameterSpec) p;
387
if (params == this.sigParams) return;
388
389
String digestAlgorithm = params.getDigestAlgorithm();
390
if (this.mdAlg != null && !isDigestEqual(digestAlgorithm, this.mdAlg)) {
391
throw new InvalidAlgorithmParameterException
392
("Digest algorithm in Signature parameters must be " +
393
this.mdAlg);
394
}
395
Integer digestLen = DIGEST_LENGTHS.get(digestAlgorithm);
396
if (digestLen == null) {
397
throw new InvalidAlgorithmParameterException
398
("Unsupported digest algorithm in Signature parameters: " +
399
digestAlgorithm);
400
}
401
if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
402
throw new InvalidAlgorithmParameterException("Only supports MGF1");
403
}
404
if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
405
throw new InvalidAlgorithmParameterException
406
("Only supports TrailerFieldBC(1)");
407
}
408
int saltLen = params.getSaltLength();
409
if (this.p11Key != null) {
410
int maxSaltLen = ((this.p11Key.length() + 7) >> 3) - digestLen.intValue() - 2;
411
412
if (DEBUG) {
413
System.out.println("Max saltLen = " + maxSaltLen);
414
System.out.println("Curr saltLen = " + saltLen);
415
}
416
if (maxSaltLen < 0 || saltLen > maxSaltLen) {
417
throw new InvalidAlgorithmParameterException("Invalid with current key size");
418
}
419
} else {
420
if (DEBUG) System.out.println("No key available for validating saltLen");
421
}
422
423
// validated, now try to store the parameter internally
424
try {
425
this.mechanism.setParameter(
426
new CK_RSA_PKCS_PSS_PARAMS(digestAlgorithm, "MGF1",
427
digestAlgorithm, saltLen));
428
this.sigParams = params;
429
} catch (IllegalArgumentException iae) {
430
throw new InvalidAlgorithmParameterException(iae);
431
}
432
}
433
434
// see JCA spec
435
@Override
436
protected void engineInitVerify(PublicKey publicKey)
437
throws InvalidKeyException {
438
439
if (publicKey == null) {
440
throw new InvalidKeyException("Key must not be null");
441
}
442
443
// Need to check key length whenever a new key is set
444
if (publicKey != p11Key) {
445
checkKeySize(publicKey);
446
}
447
448
reset(true);
449
mode = M_VERIFY;
450
p11Key = P11KeyFactory.convertKey(token, publicKey, KEY_ALGO);
451
452
// For PSS, defer PKCS11 initialization calls to update/doFinal as it
453
// needs both key and params
454
}
455
456
// see JCA spec
457
@Override
458
protected void engineInitSign(PrivateKey privateKey)
459
throws InvalidKeyException {
460
461
if (privateKey == null) {
462
throw new InvalidKeyException("Key must not be null");
463
}
464
465
// Need to check RSA key length whenever a new key is set
466
if (privateKey != p11Key) {
467
checkKeySize(privateKey);
468
}
469
470
reset(true);
471
mode = M_SIGN;
472
p11Key = P11KeyFactory.convertKey(token, privateKey, KEY_ALGO);
473
474
// For PSS, defer PKCS11 initialization calls to update/doFinal as it
475
// needs both key and params
476
}
477
478
// see JCA spec
479
@Override
480
protected void engineUpdate(byte b) throws SignatureException {
481
ensureInitialized();
482
isActive = true;
483
buffer[0] = b;
484
engineUpdate(buffer, 0, 1);
485
}
486
487
// see JCA spec
488
@Override
489
protected void engineUpdate(byte[] b, int ofs, int len)
490
throws SignatureException {
491
ensureInitialized();
492
if (len == 0) {
493
return;
494
}
495
// check for overflow
496
if (len + bytesProcessed < 0) {
497
throw new ProviderException("Processed bytes limits exceeded.");
498
}
499
isActive = true;
500
switch (type) {
501
case T_UPDATE:
502
try {
503
if (mode == M_SIGN) {
504
System.out.println(this + ": Calling C_SignUpdate");
505
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
506
} else {
507
System.out.println(this + ": Calling C_VerfifyUpdate");
508
token.p11.C_VerifyUpdate(session.id(), 0, b, ofs, len);
509
}
510
bytesProcessed += len;
511
} catch (PKCS11Exception e) {
512
reset(false);
513
throw new ProviderException(e);
514
}
515
break;
516
case T_DIGEST:
517
// should not happen as this should be covered by earlier checks
518
if (md == null) {
519
throw new ProviderException("PSS Parameters required");
520
}
521
md.update(b, ofs, len);
522
bytesProcessed += len;
523
break;
524
default:
525
throw new ProviderException("Internal error");
526
}
527
}
528
529
// see JCA spec
530
@Override
531
protected void engineUpdate(ByteBuffer byteBuffer) {
532
try {
533
ensureInitialized();
534
} catch (SignatureException se) {
535
throw new ProviderException(se);
536
}
537
int len = byteBuffer.remaining();
538
if (len <= 0) {
539
return;
540
}
541
isActive = true;
542
switch (type) {
543
case T_UPDATE:
544
if (byteBuffer instanceof DirectBuffer == false) {
545
// cannot do better than default impl
546
super.engineUpdate(byteBuffer);
547
return;
548
}
549
long addr = ((DirectBuffer)byteBuffer).address();
550
int ofs = byteBuffer.position();
551
try {
552
if (mode == M_SIGN) {
553
System.out.println(this + ": Calling C_SignUpdate");
554
token.p11.C_SignUpdate
555
(session.id(), addr + ofs, null, 0, len);
556
} else {
557
System.out.println(this + ": Calling C_VerifyUpdate");
558
token.p11.C_VerifyUpdate
559
(session.id(), addr + ofs, null, 0, len);
560
}
561
bytesProcessed += len;
562
byteBuffer.position(ofs + len);
563
} catch (PKCS11Exception e) {
564
reset(false);
565
throw new ProviderException("Update failed", e);
566
}
567
break;
568
case T_DIGEST:
569
// should not happen as this should be covered by earlier checks
570
if (md == null) {
571
throw new ProviderException("PSS Parameters required");
572
}
573
md.update(byteBuffer);
574
bytesProcessed += len;
575
break;
576
default:
577
reset(false);
578
throw new ProviderException("Internal error");
579
}
580
}
581
582
// see JCA spec
583
@Override
584
protected byte[] engineSign() throws SignatureException {
585
ensureInitialized();
586
boolean doCancel = true;
587
if (DEBUG) System.out.print("Generating signature");
588
try {
589
byte[] signature;
590
if (type == T_UPDATE) {
591
if (DEBUG) System.out.println(" by C_SignFinal");
592
signature = token.p11.C_SignFinal(session.id(), 0);
593
} else {
594
if (md == null) {
595
throw new ProviderException("PSS Parameters required");
596
}
597
byte[] digest = md.digest();
598
if (DEBUG) System.out.println(" by C_Sign");
599
signature = token.p11.C_Sign(session.id(), digest);
600
}
601
doCancel = false;
602
return signature;
603
} catch (PKCS11Exception pe) {
604
// As per the PKCS#11 standard, C_Sign and C_SignFinal may only
605
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
606
// successful calls to determine the output length. However,
607
// these cases are handled at OpenJDK's libj2pkcs11 native
608
// library. Thus, doCancel can safely be 'false' here.
609
doCancel = false;
610
throw new ProviderException(pe);
611
} catch (ProviderException e) {
612
throw e;
613
} finally {
614
reset(doCancel);
615
}
616
}
617
618
// see JCA spec
619
@Override
620
protected boolean engineVerify(byte[] signature) throws SignatureException {
621
ensureInitialized();
622
boolean doCancel = true;
623
if (DEBUG) System.out.print("Verifying signature");
624
try {
625
if (type == T_UPDATE) {
626
if (DEBUG) System.out.println(" by C_VerifyFinal");
627
token.p11.C_VerifyFinal(session.id(), signature);
628
} else {
629
if (md == null) {
630
throw new ProviderException("PSS Parameters required");
631
}
632
byte[] digest = md.digest();
633
if (DEBUG) System.out.println(" by C_Verify");
634
token.p11.C_Verify(session.id(), digest, signature);
635
}
636
doCancel = false;
637
return true;
638
} catch (PKCS11Exception pe) {
639
doCancel = false;
640
long errorCode = pe.getErrorCode();
641
if (errorCode == CKR_SIGNATURE_INVALID) {
642
return false;
643
}
644
if (errorCode == CKR_SIGNATURE_LEN_RANGE) {
645
// return false rather than throwing an exception
646
return false;
647
}
648
// ECF bug?
649
if (errorCode == CKR_DATA_LEN_RANGE) {
650
return false;
651
}
652
throw new ProviderException(pe);
653
} catch (ProviderException e) {
654
throw e;
655
} finally {
656
reset(doCancel);
657
}
658
}
659
660
// see JCA spec
661
@SuppressWarnings("deprecation")
662
@Override
663
protected void engineSetParameter(String param, Object value)
664
throws InvalidParameterException {
665
throw new UnsupportedOperationException("setParameter() not supported");
666
}
667
668
// see JCA spec
669
@Override
670
protected void engineSetParameter(AlgorithmParameterSpec params)
671
throws InvalidAlgorithmParameterException {
672
// disallow changing parameters when update has been called
673
if (isActive) {
674
throw new ProviderException
675
("Cannot set parameters during operations");
676
}
677
setSigParams(params);
678
if (type == T_DIGEST) {
679
try {
680
this.md = MessageDigest.getInstance(sigParams.getDigestAlgorithm());
681
} catch (NoSuchAlgorithmException nsae) {
682
throw new InvalidAlgorithmParameterException(nsae);
683
}
684
}
685
}
686
687
// see JCA spec
688
@SuppressWarnings("deprecation")
689
@Override
690
protected Object engineGetParameter(String param)
691
throws InvalidParameterException {
692
throw new UnsupportedOperationException("getParameter() not supported");
693
}
694
695
// see JCA spec
696
@Override
697
protected AlgorithmParameters engineGetParameters() {
698
if (this.sigParams != null) {
699
try {
700
AlgorithmParameters ap = AlgorithmParameters.getInstance("RSASSA-PSS");
701
ap.init(this.sigParams);
702
return ap;
703
} catch (GeneralSecurityException e) {
704
throw new RuntimeException(e);
705
}
706
}
707
return null;
708
}
709
}
710
711