• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.jcajce.provider.symmetric.util;
2 
3 import java.security.spec.AlgorithmParameterSpec;
4 
5 import javax.crypto.spec.PBEKeySpec;
6 import javax.crypto.spec.PBEParameterSpec;
7 
8 import org.bouncycastle.crypto.CipherParameters;
9 import org.bouncycastle.crypto.PBEParametersGenerator;
10 // BEGIN android-removed
11 // import org.bouncycastle.crypto.digests.GOST3411Digest;
12 // import org.bouncycastle.crypto.digests.MD2Digest;
13 // import org.bouncycastle.crypto.digests.MD5Digest;
14 // import org.bouncycastle.crypto.digests.RIPEMD160Digest;
15 // import org.bouncycastle.crypto.digests.SHA1Digest;
16 // import org.bouncycastle.crypto.digests.SHA256Digest;
17 // import org.bouncycastle.crypto.digests.TigerDigest;
18 // END android-removed
19 // BEGIN android-added
20 import org.bouncycastle.crypto.digests.AndroidDigestFactory;
21 // END android-added
22 import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
23 import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
24 import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
25 import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
26 import org.bouncycastle.crypto.params.DESParameters;
27 import org.bouncycastle.crypto.params.KeyParameter;
28 import org.bouncycastle.crypto.params.ParametersWithIV;
29 
30 public interface PBE
31 {
32     //
33     // PBE Based encryption constants - by default we do PKCS12 with SHA-1
34     //
35     static final int        MD5          = 0;
36     static final int        SHA1         = 1;
37     // BEGIN android-removed
38     // static final int        RIPEMD160    = 2;
39     // static final int        TIGER        = 3;
40     // END android-removed
41     static final int        SHA256       = 4;
42     // BEGIN android-removed
43     // static final int        MD2          = 5;
44     // static final int        GOST3411     = 6;
45     // END android-removed
46 
47     static final int        PKCS5S1      = 0;
48     static final int        PKCS5S2      = 1;
49     static final int        PKCS12       = 2;
50     static final int        OPENSSL      = 3;
51     static final int        PKCS5S1_UTF8 = 4;
52     static final int        PKCS5S2_UTF8 = 5;
53 
54     /**
55      * uses the appropriate mixer to generate the key and IV if necessary.
56      */
57     static class Util
58     {
makePBEGenerator( int type, int hash)59         static private PBEParametersGenerator makePBEGenerator(
60             int                     type,
61             int                     hash)
62         {
63             PBEParametersGenerator  generator;
64 
65             if (type == PKCS5S1 || type == PKCS5S1_UTF8)
66             {
67                 switch (hash)
68                 {
69                 // BEGIN android-removed
70                 // case MD2:
71                 //     generator = new PKCS5S1ParametersGenerator(new MD2Digest());
72                 //     break;
73                 // END android-removed
74                 case MD5:
75                     // BEGIN android-changed
76                     generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getMD5());
77                     // END android-changed
78                     break;
79                 case SHA1:
80                     // BEGIN android-changed
81                     generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getSHA1());
82                     // END android-changed
83                     break;
84                 default:
85                     throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1.");
86                 }
87             }
88             else if (type == PKCS5S2 || type == PKCS5S2_UTF8)
89             {
90                 switch (hash)
91                 {
92                 // BEGIN android-removed
93                 // case MD2:
94                 //     generator = new PKCS5S2ParametersGenerator(new MD2Digest());
95                 //     break;
96                 // END android-removed
97                 case MD5:
98                     // BEGIN android-changed
99                     generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5());
100                     // END android-changed
101                     break;
102                 case SHA1:
103                     // BEGIN android-changed
104                     generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1());
105                     // END android-changed
106                     break;
107                 // BEGIN android-removed
108                 // case RIPEMD160:
109                 //     generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest());
110                 //     break;
111                 // case TIGER:
112                 //     generator = new PKCS5S2ParametersGenerator(new TigerDigest());
113                 //     break;
114                 // END android-removed
115                 case SHA256:
116                     // BEGIN android-changed
117                     generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA256());
118                     // END android-changed
119                     break;
120                 // BEGIN android-removed
121                 // case GOST3411:
122                 //     generator = new PKCS5S2ParametersGenerator(new GOST3411Digest());
123                 //     break;
124                 // END android-removed
125                 default:
126                     throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
127                 }
128             }
129             else if (type == PKCS12)
130             {
131                 switch (hash)
132                 {
133                 // BEGIN android-removed
134                 // case MD2:
135                 //     generator = new PKCS12ParametersGenerator(new MD2Digest());
136                 //     break;
137                 // END android-removed
138                 case MD5:
139                     // BEGIN android-changed
140                     generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getMD5());
141                     // END android-changed
142                     break;
143                 case SHA1:
144                     // BEGIN android-changed
145                     generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA1());
146                     // END android-changed
147                     break;
148                 // BEGIN android-removed
149                 // case RIPEMD160:
150                 //     generator = new PKCS12ParametersGenerator(new RIPEMD160Digest());
151                 //     break;
152                 // case TIGER:
153                 //     generator = new PKCS12ParametersGenerator(new TigerDigest());
154                 //     break;
155                 // END android-removed
156                 case SHA256:
157                     // BEGIN android-changed
158                     generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA256());
159                     // END android-changed
160                     break;
161                 // BEGIN android-removed
162                 // case GOST3411:
163                 //     generator = new PKCS12ParametersGenerator(new GOST3411Digest());
164                 //     break;
165                 // END android-removed
166                 default:
167                     throw new IllegalStateException("unknown digest scheme for PBE encryption.");
168                 }
169             }
170             else
171             {
172                 generator = new OpenSSLPBEParametersGenerator();
173             }
174 
175             return generator;
176         }
177 
178         /**
179          * construct a key and iv (if necessary) suitable for use with a
180          * Cipher.
181          */
makePBEParameters( BCPBEKey pbeKey, AlgorithmParameterSpec spec, String targetAlgorithm)182         public static CipherParameters makePBEParameters(
183             BCPBEKey pbeKey,
184             AlgorithmParameterSpec spec,
185             String targetAlgorithm)
186         {
187             if ((spec == null) || !(spec instanceof PBEParameterSpec))
188             {
189                 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
190             }
191 
192             PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
193             PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
194             byte[]                  key = pbeKey.getEncoded();
195             CipherParameters        param;
196 
197             if (pbeKey.shouldTryWrongPKCS12())
198             {
199                 key = new byte[2];
200             }
201 
202             generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
203 
204             if (pbeKey.getIvSize() != 0)
205             {
206                 param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize());
207             }
208             else
209             {
210                 param = generator.generateDerivedParameters(pbeKey.getKeySize());
211             }
212 
213             if (targetAlgorithm.startsWith("DES"))
214             {
215                 if (param instanceof ParametersWithIV)
216                 {
217                     KeyParameter    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
218 
219                     DESParameters.setOddParity(kParam.getKey());
220                 }
221                 else
222                 {
223                     KeyParameter    kParam = (KeyParameter)param;
224 
225                     DESParameters.setOddParity(kParam.getKey());
226                 }
227             }
228 
229             for (int i = 0; i != key.length; i++)
230             {
231                 key[i] = 0;
232             }
233 
234             return param;
235         }
236 
237         /**
238          * generate a PBE based key suitable for a MAC algorithm, the
239          * key size is chosen according the MAC size, or the hashing algorithm,
240          * whichever is greater.
241          */
makePBEMacParameters( BCPBEKey pbeKey, AlgorithmParameterSpec spec)242         public static CipherParameters makePBEMacParameters(
243             BCPBEKey pbeKey,
244             AlgorithmParameterSpec spec)
245         {
246             if ((spec == null) || !(spec instanceof PBEParameterSpec))
247             {
248                 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
249             }
250 
251             PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
252             PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
253             byte[]                  key = pbeKey.getEncoded();
254             CipherParameters        param;
255 
256             if (pbeKey.shouldTryWrongPKCS12())
257             {
258                 key = new byte[2];
259             }
260 
261             generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
262 
263             param = generator.generateDerivedMacParameters(pbeKey.getKeySize());
264 
265             for (int i = 0; i != key.length; i++)
266             {
267                 key[i] = 0;
268             }
269 
270             return param;
271         }
272 
273         /**
274          * construct a key and iv (if necessary) suitable for use with a
275          * Cipher.
276          */
makePBEParameters( PBEKeySpec keySpec, int type, int hash, int keySize, int ivSize)277         public static CipherParameters makePBEParameters(
278             PBEKeySpec keySpec,
279             int type,
280             int hash,
281             int keySize,
282             int ivSize)
283         {
284             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
285             byte[]                  key;
286             CipherParameters        param;
287 
288             key = convertPassword(type, keySpec);
289 
290             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
291 
292             if (ivSize != 0)
293             {
294                 param = generator.generateDerivedParameters(keySize, ivSize);
295             }
296             else
297             {
298                 param = generator.generateDerivedParameters(keySize);
299             }
300 
301             for (int i = 0; i != key.length; i++)
302             {
303                 key[i] = 0;
304             }
305 
306             return param;
307         }
308 
309 
310         /**
311          * generate a PBE based key suitable for a MAC algorithm, the
312          * key size is chosen according the MAC size, or the hashing algorithm,
313          * whichever is greater.
314          */
makePBEMacParameters( PBEKeySpec keySpec, int type, int hash, int keySize)315         public static CipherParameters makePBEMacParameters(
316             PBEKeySpec keySpec,
317             int type,
318             int hash,
319             int keySize)
320         {
321             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
322             byte[]                  key;
323             CipherParameters        param;
324 
325             key = convertPassword(type, keySpec);
326 
327             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
328 
329             param = generator.generateDerivedMacParameters(keySize);
330 
331             for (int i = 0; i != key.length; i++)
332             {
333                 key[i] = 0;
334             }
335 
336             return param;
337         }
338 
convertPassword(int type, PBEKeySpec keySpec)339         private static byte[] convertPassword(int type, PBEKeySpec keySpec)
340         {
341             byte[] key;
342 
343             if (type == PKCS12)
344             {
345                 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
346             }
347             else if (type == PKCS5S2_UTF8 || type == PKCS5S1_UTF8)
348             {
349                 key = PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(keySpec.getPassword());
350             }
351             else
352             {
353                 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
354             }
355             return key;
356         }
357     }
358 }
359