Home | History | Annotate | Download | only in util
      1 package org.bouncycastle.jcajce.provider.symmetric.util;
      2 
      3 import java.security.AlgorithmParameters;
      4 import java.security.InvalidAlgorithmParameterException;
      5 import java.security.InvalidKeyException;
      6 import java.security.Key;
      7 import java.security.KeyFactory;
      8 import java.security.NoSuchAlgorithmException;
      9 import java.security.NoSuchProviderException;
     10 import java.security.PrivateKey;
     11 import java.security.SecureRandom;
     12 import java.security.spec.AlgorithmParameterSpec;
     13 import java.security.spec.InvalidKeySpecException;
     14 import java.security.spec.PKCS8EncodedKeySpec;
     15 import java.security.spec.X509EncodedKeySpec;
     16 
     17 import javax.crypto.BadPaddingException;
     18 import javax.crypto.Cipher;
     19 import javax.crypto.CipherSpi;
     20 import javax.crypto.IllegalBlockSizeException;
     21 import javax.crypto.NoSuchPaddingException;
     22 import javax.crypto.ShortBufferException;
     23 import javax.crypto.spec.IvParameterSpec;
     24 import javax.crypto.spec.PBEParameterSpec;
     25 // BEGIN android-removed
     26 // import javax.crypto.spec.RC2ParameterSpec;
     27 // import javax.crypto.spec.RC5ParameterSpec;
     28 // END android-removed
     29 import javax.crypto.spec.SecretKeySpec;
     30 
     31 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
     32 import org.bouncycastle.crypto.CipherParameters;
     33 import org.bouncycastle.crypto.InvalidCipherTextException;
     34 import org.bouncycastle.crypto.Wrapper;
     35 import org.bouncycastle.crypto.params.KeyParameter;
     36 import org.bouncycastle.crypto.params.ParametersWithIV;
     37 import org.bouncycastle.jce.provider.BouncyCastleProvider;
     38 
     39 public abstract class BaseWrapCipher
     40     extends CipherSpi
     41     implements PBE
     42 {
     43     //
     44     // specs we can handle.
     45     //
     46     private Class[]                 availableSpecs =
     47                                     {
     48                                         IvParameterSpec.class,
     49                                         PBEParameterSpec.class,
     50                                         // BEGIN android-removed
     51                                         // RC2ParameterSpec.class,
     52                                         // RC5ParameterSpec.class
     53                                         // END android-removed
     54                                     };
     55 
     56     protected int                     pbeType = PKCS12;
     57     protected int                     pbeHash = SHA1;
     58     protected int                     pbeKeySize;
     59     protected int                     pbeIvSize;
     60 
     61     protected AlgorithmParameters     engineParams = null;
     62 
     63     protected Wrapper                 wrapEngine = null;
     64 
     65     private int                       ivSize;
     66     private byte[]                    iv;
     67 
     68     protected BaseWrapCipher()
     69     {
     70     }
     71 
     72     protected BaseWrapCipher(
     73         Wrapper wrapEngine)
     74     {
     75         this(wrapEngine, 0);
     76     }
     77 
     78     protected BaseWrapCipher(
     79         Wrapper wrapEngine,
     80         int ivSize)
     81     {
     82         this.wrapEngine = wrapEngine;
     83         this.ivSize = ivSize;
     84     }
     85 
     86     protected int engineGetBlockSize()
     87     {
     88         return 0;
     89     }
     90 
     91     protected byte[] engineGetIV()
     92     {
     93         return (byte[])iv.clone();
     94     }
     95 
     96     protected int engineGetKeySize(
     97         Key     key)
     98     {
     99         return key.getEncoded().length;
    100     }
    101 
    102     protected int engineGetOutputSize(
    103         int     inputLen)
    104     {
    105         return -1;
    106     }
    107 
    108     protected AlgorithmParameters engineGetParameters()
    109     {
    110         return null;
    111     }
    112 
    113     protected void engineSetMode(
    114         String  mode)
    115         throws NoSuchAlgorithmException
    116     {
    117         throw new NoSuchAlgorithmException("can't support mode " + mode);
    118     }
    119 
    120     protected void engineSetPadding(
    121         String  padding)
    122     throws NoSuchPaddingException
    123     {
    124         throw new NoSuchPaddingException("Padding " + padding + " unknown.");
    125     }
    126 
    127     protected void engineInit(
    128         int                     opmode,
    129         Key                     key,
    130         AlgorithmParameterSpec  params,
    131         SecureRandom            random)
    132     throws InvalidKeyException, InvalidAlgorithmParameterException
    133     {
    134         CipherParameters        param;
    135 
    136         if (key instanceof BCPBEKey)
    137         {
    138             BCPBEKey k = (BCPBEKey)key;
    139 
    140             if (params instanceof PBEParameterSpec)
    141             {
    142                 param = PBE.Util.makePBEParameters(k, params, wrapEngine.getAlgorithmName());
    143             }
    144             else if (k.getParam() != null)
    145             {
    146                 param = k.getParam();
    147             }
    148             else
    149             {
    150                 throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
    151             }
    152         }
    153         else
    154         {
    155             param = new KeyParameter(key.getEncoded());
    156         }
    157 
    158         if (params instanceof IvParameterSpec)
    159         {
    160             IvParameterSpec iv = (IvParameterSpec) params;
    161             param = new ParametersWithIV(param, iv.getIV());
    162         }
    163 
    164         if (param instanceof KeyParameter && ivSize != 0)
    165         {
    166             iv = new byte[ivSize];
    167             random.nextBytes(iv);
    168             param = new ParametersWithIV(param, iv);
    169         }
    170 
    171         switch (opmode)
    172         {
    173         case Cipher.WRAP_MODE:
    174             wrapEngine.init(true, param);
    175             break;
    176         case Cipher.UNWRAP_MODE:
    177             wrapEngine.init(false, param);
    178             break;
    179         case Cipher.ENCRYPT_MODE:
    180         case Cipher.DECRYPT_MODE:
    181             throw new IllegalArgumentException("engine only valid for wrapping");
    182         default:
    183             System.out.println("eeek!");
    184         }
    185     }
    186 
    187     protected void engineInit(
    188         int                 opmode,
    189         Key                 key,
    190         AlgorithmParameters params,
    191         SecureRandom        random)
    192     throws InvalidKeyException, InvalidAlgorithmParameterException
    193     {
    194         AlgorithmParameterSpec  paramSpec = null;
    195 
    196         if (params != null)
    197         {
    198             for (int i = 0; i != availableSpecs.length; i++)
    199             {
    200                 try
    201                 {
    202                     paramSpec = params.getParameterSpec(availableSpecs[i]);
    203                     break;
    204                 }
    205                 catch (Exception e)
    206                 {
    207                     // try next spec
    208                 }
    209             }
    210 
    211             if (paramSpec == null)
    212             {
    213                 throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
    214             }
    215         }
    216 
    217         engineParams = params;
    218         engineInit(opmode, key, paramSpec, random);
    219     }
    220 
    221     protected void engineInit(
    222         int                 opmode,
    223         Key                 key,
    224         SecureRandom        random)
    225         throws InvalidKeyException
    226     {
    227         try
    228         {
    229             engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
    230         }
    231         catch (InvalidAlgorithmParameterException e)
    232         {
    233             throw new IllegalArgumentException(e.getMessage());
    234         }
    235     }
    236 
    237     protected byte[] engineUpdate(
    238         byte[]  input,
    239         int     inputOffset,
    240         int     inputLen)
    241     {
    242         throw new RuntimeException("not supported for wrapping");
    243     }
    244 
    245     protected int engineUpdate(
    246         byte[]  input,
    247         int     inputOffset,
    248         int     inputLen,
    249         byte[]  output,
    250         int     outputOffset)
    251         throws ShortBufferException
    252     {
    253         throw new RuntimeException("not supported for wrapping");
    254     }
    255 
    256     protected byte[] engineDoFinal(
    257         byte[]  input,
    258         int     inputOffset,
    259         int     inputLen)
    260         throws IllegalBlockSizeException, BadPaddingException
    261     {
    262         return null;
    263     }
    264 
    265     // BEGIN android-changed
    266     // added ShortBufferException to throws statement
    267     protected int engineDoFinal(
    268         byte[]  input,
    269         int     inputOffset,
    270         int     inputLen,
    271         byte[]  output,
    272         int     outputOffset)
    273         throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
    274     {
    275         return 0;
    276     }
    277     // END android-changed
    278 
    279     protected byte[] engineWrap(
    280         Key     key)
    281     throws IllegalBlockSizeException, InvalidKeyException
    282     {
    283         byte[] encoded = key.getEncoded();
    284         if (encoded == null)
    285         {
    286             throw new InvalidKeyException("Cannot wrap key, null encoding.");
    287         }
    288 
    289         try
    290         {
    291             if (wrapEngine == null)
    292             {
    293                 return engineDoFinal(encoded, 0, encoded.length);
    294             }
    295             else
    296             {
    297                 return wrapEngine.wrap(encoded, 0, encoded.length);
    298             }
    299         }
    300         catch (BadPaddingException e)
    301         {
    302             throw new IllegalBlockSizeException(e.getMessage());
    303         }
    304     }
    305 
    306     protected Key engineUnwrap(
    307         byte[]  wrappedKey,
    308         String  wrappedKeyAlgorithm,
    309         int     wrappedKeyType)
    310     throws InvalidKeyException, NoSuchAlgorithmException
    311     {
    312         byte[] encoded;
    313         try
    314         {
    315             if (wrapEngine == null)
    316             {
    317                 encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
    318             }
    319             else
    320             {
    321                 encoded = wrapEngine.unwrap(wrappedKey, 0, wrappedKey.length);
    322             }
    323         }
    324         catch (InvalidCipherTextException e)
    325         {
    326             throw new InvalidKeyException(e.getMessage());
    327         }
    328         catch (BadPaddingException e)
    329         {
    330             throw new InvalidKeyException(e.getMessage());
    331         }
    332         catch (IllegalBlockSizeException e2)
    333         {
    334             throw new InvalidKeyException(e2.getMessage());
    335         }
    336 
    337         if (wrappedKeyType == Cipher.SECRET_KEY)
    338         {
    339             return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
    340         }
    341         else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY)
    342         {
    343             /*
    344              * The caller doesn't know the algorithm as it is part of
    345              * the encrypted data.
    346              */
    347             try
    348             {
    349                 PrivateKeyInfo       in = PrivateKeyInfo.getInstance(encoded);
    350 
    351                 PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in);
    352 
    353                 if (privKey != null)
    354                 {
    355                     return privKey;
    356                 }
    357                 else
    358                 {
    359                     throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported");
    360                 }
    361             }
    362             catch (Exception e)
    363             {
    364                 throw new InvalidKeyException("Invalid key encoding.");
    365             }
    366         }
    367         else
    368         {
    369             try
    370             {
    371                 KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
    372 
    373                 if (wrappedKeyType == Cipher.PUBLIC_KEY)
    374                 {
    375                     return kf.generatePublic(new X509EncodedKeySpec(encoded));
    376                 }
    377                 else if (wrappedKeyType == Cipher.PRIVATE_KEY)
    378                 {
    379                     return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
    380                 }
    381             }
    382             catch (NoSuchProviderException e)
    383             {
    384                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
    385             }
    386             catch (InvalidKeySpecException e2)
    387             {
    388                 throw new InvalidKeyException("Unknown key type " + e2.getMessage());
    389             }
    390 
    391             throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
    392         }
    393     }
    394 
    395 }
    396