1package org.bouncycastle.asn1.pkcs;
2
3import org.bouncycastle.asn1.ASN1EncodableVector;
4import org.bouncycastle.asn1.ASN1Integer;
5import org.bouncycastle.asn1.ASN1Object;
6import org.bouncycastle.asn1.ASN1Primitive;
7import org.bouncycastle.asn1.ASN1Sequence;
8import org.bouncycastle.asn1.ASN1Set;
9import org.bouncycastle.asn1.DERSequence;
10import org.bouncycastle.asn1.DERTaggedObject;
11import org.bouncycastle.asn1.x500.X500Name;
12import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
13import org.bouncycastle.asn1.x509.X509Name;
14
15/**
16 * PKCS10 CertificationRequestInfo object.
17 * <pre>
18 *  CertificationRequestInfo ::= SEQUENCE {
19 *   version             INTEGER { v1(0) } (v1,...),
20 *   subject             Name,
21 *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
22 *   attributes          [0] Attributes{{ CRIAttributes }}
23 *  }
24 *
25 *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
26 *
27 *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
28 *    type    ATTRIBUTE.&amp;id({IOSet}),
29 *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
30 *  }
31 * </pre>
32 */
33public class CertificationRequestInfo
34    extends ASN1Object
35{
36    ASN1Integer              version = new ASN1Integer(0);
37    X500Name                subject;
38    SubjectPublicKeyInfo    subjectPKInfo;
39    ASN1Set                 attributes = null;
40
41    public static CertificationRequestInfo getInstance(
42        Object  obj)
43    {
44        if (obj instanceof CertificationRequestInfo)
45        {
46            return (CertificationRequestInfo)obj;
47        }
48        else if (obj != null)
49        {
50            return new CertificationRequestInfo(ASN1Sequence.getInstance(obj));
51        }
52
53        return null;
54    }
55
56    /**
57     * Basic constructor.
58     * <p>
59     * Note: Early on a lot of CAs would only accept messages with attributes missing. As the ASN.1 def shows
60     * the attributes field is not optional so should always at least contain an empty set. If a fully compliant
61     * request is required, pass in an empty set, the class will otherwise interpret a null as it should
62     * encode the request with the field missing.
63     * </p>
64     *
65     * @param subject subject to be associated with the public key
66     * @param pkInfo public key to be associated with subject
67     * @param attributes any attributes to be associated with the request.
68     */
69    public CertificationRequestInfo(
70        X500Name                subject,
71        SubjectPublicKeyInfo    pkInfo,
72        ASN1Set                 attributes)
73    {
74        if ((subject == null) || (pkInfo == null))
75        {
76            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
77        }
78
79        this.subject = subject;
80        this.subjectPKInfo = pkInfo;
81        this.attributes = attributes;
82    }
83
84    /**
85     * @deprecated use X500Name method.
86     */
87    public CertificationRequestInfo(
88        X509Name                subject,
89        SubjectPublicKeyInfo    pkInfo,
90        ASN1Set                 attributes)
91    {
92        if ((subject == null) || (pkInfo == null))
93        {
94            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
95        }
96
97        this.subject = X500Name.getInstance(subject.toASN1Primitive());
98        this.subjectPKInfo = pkInfo;
99        this.attributes = attributes;
100    }
101
102    /**
103     * @deprecated use getInstance().
104     */
105    public CertificationRequestInfo(
106        ASN1Sequence  seq)
107    {
108        version = (ASN1Integer)seq.getObjectAt(0);
109
110        subject = X500Name.getInstance(seq.getObjectAt(1));
111        subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
112
113        //
114        // some CertificationRequestInfo objects seem to treat this field
115        // as optional.
116        //
117        if (seq.size() > 3)
118        {
119            DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
120            attributes = ASN1Set.getInstance(tagobj, false);
121        }
122
123        if ((subject == null) || (version == null) || (subjectPKInfo == null))
124        {
125            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
126        }
127    }
128
129    public ASN1Integer getVersion()
130    {
131        return version;
132    }
133
134    public X500Name getSubject()
135    {
136        return subject;
137    }
138
139    public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
140    {
141        return subjectPKInfo;
142    }
143
144    public ASN1Set getAttributes()
145    {
146        return attributes;
147    }
148
149    public ASN1Primitive toASN1Primitive()
150    {
151        ASN1EncodableVector  v = new ASN1EncodableVector();
152
153        v.add(version);
154        v.add(subject);
155        v.add(subjectPKInfo);
156
157        if (attributes != null)
158        {
159            v.add(new DERTaggedObject(false, 0, attributes));
160        }
161
162        return new DERSequence(v);
163    }
164}
165