Home | History | Annotate | Download | only in cms
      1 package org.bouncycastle.cms;
      2 
      3 import java.io.IOException;
      4 import java.io.InputStream;
      5 import java.io.OutputStream;
      6 import java.util.ArrayList;
      7 import java.util.Collection;
      8 import java.util.Iterator;
      9 import java.util.List;
     10 
     11 import org.bouncycastle.asn1.ASN1Encodable;
     12 import org.bouncycastle.asn1.ASN1EncodableVector;
     13 import org.bouncycastle.asn1.ASN1InputStream;
     14 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
     15 import org.bouncycastle.asn1.ASN1Set;
     16 import org.bouncycastle.asn1.ASN1TaggedObject;
     17 import org.bouncycastle.asn1.BEROctetStringGenerator;
     18 import org.bouncycastle.asn1.BERSet;
     19 import org.bouncycastle.asn1.DERSet;
     20 import org.bouncycastle.asn1.DERTaggedObject;
     21 import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
     22 import org.bouncycastle.asn1.cms.ContentInfo;
     23 // BEGIN android-removed
     24 // import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
     25 // import org.bouncycastle.asn1.ocsp.OCSPResponse;
     26 // import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
     27 // END android-removed
     28 import org.bouncycastle.cert.X509AttributeCertificateHolder;
     29 import org.bouncycastle.cert.X509CRLHolder;
     30 import org.bouncycastle.cert.X509CertificateHolder;
     31 import org.bouncycastle.operator.DigestCalculator;
     32 import org.bouncycastle.util.Store;
     33 import org.bouncycastle.util.Strings;
     34 import org.bouncycastle.util.io.Streams;
     35 import org.bouncycastle.util.io.TeeInputStream;
     36 import org.bouncycastle.util.io.TeeOutputStream;
     37 
     38 class CMSUtils
     39 {
     40     static ContentInfo readContentInfo(
     41         byte[] input)
     42         throws CMSException
     43     {
     44         // enforce limit checking as from a byte array
     45         return readContentInfo(new ASN1InputStream(input));
     46     }
     47 
     48     static ContentInfo readContentInfo(
     49         InputStream input)
     50         throws CMSException
     51     {
     52         // enforce some limit checking
     53         return readContentInfo(new ASN1InputStream(input));
     54     }
     55 
     56     static List getCertificatesFromStore(Store certStore)
     57         throws CMSException
     58     {
     59         List certs = new ArrayList();
     60 
     61         try
     62         {
     63             for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();)
     64             {
     65                 X509CertificateHolder c = (X509CertificateHolder)it.next();
     66 
     67                 certs.add(c.toASN1Structure());
     68             }
     69 
     70             return certs;
     71         }
     72         catch (ClassCastException e)
     73         {
     74             throw new CMSException("error processing certs", e);
     75         }
     76     }
     77 
     78     static List getAttributeCertificatesFromStore(Store attrStore)
     79         throws CMSException
     80     {
     81         List certs = new ArrayList();
     82 
     83         try
     84         {
     85             for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();)
     86             {
     87                 X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next();
     88 
     89                 certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
     90             }
     91 
     92             return certs;
     93         }
     94         catch (ClassCastException e)
     95         {
     96             throw new CMSException("error processing certs", e);
     97         }
     98     }
     99 
    100 
    101     static List getCRLsFromStore(Store crlStore)
    102         throws CMSException
    103     {
    104         List crls = new ArrayList();
    105 
    106         try
    107         {
    108             for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();)
    109             {
    110                 Object rev = it.next();
    111 
    112                 if (rev instanceof X509CRLHolder)
    113                 {
    114                     X509CRLHolder c = (X509CRLHolder)rev;
    115 
    116                     crls.add(c.toASN1Structure());
    117                 }
    118                 // BEGIN android-removed
    119                 // else if (rev instanceof OtherRevocationInfoFormat)
    120                 // {
    121                 //     OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
    122                 //
    123                 //     validateInfoFormat(infoFormat);
    124                 //
    125                 //     crls.add(new DERTaggedObject(false, 1, infoFormat));
    126                 // }
    127                 // END android-removed
    128                 else if (rev instanceof ASN1TaggedObject)
    129                 {
    130                     crls.add(rev);
    131                 }
    132             }
    133 
    134             return crls;
    135         }
    136         catch (ClassCastException e)
    137         {
    138             throw new CMSException("error processing certs", e);
    139         }
    140     }
    141 
    142     // BEGIN android-removed
    143     // private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
    144     // {
    145     //     if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
    146     //     {
    147     //         OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
    148     //
    149     //         if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
    150     //         {
    151     //             throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
    152     //         }
    153     //     }
    154     // }
    155     //
    156     // static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
    157     // {
    158     //     List others = new ArrayList();
    159     //
    160     //     for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
    161     //     {
    162     //         ASN1Encodable info = (ASN1Encodable)it.next();
    163     //         OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
    164     //         validateInfoFormat(infoFormat);
    165     //
    166     //         others.add(new DERTaggedObject(false, 1, infoFormat));
    167     //     }
    168     //
    169     //     return others;
    170     // }
    171     // END android-removed
    172 
    173     static ASN1Set createBerSetFromList(List derObjects)
    174     {
    175         ASN1EncodableVector v = new ASN1EncodableVector();
    176 
    177         for (Iterator it = derObjects.iterator(); it.hasNext();)
    178         {
    179             v.add((ASN1Encodable)it.next());
    180         }
    181 
    182         return new BERSet(v);
    183     }
    184 
    185     static ASN1Set createDerSetFromList(List derObjects)
    186     {
    187         ASN1EncodableVector v = new ASN1EncodableVector();
    188 
    189         for (Iterator it = derObjects.iterator(); it.hasNext();)
    190         {
    191             v.add((ASN1Encodable)it.next());
    192         }
    193 
    194         return new DERSet(v);
    195     }
    196 
    197     static OutputStream createBEROctetOutputStream(OutputStream s,
    198             int tagNo, boolean isExplicit, int bufferSize) throws IOException
    199     {
    200         BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
    201 
    202         if (bufferSize != 0)
    203         {
    204             return octGen.getOctetOutputStream(new byte[bufferSize]);
    205         }
    206 
    207         return octGen.getOctetOutputStream();
    208     }
    209 
    210     private static ContentInfo readContentInfo(
    211         ASN1InputStream in)
    212         throws CMSException
    213     {
    214         try
    215         {
    216             return ContentInfo.getInstance(in.readObject());
    217         }
    218         catch (IOException e)
    219         {
    220             throw new CMSException("IOException reading content.", e);
    221         }
    222         catch (ClassCastException e)
    223         {
    224             throw new CMSException("Malformed content.", e);
    225         }
    226         catch (IllegalArgumentException e)
    227         {
    228             throw new CMSException("Malformed content.", e);
    229         }
    230     }
    231 
    232     static byte[] getPasswordBytes(int scheme, char[] password)
    233     {
    234         if (scheme == PasswordRecipient.PKCS5_SCHEME2)
    235         {
    236             return PKCS5PasswordToBytes(password);
    237         }
    238 
    239         return PKCS5PasswordToUTF8Bytes(password);
    240     }
    241 
    242     /**
    243      * converts a password to a byte array according to the scheme in
    244      * PKCS5 (ascii, no padding)
    245      *
    246      * @param password a character array representing the password.
    247      * @return a byte array representing the password.
    248      */
    249     private static byte[] PKCS5PasswordToBytes(
    250         char[]  password)
    251     {
    252         if (password != null)
    253         {
    254             byte[]  bytes = new byte[password.length];
    255 
    256             for (int i = 0; i != bytes.length; i++)
    257             {
    258                 bytes[i] = (byte)password[i];
    259             }
    260 
    261             return bytes;
    262         }
    263         else
    264         {
    265             return new byte[0];
    266         }
    267     }
    268 
    269     /**
    270      * converts a password to a byte array according to the scheme in
    271      * PKCS5 (UTF-8, no padding)
    272      *
    273      * @param password a character array representing the password.
    274      * @return a byte array representing the password.
    275      */
    276     private static byte[] PKCS5PasswordToUTF8Bytes(
    277         char[]  password)
    278     {
    279         if (password != null)
    280         {
    281             return Strings.toUTF8ByteArray(password);
    282         }
    283         else
    284         {
    285             return new byte[0];
    286         }
    287     }
    288 
    289     public static byte[] streamToByteArray(
    290         InputStream in)
    291         throws IOException
    292     {
    293         return Streams.readAll(in);
    294     }
    295 
    296     public static byte[] streamToByteArray(
    297         InputStream in,
    298         int         limit)
    299         throws IOException
    300     {
    301         return Streams.readAllLimited(in, limit);
    302     }
    303 
    304     static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
    305     {
    306         InputStream result = s;
    307         Iterator it = digests.iterator();
    308         while (it.hasNext())
    309         {
    310             DigestCalculator digest = (DigestCalculator)it.next();
    311             result = new TeeInputStream(result, digest.getOutputStream());
    312         }
    313         return result;
    314     }
    315 
    316     static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s)
    317     {
    318         OutputStream result = s;
    319         Iterator it = signers.iterator();
    320         while (it.hasNext())
    321         {
    322             SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
    323             result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream());
    324         }
    325         return result;
    326     }
    327 
    328     static OutputStream getSafeOutputStream(OutputStream s)
    329     {
    330         return s == null ? new NullOutputStream() : s;
    331     }
    332 
    333     static OutputStream getSafeTeeOutputStream(OutputStream s1,
    334             OutputStream s2)
    335     {
    336         return s1 == null ? getSafeOutputStream(s2)
    337                 : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(
    338                         s1, s2);
    339     }
    340 }
    341