Home | History | Annotate | Download | only in provider
      1 package org.bouncycastle.jce.provider;
      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.MD2Digest;
     12 // END android-removed
     13 import org.bouncycastle.crypto.digests.MD5Digest;
     14 // BEGIN android-removed
     15 // import org.bouncycastle.crypto.digests.RIPEMD160Digest;
     16 // END android-removed
     17 import org.bouncycastle.crypto.digests.SHA1Digest;
     18 import org.bouncycastle.crypto.digests.SHA256Digest;
     19 // BEGIN android-removed
     20 // import org.bouncycastle.crypto.digests.TigerDigest;
     21 // END android-removed
     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     static final int        RIPEMD160   = 2;
     38     static final int        TIGER       = 3;
     39     static final int        SHA256      = 4;
     40     static final int        MD2         = 5;
     41 
     42     static final int        PKCS5S1     = 0;
     43     static final int        PKCS5S2     = 1;
     44     static final int        PKCS12      = 2;
     45     static final int        OPENSSL     = 3;
     46 
     47     /**
     48      * uses the appropriate mixer to generate the key and IV if necessary.
     49      */
     50     static class Util
     51     {
     52         static private PBEParametersGenerator makePBEGenerator(
     53             int                     type,
     54             int                     hash)
     55         {
     56             PBEParametersGenerator  generator;
     57 
     58             if (type == PKCS5S1)
     59             {
     60                 switch (hash)
     61                 {
     62                 // BEGIN android-removed
     63                 // case MD2:
     64                 //     generator = new PKCS5S1ParametersGenerator(new MD2Digest());
     65                 //     break;
     66                 // END android-removed
     67                 case MD5:
     68                     generator = new PKCS5S1ParametersGenerator(new MD5Digest());
     69                     break;
     70                 case SHA1:
     71                     generator = new PKCS5S1ParametersGenerator(new SHA1Digest());
     72                     break;
     73                 default:
     74                     throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1.");
     75                 }
     76             }
     77             else if (type == PKCS5S2)
     78             {
     79                 generator = new PKCS5S2ParametersGenerator();
     80             }
     81             else if (type == PKCS12)
     82             {
     83                 switch (hash)
     84                 {
     85                 // BEGIN android-removed
     86                 // case MD2:
     87                 //     generator = new PKCS12ParametersGenerator(new MD2Digest());
     88                 //     break;
     89                 // END android-removed
     90                 case MD5:
     91                     generator = new PKCS12ParametersGenerator(new MD5Digest());
     92                     break;
     93                 case SHA1:
     94                     generator = new PKCS12ParametersGenerator(new SHA1Digest());
     95                     break;
     96                 // BEGIN android-removed
     97                 // case RIPEMD160:
     98                 //     generator = new PKCS12ParametersGenerator(new RIPEMD160Digest());
     99                 //     break;
    100                 // case TIGER:
    101                 //     generator = new PKCS12ParametersGenerator(new TigerDigest());
    102                 //     break;
    103                 // END android-removed
    104                 case SHA256:
    105                     generator = new PKCS12ParametersGenerator(new SHA256Digest());
    106                     break;
    107                 default:
    108                     throw new IllegalStateException("unknown digest scheme for PBE encryption.");
    109                 }
    110             }
    111             else
    112             {
    113                 generator = new OpenSSLPBEParametersGenerator();
    114             }
    115 
    116             return generator;
    117         }
    118 
    119         /**
    120          * construct a key and iv (if necessary) suitable for use with a
    121          * Cipher.
    122          */
    123         static CipherParameters makePBEParameters(
    124             JCEPBEKey               pbeKey,
    125             AlgorithmParameterSpec  spec,
    126             String                  targetAlgorithm)
    127         {
    128             if ((spec == null) || !(spec instanceof PBEParameterSpec))
    129             {
    130                 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
    131             }
    132 
    133             PBEParameterSpec        pbeParam = (PBEParameterSpec)spec;
    134             PBEParametersGenerator  generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
    135             byte[]                  key = pbeKey.getEncoded();
    136             CipherParameters        param;
    137 
    138             if (pbeKey.shouldTryWrongPKCS12())
    139             {
    140                 key = new byte[2];
    141             }
    142 
    143             generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
    144 
    145             if (pbeKey.getIvSize() != 0)
    146             {
    147                 param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize());
    148             }
    149             else
    150             {
    151                 param = generator.generateDerivedParameters(pbeKey.getKeySize());
    152             }
    153 
    154             if (targetAlgorithm.startsWith("DES"))
    155             {
    156                 if (param instanceof ParametersWithIV)
    157                 {
    158                     KeyParameter    kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
    159 
    160                     DESParameters.setOddParity(kParam.getKey());
    161                 }
    162                 else
    163                 {
    164                     KeyParameter    kParam = (KeyParameter)param;
    165 
    166                     DESParameters.setOddParity(kParam.getKey());
    167                 }
    168             }
    169 
    170             for (int i = 0; i != key.length; i++)
    171             {
    172                 key[i] = 0;
    173             }
    174 
    175             return param;
    176         }
    177 
    178         /**
    179          * generate a PBE based key suitable for a MAC algorithm, the
    180          * key size is chosen according the MAC size, or the hashing algorithm,
    181          * whichever is greater.
    182          */
    183         static CipherParameters makePBEMacParameters(
    184             JCEPBEKey               pbeKey,
    185             AlgorithmParameterSpec  spec)
    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             param = generator.generateDerivedMacParameters(pbeKey.getKeySize());
    205 
    206             for (int i = 0; i != key.length; i++)
    207             {
    208                 key[i] = 0;
    209             }
    210 
    211             return param;
    212         }
    213 
    214         /**
    215          * construct a key and iv (if necessary) suitable for use with a
    216          * Cipher.
    217          */
    218         static CipherParameters makePBEParameters(
    219             PBEKeySpec              keySpec,
    220             int                     type,
    221             int                     hash,
    222             int                     keySize,
    223             int                     ivSize)
    224         {
    225             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
    226             byte[]                  key;
    227             CipherParameters        param;
    228 
    229             if (type == PKCS12)
    230             {
    231                 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
    232             }
    233             else
    234             {
    235                 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
    236             }
    237 
    238             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
    239 
    240             if (ivSize != 0)
    241             {
    242                 param = generator.generateDerivedParameters(keySize, ivSize);
    243             }
    244             else
    245             {
    246                 param = generator.generateDerivedParameters(keySize);
    247             }
    248 
    249             for (int i = 0; i != key.length; i++)
    250             {
    251                 key[i] = 0;
    252             }
    253 
    254             return param;
    255         }
    256 
    257         /**
    258          * generate a PBE based key suitable for a MAC algorithm, the
    259          * key size is chosen according the MAC size, or the hashing algorithm,
    260          * whichever is greater.
    261          */
    262         static CipherParameters makePBEMacParameters(
    263             PBEKeySpec              keySpec,
    264             int                     type,
    265             int                     hash,
    266             int                     keySize)
    267         {
    268             PBEParametersGenerator  generator = makePBEGenerator(type, hash);
    269             byte[]                  key;
    270             CipherParameters        param;
    271 
    272             if (type == PKCS12)
    273             {
    274                 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
    275             }
    276             else
    277             {
    278                 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
    279             }
    280 
    281             generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
    282 
    283             param = generator.generateDerivedMacParameters(keySize);
    284 
    285             for (int i = 0; i != key.length; i++)
    286             {
    287                 key[i] = 0;
    288             }
    289 
    290             return param;
    291         }
    292     }
    293 }
    294