3131import org .bouncycastle .crypto .encodings .OAEPEncoding ;
3232import org .bouncycastle .crypto .engines .RSABlindedEngine ;
3333import org .bouncycastle .crypto .params .ParametersWithRandom ;
34+ import org .bouncycastle .crypto .params .RSAKeyParameters ;
35+ import org .bouncycastle .crypto .params .RSAPrivateCrtKeyParameters ;
36+ import org .bouncycastle .crypto .tls .TlsRsaKeyExchange ;
3437import org .bouncycastle .jcajce .provider .asymmetric .util .BaseCipherSpi ;
3538import org .bouncycastle .jcajce .provider .util .BadBlockException ;
3639import org .bouncycastle .jcajce .provider .util .DigestFactory ;
40+ import org .bouncycastle .jcajce .spec .TLSRSAPremasterSecretParameterSpec ;
3741import org .bouncycastle .jcajce .util .BCJcaJceHelper ;
3842import org .bouncycastle .jcajce .util .JcaJceHelper ;
3943import org .bouncycastle .util .Strings ;
@@ -49,6 +53,8 @@ public class CipherSpi
4953 private boolean publicKeyOnly = false ;
5054 private boolean privateKeyOnly = false ;
5155 private ErasableOutputStream bOut = new ErasableOutputStream ();
56+ private TLSRSAPremasterSecretParameterSpec tlsRsaSpec = null ;
57+ private CipherParameters param = null ;
5258
5359 public CipherSpi (
5460 AsymmetricBlockCipher engine )
@@ -262,9 +268,12 @@ protected void engineInit(
262268 SecureRandom random )
263269 throws InvalidKeyException , InvalidAlgorithmParameterException
264270 {
265- CipherParameters param ;
266271
267- if (params == null || params instanceof OAEPParameterSpec )
272+ this .tlsRsaSpec = null ;
273+
274+ if (params == null
275+ || params instanceof OAEPParameterSpec
276+ || params instanceof TLSRSAPremasterSecretParameterSpec )
268277 {
269278 if (key instanceof RSAPublicKey )
270279 {
@@ -291,7 +300,7 @@ else if (key instanceof RSAPrivateKey)
291300 throw new InvalidKeyException ("unknown key type passed to RSA" );
292301 }
293302
294- if (params != null )
303+ if (params instanceof OAEPParameterSpec )
295304 {
296305 OAEPParameterSpec spec = (OAEPParameterSpec )params ;
297306
@@ -324,6 +333,14 @@ else if (key instanceof RSAPrivateKey)
324333
325334 cipher = new OAEPEncoding (new RSABlindedEngine (), digest , mgfDigest , ((PSource .PSpecified )spec .getPSource ()).getValue ());
326335 }
336+ else if (params instanceof TLSRSAPremasterSecretParameterSpec )
337+ {
338+ if (!(param instanceof RSAPrivateCrtKeyParameters ))
339+ {
340+ throw new InvalidKeyException ("RSA private key required for TLS decryption" );
341+ }
342+ this .tlsRsaSpec = (TLSRSAPremasterSecretParameterSpec )params ;
343+ }
327344 }
328345 else
329346 {
@@ -403,6 +420,11 @@ protected byte[] engineUpdate(
403420 int inputOffset ,
404421 int inputLen )
405422 {
423+ if (tlsRsaSpec != null )
424+ {
425+ throw new IllegalStateException ("RSA cipher initialized for TLS only" );
426+ }
427+
406428 bOut .write (input , inputOffset , inputLen );
407429
408430 if (cipher instanceof RSABlindedEngine )
@@ -430,6 +452,11 @@ protected int engineUpdate(
430452 byte [] output ,
431453 int outputOffset )
432454 {
455+ if (tlsRsaSpec != null )
456+ {
457+ throw new IllegalStateException ("RSA cipher initialized for TLS only" );
458+ }
459+
433460 bOut .write (input , inputOffset , inputLen );
434461
435462 if (cipher instanceof RSABlindedEngine )
@@ -456,6 +483,12 @@ protected byte[] engineDoFinal(
456483 int inputLen )
457484 throws IllegalBlockSizeException , BadPaddingException
458485 {
486+ if (tlsRsaSpec != null )
487+ {
488+ ParametersWithRandom pWithR = (ParametersWithRandom )param ;
489+ return TlsRsaKeyExchange .decryptPreMasterSecret (input , (RSAKeyParameters )pWithR .getParameters (), tlsRsaSpec .getProtocolVersion (), pWithR .getRandom ());
490+ }
491+
459492 if (input != null )
460493 {
461494 bOut .write (input , inputOffset , inputLen );
@@ -487,6 +520,11 @@ protected int engineDoFinal(
487520 int outputOffset )
488521 throws IllegalBlockSizeException , BadPaddingException , ShortBufferException
489522 {
523+ if (tlsRsaSpec != null )
524+ {
525+ throw new IllegalStateException ("RSA cipher initialized for TLS only" );
526+ }
527+
490528 if (outputOffset + engineGetOutputSize (inputLen ) > output .length )
491529 {
492530 throw new ShortBufferException ("output buffer too short for input." );
0 commit comments