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