001package org.apache.commons.ssl.org.bouncycastle.asn1.cms; 002 003import java.util.Enumeration; 004 005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Set; 012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 013import org.apache.commons.ssl.org.bouncycastle.asn1.BERSequence; 014import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 015import org.apache.commons.ssl.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 016 017/** 018 * <a href="http://tools.ietf.org/html/rfc5652#section-9.1">RFC 5652</a> section 9.1: 019 * The AuthenticatedData carries AuthAttributes and other data 020 * which define what really is being signed. 021 * <p> 022 * <pre> 023 * AuthenticatedData ::= SEQUENCE { 024 * version CMSVersion, 025 * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, 026 * recipientInfos RecipientInfos, 027 * macAlgorithm MessageAuthenticationCodeAlgorithm, 028 * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, 029 * encapContentInfo EncapsulatedContentInfo, 030 * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL, 031 * mac MessageAuthenticationCode, 032 * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL } 033 * 034 * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute 035 * 036 * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute 037 * 038 * MessageAuthenticationCode ::= OCTET STRING 039 * </pre> 040 */ 041public class AuthenticatedData 042 extends ASN1Object 043{ 044 private ASN1Integer version; 045 private OriginatorInfo originatorInfo; 046 private ASN1Set recipientInfos; 047 private AlgorithmIdentifier macAlgorithm; 048 private AlgorithmIdentifier digestAlgorithm; 049 private ContentInfo encapsulatedContentInfo; 050 private ASN1Set authAttrs; 051 private ASN1OctetString mac; 052 private ASN1Set unauthAttrs; 053 054 public AuthenticatedData( 055 OriginatorInfo originatorInfo, 056 ASN1Set recipientInfos, 057 AlgorithmIdentifier macAlgorithm, 058 AlgorithmIdentifier digestAlgorithm, 059 ContentInfo encapsulatedContent, 060 ASN1Set authAttrs, 061 ASN1OctetString mac, 062 ASN1Set unauthAttrs) 063 { 064 if (digestAlgorithm != null || authAttrs != null) 065 { 066 if (digestAlgorithm == null || authAttrs == null) 067 { 068 throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together"); 069 } 070 } 071 072 version = new ASN1Integer(calculateVersion(originatorInfo)); 073 074 this.originatorInfo = originatorInfo; 075 this.macAlgorithm = macAlgorithm; 076 this.digestAlgorithm = digestAlgorithm; 077 this.recipientInfos = recipientInfos; 078 this.encapsulatedContentInfo = encapsulatedContent; 079 this.authAttrs = authAttrs; 080 this.mac = mac; 081 this.unauthAttrs = unauthAttrs; 082 } 083 084 /** 085 * @deprecated use getInstance() 086 */ 087 public AuthenticatedData( 088 ASN1Sequence seq) 089 { 090 int index = 0; 091 092 version = (ASN1Integer)seq.getObjectAt(index++); 093 094 Object tmp = seq.getObjectAt(index++); 095 096 if (tmp instanceof ASN1TaggedObject) 097 { 098 originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); 099 tmp = seq.getObjectAt(index++); 100 } 101 102 recipientInfos = ASN1Set.getInstance(tmp); 103 macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++)); 104 105 tmp = seq.getObjectAt(index++); 106 107 if (tmp instanceof ASN1TaggedObject) 108 { 109 digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false); 110 tmp = seq.getObjectAt(index++); 111 } 112 113 encapsulatedContentInfo = ContentInfo.getInstance(tmp); 114 115 tmp = seq.getObjectAt(index++); 116 117 if (tmp instanceof ASN1TaggedObject) 118 { 119 authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false); 120 tmp = seq.getObjectAt(index++); 121 } 122 123 mac = ASN1OctetString.getInstance(tmp); 124 125 if (seq.size() > index) 126 { 127 unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false); 128 } 129 } 130 131 /** 132 * Return an AuthenticatedData object from a tagged object. 133 * 134 * @param obj the tagged object holding the object we want. 135 * @param explicit true if the object is meant to be explicitly 136 * tagged false otherwise. 137 * @throws IllegalArgumentException if the object held by the 138 * tagged object cannot be converted. 139 */ 140 public static AuthenticatedData getInstance( 141 ASN1TaggedObject obj, 142 boolean explicit) 143 { 144 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 145 } 146 147 /** 148 * Return an AuthenticatedData object from the given object. 149 * <p> 150 * Accepted inputs: 151 * <ul> 152 * <li> null → null 153 * <li> {@link AuthenticatedData} object 154 * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with AuthenticatedData structure inside 155 * </ul> 156 * 157 * @param obj the object we want converted. 158 * @throws IllegalArgumentException if the object cannot be converted. 159 */ 160 public static AuthenticatedData getInstance( 161 Object obj) 162 { 163 if (obj == null || obj instanceof AuthenticatedData) 164 { 165 return (AuthenticatedData)obj; 166 } 167 168 if (obj instanceof ASN1Sequence) 169 { 170 return new AuthenticatedData((ASN1Sequence)obj); 171 } 172 173 throw new IllegalArgumentException("Invalid AuthenticatedData: " + obj.getClass().getName()); 174 } 175 176 public ASN1Integer getVersion() 177 { 178 return version; 179 } 180 181 public OriginatorInfo getOriginatorInfo() 182 { 183 return originatorInfo; 184 } 185 186 public ASN1Set getRecipientInfos() 187 { 188 return recipientInfos; 189 } 190 191 public AlgorithmIdentifier getMacAlgorithm() 192 { 193 return macAlgorithm; 194 } 195 196 public AlgorithmIdentifier getDigestAlgorithm() 197 { 198 return digestAlgorithm; 199 } 200 201 public ContentInfo getEncapsulatedContentInfo() 202 { 203 return encapsulatedContentInfo; 204 } 205 206 public ASN1Set getAuthAttrs() 207 { 208 return authAttrs; 209 } 210 211 public ASN1OctetString getMac() 212 { 213 return mac; 214 } 215 216 public ASN1Set getUnauthAttrs() 217 { 218 return unauthAttrs; 219 } 220 221 /** 222 * Produce an object suitable for an ASN1OutputStream. 223 */ 224 public ASN1Primitive toASN1Primitive() 225 { 226 ASN1EncodableVector v = new ASN1EncodableVector(); 227 228 v.add(version); 229 230 if (originatorInfo != null) 231 { 232 v.add(new DERTaggedObject(false, 0, originatorInfo)); 233 } 234 235 v.add(recipientInfos); 236 v.add(macAlgorithm); 237 238 if (digestAlgorithm != null) 239 { 240 v.add(new DERTaggedObject(false, 1, digestAlgorithm)); 241 } 242 243 v.add(encapsulatedContentInfo); 244 245 if (authAttrs != null) 246 { 247 v.add(new DERTaggedObject(false, 2, authAttrs)); 248 } 249 250 v.add(mac); 251 252 if (unauthAttrs != null) 253 { 254 v.add(new DERTaggedObject(false, 3, unauthAttrs)); 255 } 256 257 return new BERSequence(v); 258 } 259 260 public static int calculateVersion(OriginatorInfo origInfo) 261 { 262 if (origInfo == null) 263 { 264 return 0; 265 } 266 else 267 { 268 int ver = 0; 269 270 for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();) 271 { 272 Object obj = e.nextElement(); 273 274 if (obj instanceof ASN1TaggedObject) 275 { 276 ASN1TaggedObject tag = (ASN1TaggedObject)obj; 277 278 if (tag.getTagNo() == 2) 279 { 280 ver = 1; 281 } 282 else if (tag.getTagNo() == 3) 283 { 284 ver = 3; 285 break; 286 } 287 } 288 } 289 290 if (origInfo.getCRLs() != null) 291 { 292 for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();) 293 { 294 Object obj = e.nextElement(); 295 296 if (obj instanceof ASN1TaggedObject) 297 { 298 ASN1TaggedObject tag = (ASN1TaggedObject)obj; 299 300 if (tag.getTagNo() == 1) 301 { 302 ver = 3; 303 break; 304 } 305 } 306 } 307 } 308 309 return ver; 310 } 311 } 312}