3636import javax .crypto .spec .GCMParameterSpec ;
3737import javax .crypto .spec .OAEPParameterSpec ;
3838import javax .crypto .spec .PSource ;
39+ import javax .crypto .spec .SecretKeySpec ;
3940
4041import java .security .SecureRandom ;
42+ import java .security .KeyFactory ;
4143import java .security .spec .MGF1ParameterSpec ;
4244import java .security .AlgorithmParameters ;
4345import java .security .spec .AlgorithmParameterSpec ;
4446import java .security .spec .InvalidParameterSpecException ;
47+ import java .security .spec .PKCS8EncodedKeySpec ;
48+ import java .security .spec .X509EncodedKeySpec ;
49+ import java .security .spec .InvalidKeySpecException ;
4550import java .security .Key ;
4651import java .security .NoSuchAlgorithmException ;
4752import java .security .InvalidAlgorithmParameterException ;
@@ -110,6 +115,10 @@ enum RsaKeyType {
110115 private OpMode direction = null ;
111116 private RsaKeyType rsaKeyType = null ;
112117
118+ /* Store original opmode (ENCRYPT, DECRYPT, WRAP, UNWRAP), used by
119+ * post-doFinal reset to restore correct mode */
120+ private int storedOpMode = 0 ;
121+
113122 private int blockSize = 0 ;
114123
115124 private Aes aes = null ;
@@ -745,8 +754,8 @@ else if (this.cipherType == CipherType.WC_DES3) {
745754 private void wolfCryptSetDirection (int opmode )
746755 throws InvalidKeyException {
747756
748- /* we don't currently support AES key wrap in JCE yet,
749- * so don't allow WRAP_MODE or UNWRAP_MODE */
757+ this . storedOpMode = opmode ;
758+
750759 switch (opmode ) {
751760 case Cipher .ENCRYPT_MODE :
752761 this .direction = OpMode .WC_ENCRYPT ;
@@ -756,9 +765,18 @@ private void wolfCryptSetDirection(int opmode)
756765 this .direction = OpMode .WC_DECRYPT ;
757766 break ;
758767
768+ case Cipher .WRAP_MODE :
769+ this .direction = OpMode .WC_ENCRYPT ;
770+ break ;
771+
772+ case Cipher .UNWRAP_MODE :
773+ this .direction = OpMode .WC_DECRYPT ;
774+ break ;
775+
759776 default :
760777 throw new InvalidParameterException (
761- "Cipher opmode must be ENCRYPT_MODE or DECRYPT_MODE" );
778+ "Cipher opmode must be ENCRYPT_MODE, " +
779+ "DECRYPT_MODE, WRAP_MODE, or UNWRAP_MODE" );
762780 }
763781 }
764782
@@ -1520,11 +1538,7 @@ else if (cipherMode == CipherMode.WC_OFB) {
15201538 try {
15211539 buffered = new byte [0 ];
15221540
1523- if (this .direction == OpMode .WC_ENCRYPT ) {
1524- wolfCryptSetDirection (Cipher .ENCRYPT_MODE );
1525- } else {
1526- wolfCryptSetDirection (Cipher .DECRYPT_MODE );
1527- }
1541+ wolfCryptSetDirection (this .storedOpMode );
15281542
15291543 InitializeNativeStructs ();
15301544
@@ -1838,6 +1852,90 @@ protected void engineUpdateAAD(ByteBuffer src)
18381852 }
18391853 }
18401854
1855+ @ Override
1856+ protected byte [] engineWrap (Key key )
1857+ throws IllegalBlockSizeException , InvalidKeyException {
1858+
1859+ byte [] encodedKey = null ;
1860+
1861+ if (key == null ) {
1862+ throw new InvalidKeyException (
1863+ "Key to be wrapped must not be null" );
1864+ }
1865+
1866+ encodedKey = key .getEncoded ();
1867+ if (encodedKey == null ) {
1868+ throw new InvalidKeyException (
1869+ "Key does not support encoding, cannot wrap" );
1870+ }
1871+
1872+ try {
1873+ return wolfCryptFinal (encodedKey , 0 , encodedKey .length );
1874+
1875+ } catch (BadPaddingException e ) {
1876+ throw new InvalidKeyException ("Failed to wrap key: " +
1877+ e .getMessage (), e );
1878+ }
1879+ }
1880+
1881+ @ Override
1882+ protected Key engineUnwrap (byte [] wrappedKey , String wrappedKeyAlgo ,
1883+ int wrappedKeyType ) throws InvalidKeyException ,
1884+ NoSuchAlgorithmException {
1885+
1886+ byte [] unwrappedKey ;
1887+
1888+ if (wrappedKey == null || wrappedKey .length == 0 ) {
1889+ throw new InvalidKeyException (
1890+ "Wrapped key bytes must not be null or empty" );
1891+ }
1892+
1893+ try {
1894+ unwrappedKey = wolfCryptFinal (wrappedKey , 0 , wrappedKey .length );
1895+
1896+ } catch (BadPaddingException e ) {
1897+ throw new InvalidKeyException ("Failed to unwrap key: " +
1898+ e .getMessage (), e );
1899+
1900+ } catch (IllegalBlockSizeException e ) {
1901+ throw new InvalidKeyException ("Failed to unwrap key: " +
1902+ e .getMessage (), e );
1903+ }
1904+
1905+ switch (wrappedKeyType ) {
1906+ case Cipher .SECRET_KEY :
1907+ return new SecretKeySpec (unwrappedKey , wrappedKeyAlgo );
1908+
1909+ case Cipher .PUBLIC_KEY :
1910+ try {
1911+ KeyFactory kf = KeyFactory .getInstance (wrappedKeyAlgo );
1912+ return kf .generatePublic (
1913+ new X509EncodedKeySpec (unwrappedKey ));
1914+
1915+ } catch (InvalidKeySpecException e ) {
1916+ throw new InvalidKeyException (
1917+ "Failed to reconstruct public key: " +
1918+ e .getMessage (), e );
1919+ }
1920+
1921+ case Cipher .PRIVATE_KEY :
1922+ try {
1923+ KeyFactory kf = KeyFactory .getInstance (wrappedKeyAlgo );
1924+ return kf .generatePrivate (
1925+ new PKCS8EncodedKeySpec (unwrappedKey ));
1926+
1927+ } catch (InvalidKeySpecException e ) {
1928+ throw new InvalidKeyException (
1929+ "Failed to reconstruct private key: " +
1930+ e .getMessage (), e );
1931+ }
1932+
1933+ default :
1934+ throw new InvalidKeyException ("Invalid wrappedKeyType: " +
1935+ wrappedKeyType );
1936+ }
1937+ }
1938+
18411939 private String typeToString (CipherType type ) {
18421940 switch (type ) {
18431941 case WC_AES :
0 commit comments