1package org.bouncycastle.jcajce.provider.symmetric;
2
3import java.security.AlgorithmParameters;
4import java.security.InvalidAlgorithmParameterException;
5import java.security.SecureRandom;
6import java.security.spec.AlgorithmParameterSpec;
7import java.security.spec.InvalidKeySpecException;
8import java.security.spec.KeySpec;
9
10import javax.crypto.SecretKey;
11import javax.crypto.spec.DESKeySpec;
12import javax.crypto.spec.IvParameterSpec;
13import javax.crypto.spec.PBEKeySpec;
14import javax.crypto.spec.SecretKeySpec;
15
16import org.bouncycastle.asn1.ASN1ObjectIdentifier;
17import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
18import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
19import org.bouncycastle.crypto.CipherParameters;
20import org.bouncycastle.crypto.KeyGenerationParameters;
21import org.bouncycastle.crypto.engines.DESEngine;
22// Android-removed: Unsupported algorithms
23// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
24import org.bouncycastle.crypto.generators.DESKeyGenerator;
25import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
26// Android-removed: Unsupported algorithms
27// import org.bouncycastle.crypto.macs.CFBBlockCipherMac;
28// import org.bouncycastle.crypto.macs.CMac;
29// import org.bouncycastle.crypto.macs.ISO9797Alg3Mac;
30import org.bouncycastle.crypto.modes.CBCBlockCipher;
31import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
32import org.bouncycastle.crypto.params.DESParameters;
33import org.bouncycastle.crypto.params.KeyParameter;
34import org.bouncycastle.crypto.params.ParametersWithIV;
35import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
36import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
37import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
38import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
39import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
40import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
41import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
42import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher;
43import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
44import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
45
46public final class DES
47{
48    private DES()
49    {
50    }
51
52    static public class ECB
53        extends BaseBlockCipher
54    {
55        public ECB()
56        {
57            super(new DESEngine());
58        }
59    }
60
61    static public class CBC
62        extends BaseBlockCipher
63    {
64        public CBC()
65        {
66            super(new CBCBlockCipher(new DESEngine()), 64);
67        }
68    }
69
70    // BEGIN Android-removed: Unsupported algorithms
71    /*
72    /**
73     * DES   CFB8
74     *
75    public static class DESCFB8
76        extends BaseMac
77    {
78        public DESCFB8()
79        {
80            super(new CFBBlockCipherMac(new DESEngine()));
81        }
82    }
83    */
84    // END Android-removed: Unsupported algorithms
85
86    /**
87     * DES64
88     */
89    public static class DES64
90        extends BaseMac
91    {
92        public DES64()
93        {
94            super(new CBCBlockCipherMac(new DESEngine(), 64));
95        }
96    }
97
98    /**
99     * DES64with7816-4Padding
100     */
101    public static class DES64with7816d4
102        extends BaseMac
103    {
104        public DES64with7816d4()
105        {
106            super(new CBCBlockCipherMac(new DESEngine(), 64, new ISO7816d4Padding()));
107        }
108    }
109
110    public static class CBCMAC
111        extends BaseMac
112    {
113        public CBCMAC()
114        {
115            super(new CBCBlockCipherMac(new DESEngine()));
116        }
117    }
118
119    // BEGIN Android-removed: Unsupported algorithms
120    /*
121    static public class CMAC
122        extends BaseMac
123    {
124        public CMAC()
125        {
126            super(new CMac(new DESEngine()));
127        }
128    }
129
130    /**
131     * DES9797Alg3with7816-4Padding
132     *
133    public static class DES9797Alg3with7816d4
134        extends BaseMac
135    {
136        public DES9797Alg3with7816d4()
137        {
138            super(new ISO9797Alg3Mac(new DESEngine(), new ISO7816d4Padding()));
139        }
140    }
141
142    /**
143     * DES9797Alg3
144     *
145    public static class DES9797Alg3
146        extends BaseMac
147    {
148        public DES9797Alg3()
149        {
150            super(new ISO9797Alg3Mac(new DESEngine()));
151        }
152    }
153
154    public static class RFC3211
155        extends BaseWrapCipher
156    {
157        public RFC3211()
158        {
159            super(new RFC3211WrapEngine(new DESEngine()), 8);
160        }
161    }
162
163    public static class AlgParamGen
164        extends BaseAlgorithmParameterGenerator
165    {
166        protected void engineInit(
167            AlgorithmParameterSpec genParamSpec,
168            SecureRandom            random)
169            throws InvalidAlgorithmParameterException
170        {
171            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation.");
172        }
173
174        protected AlgorithmParameters engineGenerateParameters()
175        {
176            byte[]  iv = new byte[8];
177
178            if (random == null)
179            {
180                random = new SecureRandom();
181            }
182
183            random.nextBytes(iv);
184
185            AlgorithmParameters params;
186
187            try
188            {
189                params = createParametersInstance("DES");
190                params.init(new IvParameterSpec(iv));
191            }
192            catch (Exception e)
193            {
194                throw new RuntimeException(e.getMessage());
195            }
196
197            return params;
198        }
199    }
200    */
201    // END Android-removed: Unsupported algorithms
202
203  /**
204     * DES - the default for this is to generate a key in
205     * a-b-a format that's 24 bytes long but has 16 bytes of
206     * key material (the first 8 bytes is repeated as the last
207     * 8 bytes). If you give it a size, you'll get just what you
208     * asked for.
209     */
210    public static class KeyGenerator
211        extends BaseKeyGenerator
212    {
213        public KeyGenerator()
214        {
215            super("DES", 64, new DESKeyGenerator());
216        }
217
218        protected void engineInit(
219            int             keySize,
220            SecureRandom random)
221        {
222            super.engineInit(keySize, random);
223        }
224
225        protected SecretKey engineGenerateKey()
226        {
227            if (uninitialised)
228            {
229                engine.init(new KeyGenerationParameters(new SecureRandom(), defaultKeySize));
230                uninitialised = false;
231            }
232
233            return new SecretKeySpec(engine.generateKey(), algName);
234        }
235    }
236
237    static public class KeyFactory
238        extends BaseSecretKeyFactory
239    {
240        public KeyFactory()
241        {
242            super("DES", null);
243        }
244
245        protected KeySpec engineGetKeySpec(
246            SecretKey key,
247            Class keySpec)
248        throws InvalidKeySpecException
249        {
250            if (keySpec == null)
251            {
252                throw new InvalidKeySpecException("keySpec parameter is null");
253            }
254            if (key == null)
255            {
256                throw new InvalidKeySpecException("key parameter is null");
257            }
258
259            if (SecretKeySpec.class.isAssignableFrom(keySpec))
260            {
261                return new SecretKeySpec(key.getEncoded(), algName);
262            }
263            else if (DESKeySpec.class.isAssignableFrom(keySpec))
264            {
265                byte[]  bytes = key.getEncoded();
266
267                try
268                {
269                    return new DESKeySpec(bytes);
270                }
271                catch (Exception e)
272                {
273                    throw new InvalidKeySpecException(e.toString());
274                }
275            }
276
277            throw new InvalidKeySpecException("Invalid KeySpec");
278        }
279
280        protected SecretKey engineGenerateSecret(
281            KeySpec keySpec)
282        throws InvalidKeySpecException
283        {
284            if (keySpec instanceof DESKeySpec)
285            {
286                DESKeySpec desKeySpec = (DESKeySpec)keySpec;
287                return new SecretKeySpec(desKeySpec.getKey(), "DES");
288            }
289
290            return super.engineGenerateSecret(keySpec);
291        }
292    }
293
294    static public class DESPBEKeyFactory
295        extends BaseSecretKeyFactory
296    {
297        private boolean forCipher;
298        private int     scheme;
299        private int     digest;
300        private int     keySize;
301        private int     ivSize;
302
303        public DESPBEKeyFactory(
304            String              algorithm,
305            ASN1ObjectIdentifier oid,
306            boolean             forCipher,
307            int                 scheme,
308            int                 digest,
309            int                 keySize,
310            int                 ivSize)
311        {
312            super(algorithm, oid);
313
314            this.forCipher = forCipher;
315            this.scheme = scheme;
316            this.digest = digest;
317            this.keySize = keySize;
318            this.ivSize = ivSize;
319        }
320
321        protected SecretKey engineGenerateSecret(
322            KeySpec keySpec)
323        throws InvalidKeySpecException
324        {
325            if (keySpec instanceof PBEKeySpec)
326            {
327                PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
328                CipherParameters param;
329
330                if (pbeSpec.getSalt() == null)
331                {
332                    return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
333                }
334
335                if (forCipher)
336                {
337                    param = PBE.Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize);
338                }
339                else
340                {
341                    param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
342                }
343
344                KeyParameter kParam;
345                if (param instanceof ParametersWithIV)
346                {
347                    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
348                }
349                else
350                {
351                    kParam = (KeyParameter)param;
352                }
353
354                DESParameters.setOddParity(kParam.getKey());
355
356                return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
357            }
358
359            throw new InvalidKeySpecException("Invalid KeySpec");
360        }
361    }
362
363    // BEGIN Android-removed: Unsupported algorithms
364    /*
365    /**
366     * PBEWithMD2AndDES
367     *
368    static public class PBEWithMD2KeyFactory
369        extends DESPBEKeyFactory
370    {
371        public PBEWithMD2KeyFactory()
372        {
373            super("PBEwithMD2andDES", PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, true, PKCS5S1, MD2, 64, 64);
374        }
375    }
376    */
377    // END Android-removed: Unsupported algorithms
378
379    /**
380     * PBEWithMD5AndDES
381     */
382    static public class PBEWithMD5KeyFactory
383        extends DESPBEKeyFactory
384    {
385        public PBEWithMD5KeyFactory()
386        {
387            super("PBEwithMD5andDES", PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, true, PKCS5S1, MD5, 64, 64);
388        }
389    }
390
391    /**
392     * PBEWithSHA1AndDES
393     */
394    static public class PBEWithSHA1KeyFactory
395        extends DESPBEKeyFactory
396    {
397        public PBEWithSHA1KeyFactory()
398        {
399            super("PBEwithSHA1andDES", PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, true, PKCS5S1, SHA1, 64, 64);
400        }
401    }
402
403    // BEGIN Android-removed: Unsupported algorithms
404    /*
405    /**
406     * PBEWithMD2AndDES
407     *
408    static public class PBEWithMD2
409        extends BaseBlockCipher
410    {
411        public PBEWithMD2()
412        {
413            super(new CBCBlockCipher(new DESEngine()), PKCS5S1, MD2, 64, 8);
414        }
415    }
416    */
417    // END Android-removed: Unsupported algorithms
418
419    /**
420     * PBEWithMD5AndDES
421     */
422    static public class PBEWithMD5
423        extends BaseBlockCipher
424    {
425        public PBEWithMD5()
426        {
427            super(new CBCBlockCipher(new DESEngine()), PKCS5S1, MD5, 64, 8);
428        }
429    }
430
431    /**
432     * PBEWithSHA1AndDES
433     */
434    static public class PBEWithSHA1
435        extends BaseBlockCipher
436    {
437        public PBEWithSHA1()
438        {
439            super(new CBCBlockCipher(new DESEngine()), PKCS5S1, SHA1, 64, 8);
440        }
441    }
442
443    public static class Mappings
444        extends AlgorithmProvider
445    {
446        private static final String PREFIX = DES.class.getName();
447        private static final String PACKAGE = "org.bouncycastle.jcajce.provider.symmetric"; // JDK 1.2
448
449        public Mappings()
450        {
451        }
452
453        public void configure(ConfigurableProvider provider)
454        {
455
456            provider.addAlgorithm("Cipher.DES", PREFIX + "$ECB");
457            // BEGIN Android-removed: Unsupported algorithms
458            /*
459            provider.addAlgorithm("Cipher", OIWObjectIdentifiers.desCBC, PREFIX + "$CBC");
460
461            addAlias(provider, OIWObjectIdentifiers.desCBC, "DES");
462
463            provider.addAlgorithm("Cipher.DESRFC3211WRAP", PREFIX + "$RFC3211");
464            */
465            // END Android-removed: Unsupported algorithms
466
467            provider.addAlgorithm("KeyGenerator.DES", PREFIX + "$KeyGenerator");
468
469            provider.addAlgorithm("SecretKeyFactory.DES", PREFIX + "$KeyFactory");
470
471            // BEGIN Android-removed: Unsupported algorithms
472            /*
473            provider.addAlgorithm("Mac.DESCMAC", PREFIX + "$CMAC");
474            provider.addAlgorithm("Mac.DESMAC", PREFIX + "$CBCMAC");
475            provider.addAlgorithm("Alg.Alias.Mac.DES", "DESMAC");
476
477            provider.addAlgorithm("Mac.DESMAC/CFB8", PREFIX + "$DESCFB8");
478            provider.addAlgorithm("Alg.Alias.Mac.DES/CFB8", "DESMAC/CFB8");
479
480            provider.addAlgorithm("Mac.DESMAC64", PREFIX + "$DES64");
481            provider.addAlgorithm("Alg.Alias.Mac.DES64", "DESMAC64");
482
483            provider.addAlgorithm("Mac.DESMAC64WITHISO7816-4PADDING", PREFIX + "$DES64with7816d4");
484            provider.addAlgorithm("Alg.Alias.Mac.DES64WITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
485            provider.addAlgorithm("Alg.Alias.Mac.DESISO9797ALG1MACWITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
486            provider.addAlgorithm("Alg.Alias.Mac.DESISO9797ALG1WITHISO7816-4PADDING", "DESMAC64WITHISO7816-4PADDING");
487
488            provider.addAlgorithm("Mac.DESWITHISO9797", PREFIX + "$DES9797Alg3");
489            provider.addAlgorithm("Alg.Alias.Mac.DESISO9797MAC", "DESWITHISO9797");
490
491            provider.addAlgorithm("Mac.ISO9797ALG3MAC", PREFIX + "$DES9797Alg3");
492            provider.addAlgorithm("Alg.Alias.Mac.ISO9797ALG3", "ISO9797ALG3MAC");
493            provider.addAlgorithm("Mac.ISO9797ALG3WITHISO7816-4PADDING", PREFIX + "$DES9797Alg3with7816d4");
494            provider.addAlgorithm("Alg.Alias.Mac.ISO9797ALG3MACWITHISO7816-4PADDING", "ISO9797ALG3WITHISO7816-4PADDING");
495            */
496            // END Android-removed: Unsupported algorithms
497
498            provider.addAlgorithm("AlgorithmParameters.DES", PACKAGE + ".util.IvAlgorithmParameters");
499            provider.addAlgorithm("Alg.Alias.AlgorithmParameters", OIWObjectIdentifiers.desCBC, "DES");
500
501            // BEGIN Android-removed: Unsupported algorithms
502            // provider.addAlgorithm("AlgorithmParameterGenerator.DES",  PREFIX + "$AlgParamGen");
503            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + OIWObjectIdentifiers.desCBC, "DES");
504            //
505            // provider.addAlgorithm("Cipher.PBEWITHMD2ANDDES", PREFIX + "$PBEWithMD2");
506            // END Android-removed: Unsupported algorithms
507            provider.addAlgorithm("Cipher.PBEWITHMD5ANDDES", PREFIX + "$PBEWithMD5");
508            provider.addAlgorithm("Cipher.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1");
509
510            // Android-removed: Unsupported algorithms
511            // provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES");
512            provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
513            provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
514
515            // Android-removed: Unsupported algorithms
516            // provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD2ANDDES-CBC", "PBEWITHMD2ANDDES");
517            provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD5ANDDES-CBC", "PBEWITHMD5ANDDES");
518            provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDDES-CBC", "PBEWITHSHA1ANDDES");
519
520            // Android-removed: Unsupported algorithms
521            // provider.addAlgorithm("SecretKeyFactory.PBEWITHMD2ANDDES", PREFIX + "$PBEWithMD2KeyFactory");
522            provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5ANDDES", PREFIX + "$PBEWithMD5KeyFactory");
523            provider.addAlgorithm("SecretKeyFactory.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1KeyFactory");
524
525            // Android-removed: Unsupported algorithms
526            // provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHMD2ANDDES-CBC", "PBEWITHMD2ANDDES");
527            provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDDES-CBC", "PBEWITHMD5ANDDES");
528            provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDDES-CBC", "PBEWITHSHA1ANDDES");
529            // Android-removed: Unsupported algorithms
530            // provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES");
531            provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
532            provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
533        }
534
535        private void addAlias(ConfigurableProvider provider, ASN1ObjectIdentifier oid, String name)
536        {
537            provider.addAlgorithm("Alg.Alias.KeyGenerator." + oid.getId(), name);
538            provider.addAlgorithm("Alg.Alias.KeyFactory." + oid.getId(), name);
539        }
540    }
541}
542