1
1
/*
2
- * Copyright (c) 2005, 2020 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2005, 2023 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
30
30
import java .security .Key ;
31
31
import java .security .interfaces .*;
32
32
import java .security .spec .*;
33
+ import java .util .Arrays ;
33
34
34
35
import javax .crypto .*;
35
36
import javax .crypto .spec .*;
61
62
*/
62
63
public final class CRSACipher extends CipherSpi {
63
64
65
+ private static final int ERROR_INVALID_PARAMETER = 0x57 ;
66
+ private static final int NTE_INVALID_PARAMETER = 0x80090027 ;
67
+
64
68
// constant for an empty byte array
65
69
private final static byte [] B0 = new byte [0 ];
66
70
@@ -101,6 +105,8 @@ public final class CRSACipher extends CipherSpi {
101
105
// cipher parameter for TLS RSA premaster secret
102
106
private AlgorithmParameterSpec spec = null ;
103
107
108
+ private boolean forTlsPremasterSecret = false ;
109
+
104
110
// the source of randomness
105
111
private SecureRandom random ;
106
112
@@ -171,6 +177,9 @@ protected void engineInit(int opmode, Key key,
171
177
}
172
178
spec = params ;
173
179
this .random = random ; // for TLS RSA premaster secret
180
+ this .forTlsPremasterSecret = true ;
181
+ } else {
182
+ this .forTlsPremasterSecret = false ;
174
183
}
175
184
init (opmode , key );
176
185
}
@@ -277,8 +286,7 @@ private void update(byte[] in, int inOfs, int inLen) {
277
286
}
278
287
279
288
// internal doFinal() method. Here we perform the actual RSA operation
280
- private byte [] doFinal () throws BadPaddingException ,
281
- IllegalBlockSizeException {
289
+ private byte [] doFinal () throws IllegalBlockSizeException {
282
290
if (bufOfs > buffer .length ) {
283
291
throw new IllegalBlockSizeException ("Data must not be longer "
284
292
+ "than " + (buffer .length - paddingLength ) + " bytes" );
@@ -307,7 +315,7 @@ private byte[] doFinal() throws BadPaddingException,
307
315
throw new AssertionError ("Internal error" );
308
316
}
309
317
310
- } catch (KeyException e ) {
318
+ } catch (KeyException | BadPaddingException e ) {
311
319
throw new ProviderException (e );
312
320
313
321
} finally {
@@ -330,14 +338,14 @@ protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
330
338
331
339
// see JCE spec
332
340
protected byte [] engineDoFinal (byte [] in , int inOfs , int inLen )
333
- throws BadPaddingException , IllegalBlockSizeException {
341
+ throws IllegalBlockSizeException {
334
342
update (in , inOfs , inLen );
335
343
return doFinal ();
336
344
}
337
345
338
346
// see JCE spec
339
347
protected int engineDoFinal (byte [] in , int inOfs , int inLen , byte [] out ,
340
- int outOfs ) throws ShortBufferException , BadPaddingException ,
348
+ int outOfs ) throws ShortBufferException ,
341
349
IllegalBlockSizeException {
342
350
if (outputSize > out .length - outOfs ) {
343
351
throw new ShortBufferException
@@ -353,6 +361,7 @@ protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
353
361
// see JCE spec
354
362
protected byte [] engineWrap (Key key ) throws InvalidKeyException ,
355
363
IllegalBlockSizeException {
364
+
356
365
byte [] encoded = key .getEncoded (); // TODO - unextractable key
357
366
if ((encoded == null ) || (encoded .length == 0 )) {
358
367
throw new InvalidKeyException ("Could not obtain encoded key" );
@@ -361,12 +370,7 @@ protected byte[] engineWrap(Key key) throws InvalidKeyException,
361
370
throw new InvalidKeyException ("Key is too long for wrapping" );
362
371
}
363
372
update (encoded , 0 , encoded .length );
364
- try {
365
- return doFinal ();
366
- } catch (BadPaddingException e ) {
367
- // should not occur
368
- throw new InvalidKeyException ("Wrapping failed" , e );
369
- }
373
+ return doFinal ();
370
374
}
371
375
372
376
// see JCE spec
@@ -387,31 +391,31 @@ protected java.security.Key engineUnwrap(byte[] wrappedKey,
387
391
update (wrappedKey , 0 , wrappedKey .length );
388
392
try {
389
393
encoded = doFinal ();
390
- } catch (BadPaddingException e ) {
391
- if (isTlsRsaPremasterSecret ) {
392
- failover = e ;
393
- } else {
394
- throw new InvalidKeyException ("Unwrapping failed" , e );
395
- }
396
394
} catch (IllegalBlockSizeException e ) {
397
395
// should not occur, handled with length check above
398
396
throw new InvalidKeyException ("Unwrapping failed" , e );
399
397
}
400
398
401
- if (isTlsRsaPremasterSecret ) {
402
- if (!(spec instanceof TlsRsaPremasterSecretParameterSpec )) {
403
- throw new IllegalStateException (
404
- "No TlsRsaPremasterSecretParameterSpec specified" );
399
+ try {
400
+ if (isTlsRsaPremasterSecret ) {
401
+ if (!forTlsPremasterSecret ) {
402
+ throw new IllegalStateException (
403
+ "No TlsRsaPremasterSecretParameterSpec specified" );
404
+ }
405
+
406
+ // polish the TLS premaster secret
407
+ encoded = KeyUtil .checkTlsPreMasterSecretKey (
408
+ ((TlsRsaPremasterSecretParameterSpec ) spec ).getClientVersion (),
409
+ ((TlsRsaPremasterSecretParameterSpec ) spec ).getServerVersion (),
410
+ random , encoded , encoded == null );
405
411
}
406
412
407
- // polish the TLS premaster secret
408
- encoded = KeyUtil . checkTlsPreMasterSecretKey (
409
- (( TlsRsaPremasterSecretParameterSpec ) spec ). getClientVersion (),
410
- (( TlsRsaPremasterSecretParameterSpec ) spec ). getServerVersion (),
411
- random , encoded , ( failover != null ));
413
+ return constructKey ( encoded , algorithm , type );
414
+ } finally {
415
+ if ( encoded != null ) {
416
+ Arrays . fill ( encoded , ( byte ) 0 );
417
+ }
412
418
}
413
-
414
- return constructKey (encoded , algorithm , type );
415
419
}
416
420
417
421
// see JCE spec
@@ -495,7 +499,23 @@ private static Key constructKey(byte[] encodedKey,
495
499
* Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
496
500
* It expects and returns ciphertext data in big-endian form.
497
501
*/
498
- private native static byte [] encryptDecrypt (byte [] data , int dataSize ,
499
- long hCryptKey , boolean doEncrypt ) throws KeyException ;
502
+ private byte [] encryptDecrypt (byte [] data , int dataSize ,
503
+ long hCryptKey , boolean doEncrypt ) throws KeyException , BadPaddingException {
504
+ int [] returnStatus = new int [1 ];
505
+ byte [] result = encryptDecrypt (returnStatus , data , dataSize , hCryptKey , doEncrypt );
506
+ if ((returnStatus [0 ] == ERROR_INVALID_PARAMETER ) || (returnStatus [0 ] == NTE_INVALID_PARAMETER )) {
507
+ if (forTlsPremasterSecret ) {
508
+ result = null ;
509
+ } else {
510
+ throw new BadPaddingException ("Error " + returnStatus [0 ] + " returned by MSCAPI" );
511
+ }
512
+ } else if (returnStatus [0 ] != 0 ) {
513
+ throw new KeyException ("Error " + returnStatus [0 ] + " returned by MSCAPI" );
514
+ }
515
+
516
+ return result ;
517
+ }
518
+ private static native byte [] encryptDecrypt (int [] returnStatus , byte [] data , int dataSize ,
519
+ long key , boolean doEncrypt ) throws KeyException ;
500
520
501
521
}
0 commit comments