1 package org.bouncycastle.asn1.cms; 2 3 import java.util.Enumeration; 4 5 import org.bouncycastle.asn1.ASN1EncodableVector; 6 import org.bouncycastle.asn1.ASN1Integer; 7 import org.bouncycastle.asn1.ASN1Object; 8 import org.bouncycastle.asn1.ASN1OctetString; 9 import org.bouncycastle.asn1.ASN1Primitive; 10 import org.bouncycastle.asn1.ASN1Sequence; 11 import org.bouncycastle.asn1.ASN1Set; 12 import org.bouncycastle.asn1.ASN1TaggedObject; 13 import org.bouncycastle.asn1.BERSequence; 14 import org.bouncycastle.asn1.DERTaggedObject; 15 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 16 17 /** 18 * <a href="https://tools.ietf.org/html/rfc5652#section-9.1">RFC 5652</a> section 9.1: 19 * The AuthenticatedData carries AuthAttributes and other data 20 * which define what really is being signed. 21 * <pre> 22 * AuthenticatedData ::= SEQUENCE { 23 * version CMSVersion, 24 * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, 25 * recipientInfos RecipientInfos, 26 * macAlgorithm MessageAuthenticationCodeAlgorithm, 27 * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, 28 * encapContentInfo EncapsulatedContentInfo, 29 * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL, 30 * mac MessageAuthenticationCode, 31 * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL } 32 * 33 * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute 34 * 35 * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute 36 * 37 * MessageAuthenticationCode ::= OCTET STRING 38 * </pre> 39 */ 40 public class AuthenticatedData 41 extends ASN1Object 42 { 43 private ASN1Integer version; 44 private OriginatorInfo originatorInfo; 45 private ASN1Set recipientInfos; 46 private AlgorithmIdentifier macAlgorithm; 47 private AlgorithmIdentifier digestAlgorithm; 48 private ContentInfo encapsulatedContentInfo; 49 private ASN1Set authAttrs; 50 private ASN1OctetString mac; 51 private ASN1Set unauthAttrs; 52 AuthenticatedData( OriginatorInfo originatorInfo, ASN1Set recipientInfos, AlgorithmIdentifier macAlgorithm, AlgorithmIdentifier digestAlgorithm, ContentInfo encapsulatedContent, ASN1Set authAttrs, ASN1OctetString mac, ASN1Set unauthAttrs)53 public AuthenticatedData( 54 OriginatorInfo originatorInfo, 55 ASN1Set recipientInfos, 56 AlgorithmIdentifier macAlgorithm, 57 AlgorithmIdentifier digestAlgorithm, 58 ContentInfo encapsulatedContent, 59 ASN1Set authAttrs, 60 ASN1OctetString mac, 61 ASN1Set unauthAttrs) 62 { 63 if (digestAlgorithm != null || authAttrs != null) 64 { 65 if (digestAlgorithm == null || authAttrs == null) 66 { 67 throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together"); 68 } 69 } 70 71 version = new ASN1Integer(calculateVersion(originatorInfo)); 72 73 this.originatorInfo = originatorInfo; 74 this.macAlgorithm = macAlgorithm; 75 this.digestAlgorithm = digestAlgorithm; 76 this.recipientInfos = recipientInfos; 77 this.encapsulatedContentInfo = encapsulatedContent; 78 this.authAttrs = authAttrs; 79 this.mac = mac; 80 this.unauthAttrs = unauthAttrs; 81 } 82 AuthenticatedData( ASN1Sequence seq)83 private AuthenticatedData( 84 ASN1Sequence seq) 85 { 86 int index = 0; 87 88 version = (ASN1Integer)seq.getObjectAt(index++); 89 90 Object tmp = seq.getObjectAt(index++); 91 92 if (tmp instanceof ASN1TaggedObject) 93 { 94 originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false); 95 tmp = seq.getObjectAt(index++); 96 } 97 98 recipientInfos = ASN1Set.getInstance(tmp); 99 macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++)); 100 101 tmp = seq.getObjectAt(index++); 102 103 if (tmp instanceof ASN1TaggedObject) 104 { 105 digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false); 106 tmp = seq.getObjectAt(index++); 107 } 108 109 encapsulatedContentInfo = ContentInfo.getInstance(tmp); 110 111 tmp = seq.getObjectAt(index++); 112 113 if (tmp instanceof ASN1TaggedObject) 114 { 115 authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false); 116 tmp = seq.getObjectAt(index++); 117 } 118 119 mac = ASN1OctetString.getInstance(tmp); 120 121 if (seq.size() > index) 122 { 123 unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false); 124 } 125 } 126 127 /** 128 * Return an AuthenticatedData object from a tagged object. 129 * 130 * @param obj the tagged object holding the object we want. 131 * @param explicit true if the object is meant to be explicitly 132 * tagged false otherwise. 133 * @return a reference that can be assigned to AuthenticatedData (may be null) 134 * @throws IllegalArgumentException if the object held by the 135 * tagged object cannot be converted. 136 */ getInstance( ASN1TaggedObject obj, boolean explicit)137 public static AuthenticatedData getInstance( 138 ASN1TaggedObject obj, 139 boolean explicit) 140 { 141 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 142 } 143 144 /** 145 * Return an AuthenticatedData object from the given object. 146 * <p> 147 * Accepted inputs: 148 * <ul> 149 * <li> null → null 150 * <li> {@link AuthenticatedData} object 151 * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with AuthenticatedData structure inside 152 * </ul> 153 * 154 * @param obj the object we want converted. 155 * @return a reference that can be assigned to AuthenticatedData (may be null) 156 * @throws IllegalArgumentException if the object cannot be converted. 157 */ getInstance( Object obj)158 public static AuthenticatedData getInstance( 159 Object obj) 160 { 161 if (obj instanceof AuthenticatedData) 162 { 163 return (AuthenticatedData)obj; 164 } 165 else if (obj != null) 166 { 167 return new AuthenticatedData(ASN1Sequence.getInstance(obj)); 168 } 169 170 return null; 171 } 172 getVersion()173 public ASN1Integer getVersion() 174 { 175 return version; 176 } 177 getOriginatorInfo()178 public OriginatorInfo getOriginatorInfo() 179 { 180 return originatorInfo; 181 } 182 getRecipientInfos()183 public ASN1Set getRecipientInfos() 184 { 185 return recipientInfos; 186 } 187 getMacAlgorithm()188 public AlgorithmIdentifier getMacAlgorithm() 189 { 190 return macAlgorithm; 191 } 192 getDigestAlgorithm()193 public AlgorithmIdentifier getDigestAlgorithm() 194 { 195 return digestAlgorithm; 196 } 197 getEncapsulatedContentInfo()198 public ContentInfo getEncapsulatedContentInfo() 199 { 200 return encapsulatedContentInfo; 201 } 202 getAuthAttrs()203 public ASN1Set getAuthAttrs() 204 { 205 return authAttrs; 206 } 207 getMac()208 public ASN1OctetString getMac() 209 { 210 return mac; 211 } 212 getUnauthAttrs()213 public ASN1Set getUnauthAttrs() 214 { 215 return unauthAttrs; 216 } 217 218 /** 219 * Produce an object suitable for an ASN1OutputStream. 220 */ toASN1Primitive()221 public ASN1Primitive toASN1Primitive() 222 { 223 ASN1EncodableVector v = new ASN1EncodableVector(9); 224 225 v.add(version); 226 227 if (originatorInfo != null) 228 { 229 v.add(new DERTaggedObject(false, 0, originatorInfo)); 230 } 231 232 v.add(recipientInfos); 233 v.add(macAlgorithm); 234 235 if (digestAlgorithm != null) 236 { 237 v.add(new DERTaggedObject(false, 1, digestAlgorithm)); 238 } 239 240 v.add(encapsulatedContentInfo); 241 242 if (authAttrs != null) 243 { 244 v.add(new DERTaggedObject(false, 2, authAttrs)); 245 } 246 247 v.add(mac); 248 249 if (unauthAttrs != null) 250 { 251 v.add(new DERTaggedObject(false, 3, unauthAttrs)); 252 } 253 254 return new BERSequence(v); 255 } 256 calculateVersion(OriginatorInfo origInfo)257 public static int calculateVersion(OriginatorInfo origInfo) 258 { 259 if (origInfo == null) 260 { 261 return 0; 262 } 263 else 264 { 265 int ver = 0; 266 267 for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();) 268 { 269 Object obj = e.nextElement(); 270 271 if (obj instanceof ASN1TaggedObject) 272 { 273 ASN1TaggedObject tag = (ASN1TaggedObject)obj; 274 275 if (tag.getTagNo() == 2) 276 { 277 ver = 1; 278 } 279 else if (tag.getTagNo() == 3) 280 { 281 ver = 3; 282 break; 283 } 284 } 285 } 286 287 if (origInfo.getCRLs() != null) 288 { 289 for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();) 290 { 291 Object obj = e.nextElement(); 292 293 if (obj instanceof ASN1TaggedObject) 294 { 295 ASN1TaggedObject tag = (ASN1TaggedObject)obj; 296 297 if (tag.getTagNo() == 1) 298 { 299 ver = 3; 300 break; 301 } 302 } 303 } 304 } 305 306 return ver; 307 } 308 } 309 } 310