Skip to content

Commit ad62699

Browse files
authored
Merge pull request wolfSSL#197 from cconlon/cipherWrapUnwrap
Add JCE Cipher WRAP_MODE and UNWRAP_MODE support
2 parents f194852 + 32f7724 commit ad62699

File tree

3 files changed

+821
-8
lines changed

3 files changed

+821
-8
lines changed

src/main/java/com/wolfssl/provider/jce/WolfCryptCipher.java

Lines changed: 106 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@
3636
import javax.crypto.spec.GCMParameterSpec;
3737
import javax.crypto.spec.OAEPParameterSpec;
3838
import javax.crypto.spec.PSource;
39+
import javax.crypto.spec.SecretKeySpec;
3940

4041
import java.security.SecureRandom;
42+
import java.security.KeyFactory;
4143
import java.security.spec.MGF1ParameterSpec;
4244
import java.security.AlgorithmParameters;
4345
import java.security.spec.AlgorithmParameterSpec;
4446
import java.security.spec.InvalidParameterSpecException;
47+
import java.security.spec.PKCS8EncodedKeySpec;
48+
import java.security.spec.X509EncodedKeySpec;
49+
import java.security.spec.InvalidKeySpecException;
4550
import java.security.Key;
4651
import java.security.NoSuchAlgorithmException;
4752
import 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

Comments
 (0)