Home | History | Annotate | Download | only in util
      1 package org.bouncycastle.jcajce.provider.asymmetric.util;
      2 
      3 import java.security.AlgorithmParameters;
      4 import java.security.InvalidKeyException;
      5 import java.security.Key;
      6 import java.security.KeyFactory;
      7 import java.security.NoSuchAlgorithmException;
      8 import java.security.NoSuchProviderException;
      9 import java.security.PrivateKey;
     10 import java.security.spec.InvalidKeySpecException;
     11 import java.security.spec.PKCS8EncodedKeySpec;
     12 import java.security.spec.X509EncodedKeySpec;
     13 
     14 import javax.crypto.BadPaddingException;
     15 import javax.crypto.Cipher;
     16 import javax.crypto.CipherSpi;
     17 import javax.crypto.IllegalBlockSizeException;
     18 import javax.crypto.NoSuchPaddingException;
     19 import javax.crypto.spec.IvParameterSpec;
     20 import javax.crypto.spec.PBEParameterSpec;
     21 // BEGIN android-removed
     22 // import javax.crypto.spec.RC2ParameterSpec;
     23 // import javax.crypto.spec.RC5ParameterSpec;
     24 // END android-removed
     25 import javax.crypto.spec.SecretKeySpec;
     26 
     27 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
     28 import org.bouncycastle.crypto.InvalidCipherTextException;
     29 import org.bouncycastle.crypto.Wrapper;
     30 import org.bouncycastle.jce.provider.BouncyCastleProvider;
     31 
     32 public abstract class BaseCipherSpi
     33     extends CipherSpi
     34 {
     35     //
     36     // specs we can handle.
     37     //
     38     private Class[]                 availableSpecs =
     39                                     {
     40                                         IvParameterSpec.class,
     41                                         PBEParameterSpec.class,
     42                                         // BEGIN android-removed
     43                                         // RC2ParameterSpec.class,
     44                                         // RC5ParameterSpec.class
     45                                         // END android-removed
     46                                     };
     47 
     48 
     49     protected AlgorithmParameters     engineParams = null;
     50 
     51     protected Wrapper                 wrapEngine = null;
     52 
     53     private int                       ivSize;
     54     private byte[]                    iv;
     55 
     56     protected BaseCipherSpi()
     57     {
     58     }
     59 
     60     protected int engineGetBlockSize()
     61     {
     62         return 0;
     63     }
     64 
     65     protected byte[] engineGetIV()
     66     {
     67         return null;
     68     }
     69 
     70     protected int engineGetKeySize(
     71         Key     key)
     72     {
     73         return key.getEncoded().length;
     74     }
     75 
     76     protected int engineGetOutputSize(
     77         int     inputLen)
     78     {
     79         return -1;
     80     }
     81 
     82     protected AlgorithmParameters engineGetParameters()
     83     {
     84         return null;
     85     }
     86 
     87     protected void engineSetMode(
     88         String  mode)
     89         throws NoSuchAlgorithmException
     90     {
     91         throw new NoSuchAlgorithmException("can't support mode " + mode);
     92     }
     93 
     94     protected void engineSetPadding(
     95         String  padding)
     96     throws NoSuchPaddingException
     97     {
     98         throw new NoSuchPaddingException("Padding " + padding + " unknown.");
     99     }
    100 
    101     protected byte[] engineWrap(
    102         Key     key)
    103     throws IllegalBlockSizeException, InvalidKeyException
    104     {
    105         byte[] encoded = key.getEncoded();
    106         if (encoded == null)
    107         {
    108             throw new InvalidKeyException("Cannot wrap key, null encoding.");
    109         }
    110 
    111         try
    112         {
    113             if (wrapEngine == null)
    114             {
    115                 return engineDoFinal(encoded, 0, encoded.length);
    116             }
    117             else
    118             {
    119                 return wrapEngine.wrap(encoded, 0, encoded.length);
    120             }
    121         }
    122         catch (BadPaddingException e)
    123         {
    124             throw new IllegalBlockSizeException(e.getMessage());
    125         }
    126     }
    127 
    128     protected Key engineUnwrap(
    129         byte[]  wrappedKey,
    130         String  wrappedKeyAlgorithm,
    131         int     wrappedKeyType)
    132     throws InvalidKeyException
    133     {
    134         byte[] encoded;
    135         try
    136         {
    137             if (wrapEngine == null)
    138             {
    139                 encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
    140             }
    141             else
    142             {
    143                 encoded = wrapEngine.unwrap(wrappedKey, 0, wrappedKey.length);
    144             }
    145         }
    146         catch (InvalidCipherTextException e)
    147         {
    148             throw new InvalidKeyException(e.getMessage());
    149         }
    150         catch (BadPaddingException e)
    151         {
    152             throw new InvalidKeyException(e.getMessage());
    153         }
    154         catch (IllegalBlockSizeException e2)
    155         {
    156             throw new InvalidKeyException(e2.getMessage());
    157         }
    158 
    159         if (wrappedKeyType == Cipher.SECRET_KEY)
    160         {
    161             return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
    162         }
    163         else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY)
    164         {
    165             /*
    166                  * The caller doesn't know the algorithm as it is part of
    167                  * the encrypted data.
    168                  */
    169             try
    170             {
    171                 PrivateKeyInfo       in = PrivateKeyInfo.getInstance(encoded);
    172 
    173                 PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in);
    174 
    175                 if (privKey != null)
    176                 {
    177                     return privKey;
    178                 }
    179                 else
    180                 {
    181                     throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported");
    182                 }
    183             }
    184             catch (Exception e)
    185             {
    186                 throw new InvalidKeyException("Invalid key encoding.");
    187             }
    188         }
    189         else
    190         {
    191             try
    192             {
    193                 KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
    194 
    195                 if (wrappedKeyType == Cipher.PUBLIC_KEY)
    196                 {
    197                     return kf.generatePublic(new X509EncodedKeySpec(encoded));
    198                 }
    199                 else if (wrappedKeyType == Cipher.PRIVATE_KEY)
    200                 {
    201                     return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
    202                 }
    203             }
    204             catch (NoSuchProviderException e)
    205             {
    206                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
    207             }
    208             catch (NoSuchAlgorithmException e)
    209             {
    210                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
    211             }
    212             catch (InvalidKeySpecException e2)
    213             {
    214                 throw new InvalidKeyException("Unknown key type " + e2.getMessage());
    215             }
    216 
    217             throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
    218         }
    219     }
    220 }
    221