EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.impl.services.jce]

COVERAGE SUMMARY FOR SOURCE FILE [JCECipherProvider.java]

nameclass, %method, %block, %line, %
JCECipherProvider.java100% (1/1)100% (5/5)50%  (300/597)46%  (58.5/126)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JCECipherProvider100% (1/1)100% (5/5)50%  (300/597)46%  (58.5/126)
JCECipherProvider (int, SecretKey, byte [], String, String): void 100% (1/1)50%  (109/217)48%  (26/54)
decrypt (byte [], int, int, byte [], int): int 100% (1/1)46%  (77/169)40%  (12.3/31)
encrypt (byte [], int, int, byte [], int): int 100% (1/1)46%  (77/169)40%  (12.3/31)
getEncryptionBlockSize (): int 100% (1/1)100% (3/3)100% (1/1)
verifyIV (byte []): boolean 100% (1/1)87%  (34/39)76%  (6.8/9)

1/*
2 
3   Derby - Class org.apache.derby.impl.services.jce.JCECipherProvider
4 
5   Copyright 2000, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.impl.services.jce;
22 
23import org.apache.derby.iapi.services.crypto.CipherFactory;
24import org.apache.derby.iapi.services.crypto.CipherProvider;
25import org.apache.derby.iapi.services.sanity.SanityManager;
26 
27import org.apache.derby.iapi.error.StandardException;
28import org.apache.derby.iapi.reference.SQLState;
29 
30import java.security.Key;
31import java.security.InvalidKeyException;
32import java.security.NoSuchAlgorithmException;
33import java.security.GeneralSecurityException;
34import java.security.NoSuchProviderException;
35 
36import javax.crypto.Cipher;
37import javax.crypto.spec.IvParameterSpec;
38import javax.crypto.SecretKeyFactory;
39import javax.crypto.spec.SecretKeySpec;
40import javax.crypto.SecretKey;
41 
42 
43/**
44        This is a wrapper for a Cipher
45 
46        @see CipherFactory
47 */
48class JCECipherProvider implements CipherProvider
49{
50        private Cipher cipher;
51        private int mode;
52    private boolean ivUsed = true;
53    private final IvParameterSpec ivspec;
54    private final int encryptionBlockSize;
55    private boolean sunjce; //default of bool is false
56 
57    // other provider workaround, we need to re-init the cipher before every encrypt/decrypt
58    private SecretKey cryptixKey;
59 
60        JCECipherProvider(int mode, SecretKey secretKey, byte[] iv, String algorithm, String provider)
61                 throws StandardException
62        {
63                Throwable t;
64                ivspec = new IvParameterSpec(iv);
65                try
66                {
67 
68 
69                        if (provider == null)
70                        {
71                                cipher = Cipher.getInstance(algorithm);
72 
73                                // see below.
74                                if ("SunJCE".equals(cipher.getProvider().getName()))
75                                        sunjce = true;
76                        }
77                        else
78                        {
79                                /* The Sun encryption provider does not need to re-init the cipher
80                                 * after each encrypt/decrypt.  This is a speed up trick.
81                                 * Other crypto providers needs this because the encrypt/decrypt
82                                 * ciphers becomes out of sync after an encrypt/decrypt operation.
83                                 */
84                                if( provider.equals("SunJCE") )
85                                {
86                                        sunjce = true;
87                                }
88                                else
89                                {
90                                        /* The BouncyCastle encryption provider is named "BC".
91                                         * The full "BouncyCastleProvider" name used to work until
92                                         * version 103 came out.  (ie. Beta3 and Beta4 works fine)
93                                         * This trick is so that Cipher.getInstance(algo, prov) will
94                                         * not throw an exception.  Resolve 3765.
95                                         */
96                                        if( provider.equals( "BouncyCastleProvider" ) )
97                                                provider = "BC";
98                                }
99 
100                                cipher = Cipher.getInstance(algorithm,provider);
101                        }
102 
103                        // At creation time, the encryption block size is stored in order
104                        // to do appropriate padding
105                        encryptionBlockSize = cipher.getBlockSize();
106 
107                        this.mode = mode;
108                        try {
109 
110                                // ECB feedback mode does not require an IV
111                                if (mode == CipherFactory.ENCRYPT)
112                                {
113                                        if ((algorithm.indexOf("/ECB") > -1))
114                                                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
115                                        else
116                                                cipher.init(Cipher.ENCRYPT_MODE, secretKey,ivspec);
117                                }
118                                else if (mode == CipherFactory.DECRYPT)
119                                {
120                                        if ((algorithm.indexOf("/ECB") > -1))
121                                                cipher.init(Cipher.DECRYPT_MODE, secretKey);
122                                        else
123                                                cipher.init(Cipher.DECRYPT_MODE, secretKey,ivspec);
124                                }
125                                else
126                                        throw StandardException.newException(SQLState.ILLEGAL_CIPHER_MODE);
127                        } catch (InvalidKeyException ike) {
128 
129                                if (algorithm.startsWith("DES")) {
130 
131                                        SecretKeyFactory skf;
132                                        if (provider == null)
133                                                skf = SecretKeyFactory.getInstance(secretKey.getAlgorithm());
134                                        else
135                                                skf = SecretKeyFactory.getInstance(secretKey.getAlgorithm(), provider);
136 
137 
138                                        // Since the key may be a series of bytes generated by an arbitary means
139                                        // we need to translate it into a key suitable for the algorithm.
140                                        secretKey = skf.translateKey(new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()));
141 
142                                        // ECB mode does not require IV
143                                        if (mode == CipherFactory.ENCRYPT )
144                                        {
145                                                if ((algorithm.indexOf("/ECB") > -1))
146                                                        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
147                                                else
148                                                        cipher.init(Cipher.ENCRYPT_MODE, secretKey,ivspec);
149                                        }
150                                        else if (mode == CipherFactory.DECRYPT)
151                                        {
152                                                if ((algorithm.indexOf("/ECB") > -1))
153                                                        cipher.init(Cipher.DECRYPT_MODE, secretKey);
154                                                else
155                                                        cipher.init(Cipher.DECRYPT_MODE, secretKey,ivspec);
156                                        }
157 
158                                }
159                                else
160                                        throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);
161                        }
162            cryptixKey = secretKey;
163 
164            if (cipher.getIV() == null)
165                ivUsed = false;
166 
167            if (SanityManager.DEBUG)
168                SanityManager.ASSERT(verifyIV(iv));
169 
170                        return;
171 
172                }
173                catch (InvalidKeyException ike)
174                {
175                        t = ike;
176                }
177                catch (NoSuchAlgorithmException nsae)
178                {
179                    throw StandardException.newException(SQLState.ENCRYPTION_NOSUCH_ALGORITHM, algorithm, JCECipherFactory.providerErrorName(provider));
180                }
181        catch (NoSuchProviderException nspe)
182        {
183                    throw StandardException.newException(SQLState.ENCRYPTION_BAD_PROVIDER, JCECipherFactory.providerErrorName(provider));
184        }
185                catch (GeneralSecurityException gse)
186                {
187                        t = gse;
188                }
189                throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, t);
190 
191        }
192 
193        /**
194                @see CipherProvider#encrypt
195 
196                @exception StandardException Standard Cloudscape Error Policy
197         */
198        public int encrypt(byte[] cleartext, int offset, int length,
199                                           byte[] ciphertext, int outputOffset)
200                 throws StandardException
201        {
202                if (SanityManager.DEBUG)
203                {
204                        SanityManager.ASSERT(mode == CipherFactory.ENCRYPT,
205                                                                 "calling encrypt on a decryption engine");
206                        SanityManager.ASSERT(cleartext != null, "encrypting null cleartext");
207                        SanityManager.ASSERT(offset >= 0, "offset < 0");
208                        SanityManager.ASSERT(length > 0, "length <= 0");
209                        SanityManager.ASSERT(offset+length <= cleartext.length,
210                                                                 "offset+length > cleartext.length");
211                        SanityManager.ASSERT(length <= ciphertext.length-outputOffset,
212                                                                 "provided ciphertext buffer insufficient");
213                }
214 
215                int retval = 0;
216                try
217                {
218                        // this same cipher is shared across the entire raw store, make it
219                        // MT safe
220                        synchronized(this)
221                        {
222                if( !sunjce )
223                {
224                    // this code is a workaround for other providers
225                    try
226                    {
227                                    //ivspec = new IvParameterSpec(cipher.getIV());
228                                    if (mode == CipherFactory.ENCRYPT)
229                                    {
230                                                        if (ivUsed)
231                                                    cipher.init(Cipher.ENCRYPT_MODE, cryptixKey, ivspec);
232                                            else
233                                                        cipher.init(Cipher.ENCRYPT_MODE,cryptixKey);
234                                                }
235                                        else if (mode == CipherFactory.DECRYPT)
236                                        {
237                                                        if (ivUsed)
238                                                    cipher.init(Cipher.DECRYPT_MODE, cryptixKey, ivspec);
239                                                else
240                                                                cipher.init(Cipher.DECRYPT_MODE, cryptixKey);
241                                                }
242 
243                    }
244                            catch (InvalidKeyException ike)
245                            {
246                                                System.out.println("A " + ike);
247                                    throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);
248                            }
249                }
250 
251                                retval = cipher.doFinal(cleartext, offset, length, ciphertext, outputOffset);
252                        }
253                }
254                catch (IllegalStateException ise)
255                {
256                        // should never happen
257                        if (SanityManager.DEBUG)
258                                SanityManager.THROWASSERT("Illegal state exception");
259                }
260                catch (GeneralSecurityException gse)
261                {
262                                                System.out.println("B " + gse);
263                        throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, gse);
264                }
265 
266                if (SanityManager.DEBUG)
267                        SanityManager.ASSERT(retval == length, "ciphertext length != length");
268 
269                return retval;
270        }
271 
272 
273        /**
274                @see CipherProvider#decrypt
275 
276                @exception StandardException Standard Cloudscape Error Policy
277         */
278        public int decrypt(byte[] ciphertext, int offset, int length,
279                                           byte[] cleartext, int outputOffset)
280                 throws StandardException
281        {
282                if (SanityManager.DEBUG)
283                {
284                        SanityManager.ASSERT(mode == CipherFactory.DECRYPT,
285                                                                 "calling decrypt on a encryption engine");
286                        SanityManager.ASSERT(ciphertext != null, "decrypting null ciphertext");
287                        SanityManager.ASSERT(offset >= 0, "offset < 0");
288                        SanityManager.ASSERT(length > 0, "length <= 0");
289                        SanityManager.ASSERT(offset+length <= ciphertext.length,
290                                                                 "offset+length > ciphertext.length");
291                        SanityManager.ASSERT(length <= cleartext.length-outputOffset,
292                                                                 "provided cleartexte buffer insufficient");
293                }
294 
295                int retval = 0;
296                try
297                {
298                        // this same cipher is shared across the entire raw store, make it
299                        // MT safe
300                        synchronized(this)
301                        {
302                if( !sunjce )
303                {
304                    // this code is a workaround for other providers
305                    try
306                    {
307                                    //ivspec = new IvParameterSpec(cipher.getIV());
308 
309                                    if (mode == CipherFactory.ENCRYPT)
310                                                {
311                                                        if (ivUsed)
312                                                                cipher.init(Cipher.ENCRYPT_MODE, cryptixKey, ivspec);
313                                                        else
314                                                                cipher.init(Cipher.ENCRYPT_MODE,cryptixKey);
315                                                }
316                                                else if (mode == CipherFactory.DECRYPT)
317                                                {
318                                                        if (ivUsed)
319                                                                cipher.init(Cipher.DECRYPT_MODE, cryptixKey, ivspec);
320                                                        else
321                                                                cipher.init(Cipher.DECRYPT_MODE, cryptixKey);
322                                                }
323 
324                    }
325                            catch (InvalidKeyException ike)
326                            {
327                                                System.out.println("C " + ike);
328                                    throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike);
329                            }
330 
331                }
332 
333                                retval = cipher.doFinal(ciphertext, offset, length, cleartext, outputOffset);
334                        }
335                }
336                catch (IllegalStateException ise)
337                {
338                        // should never happen
339                        if (SanityManager.DEBUG)
340                                SanityManager.THROWASSERT("Illegal state exception");
341                }
342                catch (GeneralSecurityException gse)
343                {
344                                                System.out.println("D " + gse);
345                        throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, gse);
346                }
347 
348                if (SanityManager.DEBUG)
349                {
350                        SanityManager.ASSERT(retval == length,
351                                                                 "cleartext length != length");
352                }
353 
354                return retval;
355        }
356 
357        boolean verifyIV(byte[] IV)
358        {
359                byte[] myIV = cipher.getIV();
360        // null IV is OK only if IV is not used
361        if (myIV == null)
362            return !ivUsed;
363                if (myIV.length != IV.length)
364                        return false;
365                for (int i = 0; i < IV.length; i++)
366                        if (myIV[i] != IV[i])
367                                return false;
368                return true;
369        }
370 
371        public int getEncryptionBlockSize()
372        {
373                return encryptionBlockSize;
374        }
375}

[all classes][org.apache.derby.impl.services.jce]
EMMA 2.0.5312 (C) Vladimir Roubtsov