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.ASN1TaggedObject;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
012import org.apache.commons.ssl.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
013
014/**
015 * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
016 * Content encryption key delivery mechanisms.
017 * <p>
018 * <pre>
019 * KeyAgreeRecipientInfo ::= SEQUENCE {
020 *     version CMSVersion,  -- always set to 3
021 *     originator [0] EXPLICIT OriginatorIdentifierOrKey,
022 *     ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
023 *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
024 *     recipientEncryptedKeys RecipientEncryptedKeys 
025 * }
026 *
027 * UserKeyingMaterial ::= OCTET STRING
028 * </pre>
029 */
030public class KeyAgreeRecipientInfo
031    extends ASN1Object
032{
033    private ASN1Integer                  version;
034    private OriginatorIdentifierOrKey   originator;
035    private ASN1OctetString             ukm;
036    private AlgorithmIdentifier         keyEncryptionAlgorithm;
037    private ASN1Sequence                recipientEncryptedKeys;
038    
039    public KeyAgreeRecipientInfo(
040        OriginatorIdentifierOrKey   originator,
041        ASN1OctetString             ukm,
042        AlgorithmIdentifier         keyEncryptionAlgorithm,
043        ASN1Sequence                recipientEncryptedKeys)
044    {
045        this.version = new ASN1Integer(3);
046        this.originator = originator;
047        this.ukm = ukm;
048        this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
049        this.recipientEncryptedKeys = recipientEncryptedKeys;
050    }
051
052    /**
053     * @deprecated use getInstance()
054     */
055    public KeyAgreeRecipientInfo(
056        ASN1Sequence seq)
057    {
058        int index = 0;
059        
060        version = (ASN1Integer)seq.getObjectAt(index++);
061        originator = OriginatorIdentifierOrKey.getInstance(
062                            (ASN1TaggedObject)seq.getObjectAt(index++), true);
063
064        if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
065        {
066            ukm = ASN1OctetString.getInstance(
067                            (ASN1TaggedObject)seq.getObjectAt(index++), true);
068        }
069
070        keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
071                                                seq.getObjectAt(index++));
072
073        recipientEncryptedKeys = (ASN1Sequence)seq.getObjectAt(index++);
074    }
075    
076    /**
077     * Return a KeyAgreeRecipientInfo object from a tagged object.
078     *
079     * @param obj the tagged object holding the object we want.
080     * @param explicit true if the object is meant to be explicitly
081     *              tagged false otherwise.
082     * @exception IllegalArgumentException if the object held by the
083     *          tagged object cannot be converted.
084     */
085    public static KeyAgreeRecipientInfo getInstance(
086        ASN1TaggedObject    obj,
087        boolean             explicit)
088    {
089        return getInstance(ASN1Sequence.getInstance(obj, explicit));
090    }
091    
092    /**
093     * Return a KeyAgreeRecipientInfo object from the given object.
094     * <p>
095     * Accepted inputs:
096     * <ul>
097     * <li> null &rarr; null
098     * <li> {@link KeyAgreeRecipientInfo} object
099     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KeyAgreeRecipientInfo structure inside
100     * </ul>
101     *
102     * @param obj the object we want converted.
103     * @exception IllegalArgumentException if the object cannot be converted.
104     */
105    public static KeyAgreeRecipientInfo getInstance(
106        Object obj)
107    {
108        if (obj instanceof KeyAgreeRecipientInfo)
109        {
110            return (KeyAgreeRecipientInfo)obj;
111        }
112        
113        if (obj != null)
114        {
115            return new KeyAgreeRecipientInfo(ASN1Sequence.getInstance(obj));
116        }
117        
118        return null;
119    } 
120
121    public ASN1Integer getVersion()
122    {
123        return version;
124    }
125
126    public OriginatorIdentifierOrKey getOriginator()
127    {
128        return originator;
129    }
130
131    public ASN1OctetString getUserKeyingMaterial()
132    {
133        return ukm;
134    }
135
136    public AlgorithmIdentifier getKeyEncryptionAlgorithm()
137    {
138        return keyEncryptionAlgorithm;
139    }
140
141    public ASN1Sequence getRecipientEncryptedKeys()
142    {
143        return recipientEncryptedKeys;
144    }
145
146    /** 
147     * Produce an object suitable for an ASN1OutputStream.
148     */
149    public ASN1Primitive toASN1Primitive()
150    {
151        ASN1EncodableVector  v = new ASN1EncodableVector();
152
153        v.add(version);
154        v.add(new DERTaggedObject(true, 0, originator));
155        
156        if (ukm != null)
157        {
158            v.add(new DERTaggedObject(true, 1, ukm));
159        }
160        
161        v.add(keyEncryptionAlgorithm);
162        v.add(recipientEncryptedKeys);
163
164        return new DERSequence(v);
165    }
166}