001package org.apache.commons.ssl.org.bouncycastle.asn1.cms;
002
003import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
004import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Set;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
011import org.apache.commons.ssl.org.bouncycastle.asn1.BERSequence;
012import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
013
014/**
015 * <a href="http://tools.ietf.org/html/rfc5083">RFC 5083</a>:
016 *
017 * CMS AuthEnveloped Data object.
018 * <p>
019 * ASN.1:
020 * <pre>
021 * id-ct-authEnvelopedData OBJECT IDENTIFIER ::= { iso(1)
022 *       member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)
023 *       smime(16) ct(1) 23 }
024 *
025 * AuthEnvelopedData ::= SEQUENCE {
026 *       version CMSVersion,
027 *       originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
028 *       recipientInfos RecipientInfos,
029 *       authEncryptedContentInfo EncryptedContentInfo,
030 *       authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
031 *       mac MessageAuthenticationCode,
032 *       unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
033 * </pre>
034 */
035public class AuthEnvelopedData
036    extends ASN1Object
037{
038    private ASN1Integer version;
039    private OriginatorInfo originatorInfo;
040    private ASN1Set recipientInfos;
041    private EncryptedContentInfo authEncryptedContentInfo;
042    private ASN1Set authAttrs;
043    private ASN1OctetString mac;
044    private ASN1Set unauthAttrs;
045
046    public AuthEnvelopedData(
047        OriginatorInfo originatorInfo,
048        ASN1Set recipientInfos,
049        EncryptedContentInfo authEncryptedContentInfo,
050        ASN1Set authAttrs,
051        ASN1OctetString mac,
052        ASN1Set unauthAttrs)
053    {
054        // "It MUST be set to 0."
055        this.version = new ASN1Integer(0);
056
057        this.originatorInfo = originatorInfo;
058
059        // TODO
060        // "There MUST be at least one element in the collection."
061        this.recipientInfos = recipientInfos;
062
063        this.authEncryptedContentInfo = authEncryptedContentInfo;
064
065        // TODO
066        // "The authAttrs MUST be present if the content type carried in
067        // EncryptedContentInfo is not id-data."
068        this.authAttrs = authAttrs;
069
070        this.mac = mac;
071
072        this.unauthAttrs = unauthAttrs;
073    }
074
075    /**
076     * Constructs AuthEnvelopedData by parsing supplied ASN1Sequence
077     * <p>
078     * @param seq An ASN1Sequence with AuthEnvelopedData
079     * @deprecated use getInstance().
080     */
081    public AuthEnvelopedData(
082        ASN1Sequence seq)
083    {
084        int index = 0;
085
086        // TODO
087        // "It MUST be set to 0."
088        ASN1Primitive tmp = seq.getObjectAt(index++).toASN1Primitive();
089        version = (ASN1Integer)tmp;
090
091        tmp = seq.getObjectAt(index++).toASN1Primitive();
092        if (tmp instanceof ASN1TaggedObject)
093        {
094            originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
095            tmp = seq.getObjectAt(index++).toASN1Primitive();
096        }
097
098        // TODO
099        // "There MUST be at least one element in the collection."
100        recipientInfos = ASN1Set.getInstance(tmp);
101
102        tmp = seq.getObjectAt(index++).toASN1Primitive();
103        authEncryptedContentInfo = EncryptedContentInfo.getInstance(tmp);
104
105        tmp = seq.getObjectAt(index++).toASN1Primitive();
106        if (tmp instanceof ASN1TaggedObject)
107        {
108            authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
109            tmp = seq.getObjectAt(index++).toASN1Primitive();
110        }
111        else
112        {
113            // TODO
114            // "The authAttrs MUST be present if the content type carried in
115            // EncryptedContentInfo is not id-data."
116        }
117
118        mac = ASN1OctetString.getInstance(tmp);
119
120        if (seq.size() > index)
121        {
122            tmp = seq.getObjectAt(index++).toASN1Primitive();
123            unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
124        }
125    }
126
127    /**
128     * Return an AuthEnvelopedData object from a tagged object.
129     * <p>
130     * Accepted inputs:
131     * <ul>
132     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats
133     * </ul>
134     *
135
136     * @param obj      the tagged object holding the object we want.
137     * @param explicit true if the object is meant to be explicitly
138     *                 tagged false otherwise.
139     * @throws IllegalArgumentException if the object held by the
140     *                                  tagged object cannot be converted.
141     */
142    public static AuthEnvelopedData getInstance(
143        ASN1TaggedObject obj,
144        boolean explicit)
145    {
146        return getInstance(ASN1Sequence.getInstance(obj, explicit));
147    }
148
149    /**
150     * Return an AuthEnvelopedData object from the given object.
151     * <p>
152     * Accepted inputs:
153     * <ul>
154     * <li> null &rarr; null
155     * <li> {@link AuthEnvelopedData} object
156     * <li> {@link ASN1Sequence org.bouncycastle.asn1.ASN1Sequence} input formats with AuthEnvelopedData structure inside
157     * </ul>
158     *
159     * @param obj The object we want converted.
160     * @throws IllegalArgumentException if the object cannot be converted, or was null.
161     */
162    public static AuthEnvelopedData getInstance(
163        Object obj)
164    {
165        if (obj == null || obj instanceof AuthEnvelopedData)
166        {
167            return (AuthEnvelopedData)obj;
168        }
169
170        if (obj instanceof ASN1Sequence)
171        {
172            return new AuthEnvelopedData((ASN1Sequence)obj);
173        }
174
175        throw new IllegalArgumentException("Invalid AuthEnvelopedData: " + obj.getClass().getName());
176    }
177
178    public ASN1Integer getVersion()
179    {
180        return version;
181    }
182
183    public OriginatorInfo getOriginatorInfo()
184    {
185        return originatorInfo;
186    }
187
188    public ASN1Set getRecipientInfos()
189    {
190        return recipientInfos;
191    }
192
193    public EncryptedContentInfo getAuthEncryptedContentInfo()
194    {
195        return authEncryptedContentInfo;
196    }
197
198    public ASN1Set getAuthAttrs()
199    {
200        return authAttrs;
201    }
202
203    public ASN1OctetString getMac()
204    {
205        return mac;
206    }
207
208    public ASN1Set getUnauthAttrs()
209    {
210        return unauthAttrs;
211    }
212
213    /**
214     * Produce an object suitable for an ASN1OutputStream.
215     */
216    public ASN1Primitive toASN1Primitive()
217    {
218        ASN1EncodableVector v = new ASN1EncodableVector();
219
220        v.add(version);
221
222        if (originatorInfo != null)
223        {
224            v.add(new DERTaggedObject(false, 0, originatorInfo));
225        }
226
227        v.add(recipientInfos);
228        v.add(authEncryptedContentInfo);
229
230        // "authAttrs optionally contains the authenticated attributes."
231        if (authAttrs != null)
232        {
233            // "AuthAttributes MUST be DER encoded, even if the rest of the
234            // AuthEnvelopedData structure is BER encoded."
235            v.add(new DERTaggedObject(false, 1, authAttrs));
236        }
237
238        v.add(mac);
239
240        // "unauthAttrs optionally contains the unauthenticated attributes."
241        if (unauthAttrs != null)
242        {
243            v.add(new DERTaggedObject(false, 2, unauthAttrs));
244        }
245
246        return new BERSequence(v);
247    }
248}