11/*
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.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3030import java .security .Key ;
3131import java .security .interfaces .*;
3232import java .security .spec .*;
33+ import java .util .Arrays ;
3334
3435import javax .crypto .*;
3536import javax .crypto .spec .*;
6162 */
6263public final class CRSACipher extends CipherSpi {
6364
65+ private static final int ERROR_INVALID_PARAMETER = 0x57 ;
66+ private static final int NTE_INVALID_PARAMETER = 0x80090027 ;
67+
6468 // constant for an empty byte array
6569 private final static byte [] B0 = new byte [0 ];
6670
@@ -101,6 +105,8 @@ public final class CRSACipher extends CipherSpi {
101105 // cipher parameter for TLS RSA premaster secret
102106 private AlgorithmParameterSpec spec = null ;
103107
108+ private boolean forTlsPremasterSecret = false ;
109+
104110 // the source of randomness
105111 private SecureRandom random ;
106112
@@ -171,6 +177,9 @@ protected void engineInit(int opmode, Key key,
171177 }
172178 spec = params ;
173179 this .random = random ; // for TLS RSA premaster secret
180+ this .forTlsPremasterSecret = true ;
181+ } else {
182+ this .forTlsPremasterSecret = false ;
174183 }
175184 init (opmode , key );
176185 }
@@ -277,8 +286,7 @@ private void update(byte[] in, int inOfs, int inLen) {
277286 }
278287
279288 // internal doFinal() method. Here we perform the actual RSA operation
280- private byte [] doFinal () throws BadPaddingException ,
281- IllegalBlockSizeException {
289+ private byte [] doFinal () throws IllegalBlockSizeException {
282290 if (bufOfs > buffer .length ) {
283291 throw new IllegalBlockSizeException ("Data must not be longer "
284292 + "than " + (buffer .length - paddingLength ) + " bytes" );
@@ -307,7 +315,7 @@ private byte[] doFinal() throws BadPaddingException,
307315 throw new AssertionError ("Internal error" );
308316 }
309317
310- } catch (KeyException e ) {
318+ } catch (KeyException | BadPaddingException e ) {
311319 throw new ProviderException (e );
312320
313321 } finally {
@@ -330,14 +338,14 @@ protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
330338
331339 // see JCE spec
332340 protected byte [] engineDoFinal (byte [] in , int inOfs , int inLen )
333- throws BadPaddingException , IllegalBlockSizeException {
341+ throws IllegalBlockSizeException {
334342 update (in , inOfs , inLen );
335343 return doFinal ();
336344 }
337345
338346 // see JCE spec
339347 protected int engineDoFinal (byte [] in , int inOfs , int inLen , byte [] out ,
340- int outOfs ) throws ShortBufferException , BadPaddingException ,
348+ int outOfs ) throws ShortBufferException ,
341349 IllegalBlockSizeException {
342350 if (outputSize > out .length - outOfs ) {
343351 throw new ShortBufferException
@@ -353,6 +361,7 @@ protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
353361 // see JCE spec
354362 protected byte [] engineWrap (Key key ) throws InvalidKeyException ,
355363 IllegalBlockSizeException {
364+
356365 byte [] encoded = key .getEncoded (); // TODO - unextractable key
357366 if ((encoded == null ) || (encoded .length == 0 )) {
358367 throw new InvalidKeyException ("Could not obtain encoded key" );
@@ -361,12 +370,7 @@ protected byte[] engineWrap(Key key) throws InvalidKeyException,
361370 throw new InvalidKeyException ("Key is too long for wrapping" );
362371 }
363372 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 ();
370374 }
371375
372376 // see JCE spec
@@ -387,31 +391,31 @@ protected java.security.Key engineUnwrap(byte[] wrappedKey,
387391 update (wrappedKey , 0 , wrappedKey .length );
388392 try {
389393 encoded = doFinal ();
390- } catch (BadPaddingException e ) {
391- if (isTlsRsaPremasterSecret ) {
392- failover = e ;
393- } else {
394- throw new InvalidKeyException ("Unwrapping failed" , e );
395- }
396394 } catch (IllegalBlockSizeException e ) {
397395 // should not occur, handled with length check above
398396 throw new InvalidKeyException ("Unwrapping failed" , e );
399397 }
400398
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 );
405411 }
406412
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+ }
412418 }
413-
414- return constructKey (encoded , algorithm , type );
415419 }
416420
417421 // see JCE spec
@@ -495,7 +499,23 @@ private static Key constructKey(byte[] encodedKey,
495499 * Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY.
496500 * It expects and returns ciphertext data in big-endian form.
497501 */
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 ;
500520
501521}
0 commit comments