Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / services / jce / JCECipherProvider.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/services/jce/JCECipherProvider.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/services/jce/JCECipherProvider.java
new file mode 100644 (file)
index 0000000..f271aed
--- /dev/null
@@ -0,0 +1,376 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.services.jce.JCECipherProvider\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.services.jce;\r
+\r
+import org.apache.derby.iapi.services.crypto.CipherFactory;\r
+import org.apache.derby.iapi.services.crypto.CipherProvider;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import java.security.Key;\r
+import java.security.InvalidKeyException;\r
+import java.security.NoSuchAlgorithmException;\r
+import java.security.GeneralSecurityException;\r
+import java.security.NoSuchProviderException;\r
+\r
+import javax.crypto.Cipher;\r
+import javax.crypto.spec.IvParameterSpec;\r
+import javax.crypto.SecretKeyFactory;\r
+import javax.crypto.spec.SecretKeySpec;\r
+import javax.crypto.SecretKey;\r
+\r
+\r
+/**\r
+       This is a wrapper for a Cipher\r
+\r
+       @see CipherFactory\r
+ */\r
+class JCECipherProvider implements CipherProvider\r
+{\r
+       private Cipher cipher;\r
+       private int mode;\r
+    private boolean ivUsed = true;\r
+    private final IvParameterSpec ivspec;\r
+    private final int encryptionBlockSize;\r
+    private boolean sunjce; //default of bool is false\r
+\r
+    // other provider workaround, we need to re-init the cipher before every encrypt/decrypt\r
+    private SecretKey cryptixKey;\r
+\r
+       JCECipherProvider(int mode, SecretKey secretKey, byte[] iv, String algorithm, String provider)\r
+                throws StandardException\r
+       {\r
+               Throwable t;\r
+               ivspec = new IvParameterSpec(iv);\r
+               try\r
+               {\r
+\r
+\r
+                       if (provider == null)\r
+                       {\r
+                               cipher = Cipher.getInstance(algorithm);\r
+\r
+                               // see below.\r
+                               if ("SunJCE".equals(cipher.getProvider().getName()))\r
+                                       sunjce = true;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The Sun encryption provider does not need to re-init the cipher\r
+                                * after each encrypt/decrypt.  This is a speed up trick.\r
+                                * Other crypto providers needs this because the encrypt/decrypt\r
+                                * ciphers becomes out of sync after an encrypt/decrypt operation.\r
+                                */\r
+                               if( provider.equals("SunJCE") )\r
+                               {\r
+                                       sunjce = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* The BouncyCastle encryption provider is named "BC".\r
+                                        * The full "BouncyCastleProvider" name used to work until\r
+                                        * version 103 came out.  (ie. Beta3 and Beta4 works fine)\r
+                                        * This trick is so that Cipher.getInstance(algo, prov) will\r
+                                        * not throw an exception.  Resolve 3765.\r
+                                        */\r
+                                       if( provider.equals( "BouncyCastleProvider" ) )\r
+                                               provider = "BC";\r
+                               }\r
+\r
+                               cipher = Cipher.getInstance(algorithm,provider);\r
+                       }\r
+\r
+                       // At creation time, the encryption block size is stored in order\r
+                       // to do appropriate padding\r
+                       encryptionBlockSize = cipher.getBlockSize();\r
+\r
+                       this.mode = mode;\r
+                       try {\r
+\r
+                               // ECB feedback mode does not require an IV\r
+                               if (mode == CipherFactory.ENCRYPT)\r
+                               {\r
+                                       if ((algorithm.indexOf("/ECB") > -1))\r
+                                               cipher.init(Cipher.ENCRYPT_MODE, secretKey);\r
+                                       else\r
+                                               cipher.init(Cipher.ENCRYPT_MODE, secretKey,ivspec);\r
+                               }\r
+                               else if (mode == CipherFactory.DECRYPT)\r
+                               {\r
+                                       if ((algorithm.indexOf("/ECB") > -1))\r
+                                               cipher.init(Cipher.DECRYPT_MODE, secretKey);\r
+                                       else\r
+                                               cipher.init(Cipher.DECRYPT_MODE, secretKey,ivspec);\r
+                               }\r
+                               else\r
+                                       throw StandardException.newException(SQLState.ILLEGAL_CIPHER_MODE);\r
+                       } catch (InvalidKeyException ike) {\r
+\r
+                               if (algorithm.startsWith("DES")) {\r
+\r
+                                       SecretKeyFactory skf;\r
+                                       if (provider == null)\r
+                                               skf = SecretKeyFactory.getInstance(secretKey.getAlgorithm());\r
+                                       else\r
+                                               skf = SecretKeyFactory.getInstance(secretKey.getAlgorithm(), provider);\r
+\r
+\r
+                                       // Since the key may be a series of bytes generated by an arbitary means\r
+                                       // we need to translate it into a key suitable for the algorithm.\r
+                                       secretKey = skf.translateKey(new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()));\r
+\r
+                                       // ECB mode does not require IV\r
+                                       if (mode == CipherFactory.ENCRYPT )\r
+                                       {\r
+                                               if ((algorithm.indexOf("/ECB") > -1))\r
+                                                       cipher.init(Cipher.ENCRYPT_MODE, secretKey);\r
+                                               else\r
+                                                       cipher.init(Cipher.ENCRYPT_MODE, secretKey,ivspec);\r
+                                       }\r
+                                       else if (mode == CipherFactory.DECRYPT)\r
+                                       {\r
+                                               if ((algorithm.indexOf("/ECB") > -1))\r
+                                                       cipher.init(Cipher.DECRYPT_MODE, secretKey);\r
+                                               else\r
+                                                       cipher.init(Cipher.DECRYPT_MODE, secretKey,ivspec);\r
+                                       }\r
+\r
+                               }\r
+                               else\r
+                                       throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);\r
+                       }\r
+            cryptixKey = secretKey;\r
+\r
+            if (cipher.getIV() == null)\r
+                ivUsed = false;\r
+\r
+            if (SanityManager.DEBUG)\r
+                SanityManager.ASSERT(verifyIV(iv));\r
+\r
+                       return;\r
+\r
+               }\r
+               catch (InvalidKeyException ike)\r
+               {\r
+                       t = ike;\r
+               }\r
+               catch (NoSuchAlgorithmException nsae)\r
+               {\r
+               throw StandardException.newException(SQLState.ENCRYPTION_NOSUCH_ALGORITHM, algorithm, JCECipherFactory.providerErrorName(provider));\r
+               }\r
+        catch (NoSuchProviderException nspe)\r
+        {\r
+               throw StandardException.newException(SQLState.ENCRYPTION_BAD_PROVIDER, JCECipherFactory.providerErrorName(provider));\r
+        }\r
+               catch (GeneralSecurityException gse)\r
+               {\r
+                       t = gse;\r
+               }\r
+               throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, t);\r
+\r
+       }\r
+\r
+       /**\r
+               @see CipherProvider#encrypt\r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public int encrypt(byte[] cleartext, int offset, int length,\r
+                                          byte[] ciphertext, int outputOffset)\r
+                throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(mode == CipherFactory.ENCRYPT,\r
+                                                                "calling encrypt on a decryption engine");\r
+                       SanityManager.ASSERT(cleartext != null, "encrypting null cleartext");\r
+                       SanityManager.ASSERT(offset >= 0, "offset < 0");\r
+                       SanityManager.ASSERT(length > 0, "length <= 0");\r
+                       SanityManager.ASSERT(offset+length <= cleartext.length,\r
+                                                                "offset+length > cleartext.length");\r
+                       SanityManager.ASSERT(length <= ciphertext.length-outputOffset,\r
+                                                                "provided ciphertext buffer insufficient");\r
+               }\r
+\r
+               int retval = 0;\r
+               try\r
+               {\r
+                       // this same cipher is shared across the entire raw store, make it\r
+                       // MT safe\r
+                       synchronized(this)\r
+                       {\r
+                if( !sunjce )\r
+                {\r
+                    // this code is a workaround for other providers\r
+                    try\r
+                    {\r
+                                   //ivspec = new IvParameterSpec(cipher.getIV());\r
+                               if (mode == CipherFactory.ENCRYPT)\r
+                               {\r
+                                                       if (ivUsed)\r
+                                               cipher.init(Cipher.ENCRYPT_MODE, cryptixKey, ivspec);\r
+                                       else\r
+                                               cipher.init(Cipher.ENCRYPT_MODE,cryptixKey);\r
+                                               }\r
+                                   else if (mode == CipherFactory.DECRYPT)\r
+                                   {\r
+                                                       if (ivUsed)\r
+                                               cipher.init(Cipher.DECRYPT_MODE, cryptixKey, ivspec);\r
+                                       else\r
+                                                               cipher.init(Cipher.DECRYPT_MODE, cryptixKey);\r
+                                               }\r
+\r
+                    }\r
+                       catch (InvalidKeyException ike)\r
+                           {\r
+                                               System.out.println("A " + ike);\r
+                                   throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);\r
+                           }\r
+                }\r
+\r
+                               retval = cipher.doFinal(cleartext, offset, length, ciphertext, outputOffset);\r
+                       }\r
+               }\r
+               catch (IllegalStateException ise)\r
+               {\r
+                       // should never happen\r
+                       if (SanityManager.DEBUG)\r
+                               SanityManager.THROWASSERT(ise);\r
+               }\r
+               catch (GeneralSecurityException gse)\r
+               {\r
+                                               System.out.println("B " + gse);\r
+                       throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, gse);\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(retval == length, "ciphertext length != length");\r
+\r
+               return retval;\r
+       }\r
+\r
+\r
+       /**\r
+               @see CipherProvider#decrypt\r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public int decrypt(byte[] ciphertext, int offset, int length,\r
+                                          byte[] cleartext, int outputOffset)\r
+                throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(mode == CipherFactory.DECRYPT,\r
+                                                                "calling decrypt on a encryption engine");\r
+                       SanityManager.ASSERT(ciphertext != null, "decrypting null ciphertext");\r
+                       SanityManager.ASSERT(offset >= 0, "offset < 0");\r
+                       SanityManager.ASSERT(length > 0, "length <= 0");\r
+                       SanityManager.ASSERT(offset+length <= ciphertext.length,\r
+                                                                "offset+length > ciphertext.length");\r
+                       SanityManager.ASSERT(length <= cleartext.length-outputOffset,\r
+                                                                "provided cleartexte buffer insufficient");\r
+               }\r
+\r
+               int retval = 0;\r
+               try\r
+               {\r
+                       // this same cipher is shared across the entire raw store, make it\r
+                       // MT safe\r
+                       synchronized(this)\r
+                       {\r
+                if( !sunjce )\r
+                {\r
+                    // this code is a workaround for other providers\r
+                    try\r
+                    {\r
+                                   //ivspec = new IvParameterSpec(cipher.getIV());\r
+\r
+                                   if (mode == CipherFactory.ENCRYPT)\r
+                                               {\r
+                                                       if (ivUsed)\r
+                                                               cipher.init(Cipher.ENCRYPT_MODE, cryptixKey, ivspec);\r
+                                                       else\r
+                                                               cipher.init(Cipher.ENCRYPT_MODE,cryptixKey);\r
+                                               }\r
+                                               else if (mode == CipherFactory.DECRYPT)\r
+                                               {\r
+                                                       if (ivUsed)\r
+                                                               cipher.init(Cipher.DECRYPT_MODE, cryptixKey, ivspec);\r
+                                                       else\r
+                                                               cipher.init(Cipher.DECRYPT_MODE, cryptixKey);\r
+                                               }\r
+\r
+                    }\r
+                       catch (InvalidKeyException ike)\r
+                           {\r
+                                               System.out.println("C " + ike);\r
+                                   throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);\r
+                           }\r
+\r
+                }\r
+\r
+                               retval = cipher.doFinal(ciphertext, offset, length, cleartext, outputOffset);\r
+                       }\r
+               }\r
+               catch (IllegalStateException ise)\r
+               {\r
+                       // should never happen\r
+                       if (SanityManager.DEBUG)\r
+                               SanityManager.THROWASSERT(ise);\r
+               }\r
+               catch (GeneralSecurityException gse)\r
+               {\r
+                                               System.out.println("D " + gse);\r
+                       throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, gse);\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(retval == length,\r
+                                                                "cleartext length != length");\r
+               }\r
+\r
+               return retval;\r
+       }\r
+\r
+       boolean verifyIV(byte[] IV)\r
+       {\r
+               byte[] myIV = cipher.getIV();\r
+        // null IV is OK only if IV is not used\r
+        if (myIV == null)\r
+            return !ivUsed;\r
+               if (myIV.length != IV.length)\r
+                       return false;\r
+               for (int i = 0; i < IV.length; i++)\r
+                       if (myIV[i] != IV[i])\r
+                               return false;\r
+               return true;\r
+       }\r
+\r
+       public int getEncryptionBlockSize()\r
+       {\r
+               return encryptionBlockSize;\r
+       }\r
+}\r