• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Set;
12 
13 import org.bouncycastle.asn1.ASN1Encodable;
14 import org.bouncycastle.asn1.ASN1EncodableVector;
15 import org.bouncycastle.asn1.ASN1InputStream;
16 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
17 import org.bouncycastle.asn1.ASN1Set;
18 import org.bouncycastle.asn1.ASN1TaggedObject;
19 import org.bouncycastle.asn1.BEROctetStringGenerator;
20 import org.bouncycastle.asn1.BERSet;
21 import org.bouncycastle.asn1.DERNull;
22 import org.bouncycastle.asn1.DERSet;
23 import org.bouncycastle.asn1.DERTaggedObject;
24 import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
25 import org.bouncycastle.asn1.cms.ContentInfo;
26 // Android-removed: Unsupported algorithms
27 // import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
28 // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
29 // import org.bouncycastle.asn1.ocsp.OCSPResponse;
30 // import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
31 // import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
32 // import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
33 // import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
34 // import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
35 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
36 // import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
37 import org.bouncycastle.cert.X509AttributeCertificateHolder;
38 import org.bouncycastle.cert.X509CRLHolder;
39 import org.bouncycastle.cert.X509CertificateHolder;
40 import org.bouncycastle.operator.DigestCalculator;
41 import org.bouncycastle.util.Store;
42 import org.bouncycastle.util.Strings;
43 import org.bouncycastle.util.io.Streams;
44 import org.bouncycastle.util.io.TeeInputStream;
45 import org.bouncycastle.util.io.TeeOutputStream;
46 
47 class CMSUtils
48 {
49     private static final Set<String> des = new HashSet<String>();
50     private static final Set mqvAlgs = new HashSet();
51     private static final Set ecAlgs = new HashSet();
52     private static final Set gostAlgs = new HashSet();
53 
54     static
55     {
56         des.add("DES");
57         des.add("DESEDE");
58         // BEGIN Android-removed: Unsupported algorithms
59         /*
60         des.add(OIWObjectIdentifiers.desCBC.getId());
61         des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
62         des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
63         des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId());
64 
65         mqvAlgs.add(X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme);
66         mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme);
67         mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme);
68         mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme);
69         mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme);
70 
71         ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme);
72         ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme);
73         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme);
74         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme);
75         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme);
76         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme);
77         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme);
78         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme);
79         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme);
80         ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme);
81 
82         gostAlgs.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_ESDH);
83         gostAlgs.add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_256);
84         gostAlgs.add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_512);
85         */
86         // END Android-removed: Unsupported algorithms
87     }
88 
isMQV(ASN1ObjectIdentifier algorithm)89     static boolean isMQV(ASN1ObjectIdentifier algorithm)
90     {
91         return mqvAlgs.contains(algorithm);
92     }
93 
isEC(ASN1ObjectIdentifier algorithm)94     static boolean isEC(ASN1ObjectIdentifier algorithm)
95     {
96         return ecAlgs.contains(algorithm);
97     }
98 
isGOST(ASN1ObjectIdentifier algorithm)99     static boolean isGOST(ASN1ObjectIdentifier algorithm)
100     {
101         return gostAlgs.contains(algorithm);
102     }
103 
104     // BEGIN Android-removed: Unsupported algorithms
105     /*
106     static boolean isRFC2631(ASN1ObjectIdentifier algorithm)
107     {
108         return algorithm.equals(PKCSObjectIdentifiers.id_alg_ESDH) || algorithm.equals(PKCSObjectIdentifiers.id_alg_SSDH);
109     }
110     */
111     // END Android-removed: Unsupported algorithms
112 
isDES(String algorithmID)113     static boolean isDES(String algorithmID)
114     {
115         String name = Strings.toUpperCase(algorithmID);
116 
117         return des.contains(name);
118     }
119 
isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2)120     static boolean isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2)
121     {
122         if (algId1 == null || algId2 == null)
123         {
124             return false;
125         }
126 
127         if (!algId1.getAlgorithm().equals(algId2.getAlgorithm()))
128         {
129             return false;
130         }
131 
132         ASN1Encodable params1 = algId1.getParameters();
133         ASN1Encodable params2 = algId2.getParameters();
134         if (params1 != null)
135         {
136             return params1.equals(params2) || (params1.equals(DERNull.INSTANCE) && params2 == null);
137         }
138 
139         return params2 == null || params2.equals(DERNull.INSTANCE);
140     }
141 
readContentInfo( byte[] input)142     static ContentInfo readContentInfo(
143         byte[] input)
144         throws CMSException
145     {
146         // enforce limit checking as from a byte array
147         return readContentInfo(new ASN1InputStream(input));
148     }
149 
readContentInfo( InputStream input)150     static ContentInfo readContentInfo(
151         InputStream input)
152         throws CMSException
153     {
154         // enforce some limit checking
155         return readContentInfo(new ASN1InputStream(input));
156     }
157 
getCertificatesFromStore(Store certStore)158     static List getCertificatesFromStore(Store certStore)
159         throws CMSException
160     {
161         List certs = new ArrayList();
162 
163         try
164         {
165             for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext(); )
166             {
167                 X509CertificateHolder c = (X509CertificateHolder)it.next();
168 
169                 certs.add(c.toASN1Structure());
170             }
171 
172             return certs;
173         }
174         catch (ClassCastException e)
175         {
176             throw new CMSException("error processing certs", e);
177         }
178     }
179 
getAttributeCertificatesFromStore(Store attrStore)180     static List getAttributeCertificatesFromStore(Store attrStore)
181         throws CMSException
182     {
183         List certs = new ArrayList();
184 
185         try
186         {
187             for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext(); )
188             {
189                 X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next();
190 
191                 certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
192             }
193 
194             return certs;
195         }
196         catch (ClassCastException e)
197         {
198             throw new CMSException("error processing certs", e);
199         }
200     }
201 
202 
getCRLsFromStore(Store crlStore)203     static List getCRLsFromStore(Store crlStore)
204         throws CMSException
205     {
206         List crls = new ArrayList();
207 
208         try
209         {
210             for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext(); )
211             {
212                 Object rev = it.next();
213 
214                 if (rev instanceof X509CRLHolder)
215                 {
216                     X509CRLHolder c = (X509CRLHolder)rev;
217 
218                     crls.add(c.toASN1Structure());
219                 }
220                 // BEGIN Android-removed: OtherRevocationInfoFormat isn't supported
221                 // else if (rev instanceof OtherRevocationInfoFormat)
222                 // {
223                 //     OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
224                 //
225                 //     validateInfoFormat(infoFormat);
226                 //
227                 //     crls.add(new DERTaggedObject(false, 1, infoFormat));
228                 // }
229                 // END Android-removed: OtherRevocationInfoFormat isn't supported
230                 else if (rev instanceof ASN1TaggedObject)
231                 {
232                     crls.add(rev);
233                 }
234             }
235 
236             return crls;
237         }
238         catch (ClassCastException e)
239         {
240             throw new CMSException("error processing certs", e);
241         }
242     }
243 
244     // BEGIN Android-removed: OtherRevocationInfoFormat isn't supported
245     /*
246     private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
247     {
248         if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
249         {
250             OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
251 
252             if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
253             {
254                 throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
255             }
256         }
257     }
258 
259     static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
260     {
261         List others = new ArrayList();
262 
263         for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext(); )
264         {
265             ASN1Encodable info = (ASN1Encodable)it.next();
266             OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
267 
268             validateInfoFormat(infoFormat);
269 
270             others.add(new DERTaggedObject(false, 1, infoFormat));
271         }
272 
273         return others;
274     }
275     */
276     // END Android-removed: OtherRevocationInfoFormat isn't supported
277 
createBerSetFromList(List derObjects)278     static ASN1Set createBerSetFromList(List derObjects)
279     {
280         ASN1EncodableVector v = new ASN1EncodableVector();
281 
282         for (Iterator it = derObjects.iterator(); it.hasNext(); )
283         {
284             v.add((ASN1Encodable)it.next());
285         }
286 
287         return new BERSet(v);
288     }
289 
createDerSetFromList(List derObjects)290     static ASN1Set createDerSetFromList(List derObjects)
291     {
292         ASN1EncodableVector v = new ASN1EncodableVector();
293 
294         for (Iterator it = derObjects.iterator(); it.hasNext(); )
295         {
296             v.add((ASN1Encodable)it.next());
297         }
298 
299         return new DERSet(v);
300     }
301 
createBEROctetOutputStream(OutputStream s, int tagNo, boolean isExplicit, int bufferSize)302     static OutputStream createBEROctetOutputStream(OutputStream s,
303                                                    int tagNo, boolean isExplicit, int bufferSize)
304         throws IOException
305     {
306         BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
307 
308         if (bufferSize != 0)
309         {
310             return octGen.getOctetOutputStream(new byte[bufferSize]);
311         }
312 
313         return octGen.getOctetOutputStream();
314     }
315 
readContentInfo( ASN1InputStream in)316     private static ContentInfo readContentInfo(
317         ASN1InputStream in)
318         throws CMSException
319     {
320         try
321         {
322             ContentInfo info = ContentInfo.getInstance(in.readObject());
323             if (info == null)
324             {
325                 throw new CMSException("No content found.");
326             }
327 
328             return info;
329         }
330         catch (IOException e)
331         {
332             throw new CMSException("IOException reading content.", e);
333         }
334         catch (ClassCastException e)
335         {
336             throw new CMSException("Malformed content.", e);
337         }
338         catch (IllegalArgumentException e)
339         {
340             throw new CMSException("Malformed content.", e);
341         }
342     }
343 
streamToByteArray( InputStream in)344     public static byte[] streamToByteArray(
345         InputStream in)
346         throws IOException
347     {
348         return Streams.readAll(in);
349     }
350 
streamToByteArray( InputStream in, int limit)351     public static byte[] streamToByteArray(
352         InputStream in,
353         int limit)
354         throws IOException
355     {
356         return Streams.readAllLimited(in, limit);
357     }
358 
attachDigestsToInputStream(Collection digests, InputStream s)359     static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
360     {
361         InputStream result = s;
362         Iterator it = digests.iterator();
363         while (it.hasNext())
364         {
365             DigestCalculator digest = (DigestCalculator)it.next();
366             result = new TeeInputStream(result, digest.getOutputStream());
367         }
368         return result;
369     }
370 
attachSignersToOutputStream(Collection signers, OutputStream s)371     static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s)
372     {
373         OutputStream result = s;
374         Iterator it = signers.iterator();
375         while (it.hasNext())
376         {
377             SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
378             result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream());
379         }
380         return result;
381     }
382 
getSafeOutputStream(OutputStream s)383     static OutputStream getSafeOutputStream(OutputStream s)
384     {
385         return s == null ? new NullOutputStream() : s;
386     }
387 
getSafeTeeOutputStream(OutputStream s1, OutputStream s2)388     static OutputStream getSafeTeeOutputStream(OutputStream s1,
389                                                OutputStream s2)
390     {
391         return s1 == null ? getSafeOutputStream(s2)
392             : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(
393             s1, s2);
394     }
395 }
396