1package org.bouncycastle.cms; 2 3import java.io.IOException; 4import java.io.InputStream; 5import java.io.OutputStream; 6import java.util.ArrayList; 7import java.util.Collection; 8import java.util.Iterator; 9import java.util.List; 10 11import org.bouncycastle.asn1.ASN1Encodable; 12import org.bouncycastle.asn1.ASN1EncodableVector; 13import org.bouncycastle.asn1.ASN1InputStream; 14import org.bouncycastle.asn1.ASN1ObjectIdentifier; 15import org.bouncycastle.asn1.ASN1Set; 16import org.bouncycastle.asn1.BEROctetStringGenerator; 17import org.bouncycastle.asn1.BERSet; 18import org.bouncycastle.asn1.DERSet; 19import org.bouncycastle.asn1.DERTaggedObject; 20import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; 21import org.bouncycastle.asn1.cms.ContentInfo; 22// BEGIN android-removed 23// import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat; 24// import org.bouncycastle.asn1.ocsp.OCSPResponse; 25// import org.bouncycastle.asn1.ocsp.OCSPResponseStatus; 26// END android-removed 27import org.bouncycastle.cert.X509AttributeCertificateHolder; 28import org.bouncycastle.cert.X509CRLHolder; 29import org.bouncycastle.cert.X509CertificateHolder; 30import org.bouncycastle.operator.DigestCalculator; 31import org.bouncycastle.util.Store; 32import org.bouncycastle.util.io.Streams; 33import org.bouncycastle.util.io.TeeInputStream; 34import org.bouncycastle.util.io.TeeOutputStream; 35 36class CMSUtils 37{ 38 static ContentInfo readContentInfo( 39 byte[] input) 40 throws CMSException 41 { 42 // enforce limit checking as from a byte array 43 return readContentInfo(new ASN1InputStream(input)); 44 } 45 46 static ContentInfo readContentInfo( 47 InputStream input) 48 throws CMSException 49 { 50 // enforce some limit checking 51 return readContentInfo(new ASN1InputStream(input)); 52 } 53 54 static List getCertificatesFromStore(Store certStore) 55 throws CMSException 56 { 57 List certs = new ArrayList(); 58 59 try 60 { 61 for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();) 62 { 63 X509CertificateHolder c = (X509CertificateHolder)it.next(); 64 65 certs.add(c.toASN1Structure()); 66 } 67 68 return certs; 69 } 70 catch (ClassCastException e) 71 { 72 throw new CMSException("error processing certs", e); 73 } 74 } 75 76 static List getAttributeCertificatesFromStore(Store attrStore) 77 throws CMSException 78 { 79 List certs = new ArrayList(); 80 81 try 82 { 83 for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();) 84 { 85 X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next(); 86 87 certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure())); 88 } 89 90 return certs; 91 } 92 catch (ClassCastException e) 93 { 94 throw new CMSException("error processing certs", e); 95 } 96 } 97 98 99 static List getCRLsFromStore(Store crlStore) 100 throws CMSException 101 { 102 List certs = new ArrayList(); 103 104 try 105 { 106 for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();) 107 { 108 X509CRLHolder c = (X509CRLHolder)it.next(); 109 110 certs.add(c.toASN1Structure()); 111 } 112 113 return certs; 114 } 115 catch (ClassCastException e) 116 { 117 throw new CMSException("error processing certs", e); 118 } 119 } 120 121 // BEGIN android-removed 122 // static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos) 123 // { 124 // List others = new ArrayList(); 125 // 126 // for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();) 127 // { 128 // ASN1Encodable info = (ASN1Encodable)it.next(); 129 // 130 // if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat)) 131 // { 132 // OCSPResponse resp = OCSPResponse.getInstance(info); 133 // 134 // if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL) 135 // { 136 // throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData"); 137 // } 138 // } 139 // 140 // others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info))); 141 // } 142 // 143 // return others; 144 // } 145 // END android-removed 146 147 static ASN1Set createBerSetFromList(List derObjects) 148 { 149 ASN1EncodableVector v = new ASN1EncodableVector(); 150 151 for (Iterator it = derObjects.iterator(); it.hasNext();) 152 { 153 v.add((ASN1Encodable)it.next()); 154 } 155 156 return new BERSet(v); 157 } 158 159 static ASN1Set createDerSetFromList(List derObjects) 160 { 161 ASN1EncodableVector v = new ASN1EncodableVector(); 162 163 for (Iterator it = derObjects.iterator(); it.hasNext();) 164 { 165 v.add((ASN1Encodable)it.next()); 166 } 167 168 return new DERSet(v); 169 } 170 171 static OutputStream createBEROctetOutputStream(OutputStream s, 172 int tagNo, boolean isExplicit, int bufferSize) throws IOException 173 { 174 BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit); 175 176 if (bufferSize != 0) 177 { 178 return octGen.getOctetOutputStream(new byte[bufferSize]); 179 } 180 181 return octGen.getOctetOutputStream(); 182 } 183 184 private static ContentInfo readContentInfo( 185 ASN1InputStream in) 186 throws CMSException 187 { 188 try 189 { 190 return ContentInfo.getInstance(in.readObject()); 191 } 192 catch (IOException e) 193 { 194 throw new CMSException("IOException reading content.", e); 195 } 196 catch (ClassCastException e) 197 { 198 throw new CMSException("Malformed content.", e); 199 } 200 catch (IllegalArgumentException e) 201 { 202 throw new CMSException("Malformed content.", e); 203 } 204 } 205 206 public static byte[] streamToByteArray( 207 InputStream in) 208 throws IOException 209 { 210 return Streams.readAll(in); 211 } 212 213 public static byte[] streamToByteArray( 214 InputStream in, 215 int limit) 216 throws IOException 217 { 218 return Streams.readAllLimited(in, limit); 219 } 220 221 static InputStream attachDigestsToInputStream(Collection digests, InputStream s) 222 { 223 InputStream result = s; 224 Iterator it = digests.iterator(); 225 while (it.hasNext()) 226 { 227 DigestCalculator digest = (DigestCalculator)it.next(); 228 result = new TeeInputStream(result, digest.getOutputStream()); 229 } 230 return result; 231 } 232 233 static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s) 234 { 235 OutputStream result = s; 236 Iterator it = signers.iterator(); 237 while (it.hasNext()) 238 { 239 SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next(); 240 result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream()); 241 } 242 return result; 243 } 244 245 static OutputStream getSafeOutputStream(OutputStream s) 246 { 247 return s == null ? new NullOutputStream() : s; 248 } 249 250 static OutputStream getSafeTeeOutputStream(OutputStream s1, 251 OutputStream s2) 252 { 253 return s1 == null ? getSafeOutputStream(s2) 254 : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream( 255 s1, s2); 256 } 257} 258