diff options
author | Brian Carlstrom <bdc@google.com> | 2013-01-30 05:52:33 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-01-30 05:52:33 +0000 |
commit | b8bddcfe1c0fdb5fd26a0285673f7d4d488dbab7 (patch) | |
tree | 0680698559d75d295e856044f26fb9aef64e1b96 | |
parent | 6c392aa76b14c3bc3bab3b0c1209d52febab621a (diff) | |
parent | aea1f1224e7ad62991b68c485f086abcb289f82b (diff) | |
download | android_external_bouncycastle-b8bddcfe1c0fdb5fd26a0285673f7d4d488dbab7.tar.gz android_external_bouncycastle-b8bddcfe1c0fdb5fd26a0285673f7d4d488dbab7.tar.bz2 android_external_bouncycastle-b8bddcfe1c0fdb5fd26a0285673f7d4d488dbab7.zip |
Merge "Restore PBE Cipher wrap and unwrap support from upstream"
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java | 110 | ||||
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java | 119 | ||||
-rw-r--r-- | bouncycastle.config | 2 | ||||
-rwxr-xr-x | import_bouncycastle.sh | 2 | ||||
-rw-r--r-- | patches/CipherSpi-engineWrap.patch | 303 | ||||
-rw-r--r-- | patches/README | 11 |
6 files changed, 543 insertions, 4 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java index 2205a26..ca655cf 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java @@ -5,9 +5,15 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.Key; +import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -22,7 +28,9 @@ import javax.crypto.spec.PBEParameterSpec; // import javax.crypto.spec.RC2ParameterSpec; // import javax.crypto.spec.RC5ParameterSpec; // END android-removed +import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.CipherParameters; @@ -779,6 +787,108 @@ public class JCEBlockCipher return "CCM".equals(modeName) || "EAX".equals(modeName) || "GCM".equals(modeName); } + protected byte[] engineWrap( + Key key) + throws IllegalBlockSizeException, InvalidKeyException + { + byte[] encoded = key.getEncoded(); + if (encoded == null) + { + throw new InvalidKeyException("Cannot wrap key, null encoding."); + } + + try + { + return engineDoFinal(encoded, 0, encoded.length); + } + catch (BadPaddingException e) + { + throw new IllegalBlockSizeException(e.getMessage()); + } + } + + protected Key engineUnwrap( + byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException + { + byte[] encoded; + try + { + encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); + } + catch (BadPaddingException e) + { + throw new InvalidKeyException(e.getMessage()); + } + catch (IllegalBlockSizeException e2) + { + throw new InvalidKeyException(e2.getMessage()); + } + + if (wrappedKeyType == Cipher.SECRET_KEY) + { + return new SecretKeySpec(encoded, wrappedKeyAlgorithm); + } + else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY) + { + /* + * The caller doesn't know the algorithm as it is part of + * the encrypted data. + */ + try + { + PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded); + + PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in); + + if (privKey != null) + { + return privKey; + } + else + { + throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported"); + } + } + catch (Exception e) + { + throw new InvalidKeyException("Invalid key encoding."); + } + } + else + { + try + { + KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME); + + if (wrappedKeyType == Cipher.PUBLIC_KEY) + { + return kf.generatePublic(new X509EncodedKeySpec(encoded)); + } + else if (wrappedKeyType == Cipher.PRIVATE_KEY) + { + return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded)); + } + } + catch (NoSuchProviderException e) + { + throw new InvalidKeyException("Unknown key type " + e.getMessage()); + } + catch (NoSuchAlgorithmException e) + { + throw new InvalidKeyException("Unknown key type " + e.getMessage()); + } + catch (InvalidKeySpecException e2) + { + throw new InvalidKeyException("Unknown key type " + e2.getMessage()); + } + + throw new InvalidKeyException("Unknown key type " + wrappedKeyType); + } + } + /* * The ciphers that inherit from us. */ diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java index 16a14ec..4600679 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java @@ -4,11 +4,20 @@ import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.CipherSpi; +import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; @@ -18,7 +27,9 @@ import javax.crypto.spec.PBEParameterSpec; // import javax.crypto.spec.RC2ParameterSpec; // import javax.crypto.spec.RC5ParameterSpec; // END android-removed +import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; @@ -347,7 +358,8 @@ public class JCEStreamCipher protected byte[] engineDoFinal( byte[] input, int inputOffset, - int inputLen) + int inputLen) + throws BadPaddingException, IllegalBlockSizeException { if (inputLen != 0) { @@ -368,7 +380,8 @@ public class JCEStreamCipher int inputOffset, int inputLen, byte[] output, - int outputOffset) + int outputOffset) + throws BadPaddingException { if (inputLen != 0) { @@ -380,6 +393,108 @@ public class JCEStreamCipher return inputLen; } + protected byte[] engineWrap( + Key key) + throws IllegalBlockSizeException, InvalidKeyException + { + byte[] encoded = key.getEncoded(); + if (encoded == null) + { + throw new InvalidKeyException("Cannot wrap key, null encoding."); + } + + try + { + return engineDoFinal(encoded, 0, encoded.length); + } + catch (BadPaddingException e) + { + throw new IllegalBlockSizeException(e.getMessage()); + } + } + + protected Key engineUnwrap( + byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException + { + byte[] encoded; + try + { + encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); + } + catch (BadPaddingException e) + { + throw new InvalidKeyException(e.getMessage()); + } + catch (IllegalBlockSizeException e2) + { + throw new InvalidKeyException(e2.getMessage()); + } + + if (wrappedKeyType == Cipher.SECRET_KEY) + { + return new SecretKeySpec(encoded, wrappedKeyAlgorithm); + } + else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY) + { + /* + * The caller doesn't know the algorithm as it is part of + * the encrypted data. + */ + try + { + PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded); + + PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in); + + if (privKey != null) + { + return privKey; + } + else + { + throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported"); + } + } + catch (Exception e) + { + throw new InvalidKeyException("Invalid key encoding."); + } + } + else + { + try + { + KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME); + + if (wrappedKeyType == Cipher.PUBLIC_KEY) + { + return kf.generatePublic(new X509EncodedKeySpec(encoded)); + } + else if (wrappedKeyType == Cipher.PRIVATE_KEY) + { + return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded)); + } + } + catch (NoSuchProviderException e) + { + throw new InvalidKeyException("Unknown key type " + e.getMessage()); + } + catch (NoSuchAlgorithmException e) + { + throw new InvalidKeyException("Unknown key type " + e.getMessage()); + } + catch (InvalidKeySpecException e2) + { + throw new InvalidKeyException("Unknown key type " + e2.getMessage()); + } + + throw new InvalidKeyException("Unknown key type " + wrappedKeyType); + } + } + /* * The ciphers that inherit from us. */ diff --git a/bouncycastle.config b/bouncycastle.config index 7ee682e..c31204f 100644 --- a/bouncycastle.config +++ b/bouncycastle.config @@ -592,5 +592,5 @@ NEEDED_BCPROV_SOURCES="org" NEEDED_BCPKIX_SOURCES="org" # list of patch files to apply in the given order -BOUNCYCASTLE_BCPROV_PATCHES="patches/bcprov.patch" +BOUNCYCASTLE_BCPROV_PATCHES="patches/bcprov.patch patches/CipherSpi-engineWrap.patch" BOUNCYCASTLE_BCPKIX_PATCHES="patches/bcpkix.patch" diff --git a/import_bouncycastle.sh b/import_bouncycastle.sh index 5cbd504..a97b060 100755 --- a/import_bouncycastle.sh +++ b/import_bouncycastle.sh @@ -235,7 +235,7 @@ function applypatches () { # Apply appropriate patches for i in $bouncycastle_patches; do echo "Applying patch $i" - patch -p1 < ../$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i" + patch -p1 < ../$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate $i" # make sure no unneeded sources got into the patch problem=0 diff --git a/patches/CipherSpi-engineWrap.patch b/patches/CipherSpi-engineWrap.patch new file mode 100644 index 0000000..1df8688 --- /dev/null +++ b/patches/CipherSpi-engineWrap.patch @@ -0,0 +1,303 @@ +--- bcprov-jdk15on-147.orig/org/bouncycastle/jce/provider/JCEBlockCipher.java 2012/04/05 10:57:52 1.31 ++++ bcprov-jdk15on-147/org/bouncycastle/jce/provider/JCEBlockCipher.java 2013/01/02 08:01:03 1.32 +@@ -5,9 +5,15 @@ + import java.security.InvalidKeyException; + import java.security.InvalidParameterException; + import java.security.Key; ++import java.security.KeyFactory; + import java.security.NoSuchAlgorithmException; ++import java.security.NoSuchProviderException; ++import java.security.PrivateKey; + import java.security.SecureRandom; + import java.security.spec.AlgorithmParameterSpec; ++import java.security.spec.InvalidKeySpecException; ++import java.security.spec.PKCS8EncodedKeySpec; ++import java.security.spec.X509EncodedKeySpec; + + import javax.crypto.BadPaddingException; + import javax.crypto.Cipher; +@@ -20,9 +26,11 @@ + import javax.crypto.spec.PBEParameterSpec; + // BEGIN android-removed + // import javax.crypto.spec.RC2ParameterSpec; + // import javax.crypto.spec.RC5ParameterSpec; + // END android-removed ++import javax.crypto.spec.SecretKeySpec; + ++import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; + import org.bouncycastle.crypto.BlockCipher; + import org.bouncycastle.crypto.BufferedBlockCipher; + import org.bouncycastle.crypto.CipherParameters; +@@ -739,6 +747,108 @@ + return "CCM".equals(modeName) || "EAX".equals(modeName) || "GCM".equals(modeName); + } + ++ protected byte[] engineWrap( ++ Key key) ++ throws IllegalBlockSizeException, InvalidKeyException ++ { ++ byte[] encoded = key.getEncoded(); ++ if (encoded == null) ++ { ++ throw new InvalidKeyException("Cannot wrap key, null encoding."); ++ } ++ ++ try ++ { ++ return engineDoFinal(encoded, 0, encoded.length); ++ } ++ catch (BadPaddingException e) ++ { ++ throw new IllegalBlockSizeException(e.getMessage()); ++ } ++ } ++ ++ protected Key engineUnwrap( ++ byte[] wrappedKey, ++ String wrappedKeyAlgorithm, ++ int wrappedKeyType) ++ throws InvalidKeyException ++ { ++ byte[] encoded; ++ try ++ { ++ encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); ++ } ++ catch (BadPaddingException e) ++ { ++ throw new InvalidKeyException(e.getMessage()); ++ } ++ catch (IllegalBlockSizeException e2) ++ { ++ throw new InvalidKeyException(e2.getMessage()); ++ } ++ ++ if (wrappedKeyType == Cipher.SECRET_KEY) ++ { ++ return new SecretKeySpec(encoded, wrappedKeyAlgorithm); ++ } ++ else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY) ++ { ++ /* ++ * The caller doesn't know the algorithm as it is part of ++ * the encrypted data. ++ */ ++ try ++ { ++ PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded); ++ ++ PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in); ++ ++ if (privKey != null) ++ { ++ return privKey; ++ } ++ else ++ { ++ throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported"); ++ } ++ } ++ catch (Exception e) ++ { ++ throw new InvalidKeyException("Invalid key encoding."); ++ } ++ } ++ else ++ { ++ try ++ { ++ KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME); ++ ++ if (wrappedKeyType == Cipher.PUBLIC_KEY) ++ { ++ return kf.generatePublic(new X509EncodedKeySpec(encoded)); ++ } ++ else if (wrappedKeyType == Cipher.PRIVATE_KEY) ++ { ++ return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded)); ++ } ++ } ++ catch (NoSuchProviderException e) ++ { ++ throw new InvalidKeyException("Unknown key type " + e.getMessage()); ++ } ++ catch (NoSuchAlgorithmException e) ++ { ++ throw new InvalidKeyException("Unknown key type " + e.getMessage()); ++ } ++ catch (InvalidKeySpecException e2) ++ { ++ throw new InvalidKeyException("Unknown key type " + e2.getMessage()); ++ } ++ ++ throw new InvalidKeyException("Unknown key type " + wrappedKeyType); ++ } ++ } ++ + /* + * The ciphers that inherit from us. + */ +--- bcprov-jdk15on-147.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java 2011/08/25 06:17:08 1.15 ++++ bcprov-jdk15on-147/org/bouncycastle/jce/provider/JCEStreamCipher.java 2013/01/29 05:42:31 1.16 +@@ -4,11 +4,20 @@ + import java.security.InvalidAlgorithmParameterException; + import java.security.InvalidKeyException; + import java.security.Key; ++import java.security.KeyFactory; ++import java.security.NoSuchAlgorithmException; ++import java.security.NoSuchProviderException; ++import java.security.PrivateKey; + import java.security.SecureRandom; + import java.security.spec.AlgorithmParameterSpec; ++import java.security.spec.InvalidKeySpecException; ++import java.security.spec.PKCS8EncodedKeySpec; ++import java.security.spec.X509EncodedKeySpec; + ++import javax.crypto.BadPaddingException; + import javax.crypto.Cipher; + import javax.crypto.CipherSpi; ++import javax.crypto.IllegalBlockSizeException; + import javax.crypto.NoSuchPaddingException; + import javax.crypto.SecretKey; + import javax.crypto.ShortBufferException; +@@ -16,9 +25,11 @@ + import javax.crypto.spec.PBEParameterSpec; + // BEGIN android-removed + // import javax.crypto.spec.RC2ParameterSpec; + // import javax.crypto.spec.RC5ParameterSpec; + // END android-removed ++import javax.crypto.spec.SecretKeySpec; + ++import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; + import org.bouncycastle.crypto.BlockCipher; + import org.bouncycastle.crypto.CipherParameters; + import org.bouncycastle.crypto.DataLengthException; +@@ -339,7 +350,8 @@ + protected byte[] engineDoFinal( + byte[] input, + int inputOffset, +- int inputLen) ++ int inputLen) ++ throws BadPaddingException, IllegalBlockSizeException + { + if (inputLen != 0) + { +@@ -360,7 +372,8 @@ + int inputOffset, + int inputLen, + byte[] output, +- int outputOffset) ++ int outputOffset) ++ throws BadPaddingException + { + if (inputLen != 0) + { +@@ -372,6 +385,108 @@ + return inputLen; + } + ++ protected byte[] engineWrap( ++ Key key) ++ throws IllegalBlockSizeException, InvalidKeyException ++ { ++ byte[] encoded = key.getEncoded(); ++ if (encoded == null) ++ { ++ throw new InvalidKeyException("Cannot wrap key, null encoding."); ++ } ++ ++ try ++ { ++ return engineDoFinal(encoded, 0, encoded.length); ++ } ++ catch (BadPaddingException e) ++ { ++ throw new IllegalBlockSizeException(e.getMessage()); ++ } ++ } ++ ++ protected Key engineUnwrap( ++ byte[] wrappedKey, ++ String wrappedKeyAlgorithm, ++ int wrappedKeyType) ++ throws InvalidKeyException ++ { ++ byte[] encoded; ++ try ++ { ++ encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); ++ } ++ catch (BadPaddingException e) ++ { ++ throw new InvalidKeyException(e.getMessage()); ++ } ++ catch (IllegalBlockSizeException e2) ++ { ++ throw new InvalidKeyException(e2.getMessage()); ++ } ++ ++ if (wrappedKeyType == Cipher.SECRET_KEY) ++ { ++ return new SecretKeySpec(encoded, wrappedKeyAlgorithm); ++ } ++ else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY) ++ { ++ /* ++ * The caller doesn't know the algorithm as it is part of ++ * the encrypted data. ++ */ ++ try ++ { ++ PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded); ++ ++ PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in); ++ ++ if (privKey != null) ++ { ++ return privKey; ++ } ++ else ++ { ++ throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported"); ++ } ++ } ++ catch (Exception e) ++ { ++ throw new InvalidKeyException("Invalid key encoding."); ++ } ++ } ++ else ++ { ++ try ++ { ++ KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME); ++ ++ if (wrappedKeyType == Cipher.PUBLIC_KEY) ++ { ++ return kf.generatePublic(new X509EncodedKeySpec(encoded)); ++ } ++ else if (wrappedKeyType == Cipher.PRIVATE_KEY) ++ { ++ return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded)); ++ } ++ } ++ catch (NoSuchProviderException e) ++ { ++ throw new InvalidKeyException("Unknown key type " + e.getMessage()); ++ } ++ catch (NoSuchAlgorithmException e) ++ { ++ throw new InvalidKeyException("Unknown key type " + e.getMessage()); ++ } ++ catch (InvalidKeySpecException e2) ++ { ++ throw new InvalidKeyException("Unknown key type " + e2.getMessage()); ++ } ++ ++ throw new InvalidKeyException("Unknown key type " + wrappedKeyType); ++ } ++ } ++ + /* + * The ciphers that inherit from us. + */ diff --git a/patches/README b/patches/README index 0caaea9..b9c9181 100644 --- a/patches/README +++ b/patches/README @@ -48,3 +48,14 @@ patch against Bouncy Castle's bcpkix: The main differences involve: - removing algorithms not in our bcprov (MD2, MD4, SHA224, RIPEMD, GOST) - using the singleton DERNull.INSTANCE + + +CipherSpi-engineWrap.patch: + +Fixes from upstream BouncyCastle repository for: + https://code.google.com/p/android/issues/detail?id=41405 + +"added wrap/unwrap support back in." + http://www.bouncycastle.org/viewcvs/viewcvs.cgi/java/crypto/src/org/bouncycastle/jce/provider/JCEBlockCipher.java?r1=1.31&r2=1.32&view=patch +"fix for JCEStreamCipher PBE wrapping" + http://www.bouncycastle.org/viewcvs/viewcvs.cgi/java/crypto/src/org/bouncycastle/jce/provider/JCEStreamCipher.java?r1=1.15&r2=1.16&view=patch |