1 package org.bouncycastle.asn1.isismtt.ocsp;
2 
3 import java.io.IOException;
4 
5 import org.bouncycastle.asn1.ASN1Choice;
6 import org.bouncycastle.asn1.ASN1Object;
7 import org.bouncycastle.asn1.ASN1OctetString;
8 import org.bouncycastle.asn1.ASN1Primitive;
9 import org.bouncycastle.asn1.ASN1Sequence;
10 import org.bouncycastle.asn1.ASN1TaggedObject;
11 import org.bouncycastle.asn1.DEROctetString;
12 import org.bouncycastle.asn1.DERTaggedObject;
13 import org.bouncycastle.asn1.x509.Certificate;
14 import org.bouncycastle.util.Arrays;
15 
16 /**
17  * ISIS-MTT-Optional: The certificate requested by the client by inserting the
18  * RetrieveIfAllowed extension in the request, will be returned in this
19  * extension.
20  * <p>
21  * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
22  * when the certificate owner gives his explicit permission. Accordingly, there
23  * may be �nondownloadable� certificates, about which the responder must provide
24  * status information, but MUST NOT include them in the response. Clients may
25  * get therefore the following three kind of answers on a single request
26  * including the RetrieveIfAllowed extension:
27  * <ul>
28  * <li> a) the responder supports the extension and is allowed to publish the
29  * certificate: RequestedCertificate returned including the requested
30  * certificate
31  * <li>b) the responder supports the extension but is NOT allowed to publish
32  * the certificate: RequestedCertificate returned including an empty OCTET
33  * STRING
34  * <li>c) the responder does not support the extension: RequestedCertificate is
35  * not included in the response
36  * </ul>
37  * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
38  * any of the OCTET STRING options is used, it MUST contain the DER encoding of
39  * the requested certificate.
40  * <pre>
41  *            RequestedCertificate ::= CHOICE {
42  *              Certificate Certificate,
43  *              publicKeyCertificate [0] EXPLICIT OCTET STRING,
44  *              attributeCertificate [1] EXPLICIT OCTET STRING
45  *            }
46  * </pre>
47  */
48 public class RequestedCertificate
49     extends ASN1Object
50     implements ASN1Choice
51 {
52     public static final int certificate = -1;
53     public static final int publicKeyCertificate = 0;
54     public static final int attributeCertificate = 1;
55 
56     private Certificate cert;
57     private byte[] publicKeyCert;
58     private byte[] attributeCert;
59 
getInstance(Object obj)60     public static RequestedCertificate getInstance(Object obj)
61     {
62         if (obj == null || obj instanceof RequestedCertificate)
63         {
64             return (RequestedCertificate)obj;
65         }
66 
67         if (obj instanceof ASN1Sequence)
68         {
69             return new RequestedCertificate(Certificate.getInstance(obj));
70         }
71         if (obj instanceof ASN1TaggedObject)
72         {
73             return new RequestedCertificate((ASN1TaggedObject)obj);
74         }
75 
76         throw new IllegalArgumentException("illegal object in getInstance: "
77             + obj.getClass().getName());
78     }
79 
getInstance(ASN1TaggedObject obj, boolean explicit)80     public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit)
81     {
82         if (!explicit)
83         {
84             throw new IllegalArgumentException("choice item must be explicitly tagged");
85         }
86 
87         return getInstance(obj.getObject());
88     }
89 
RequestedCertificate(ASN1TaggedObject tagged)90     private RequestedCertificate(ASN1TaggedObject tagged)
91     {
92         if (tagged.getTagNo() == publicKeyCertificate)
93         {
94             publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets();
95         }
96         else if (tagged.getTagNo() == attributeCertificate)
97         {
98             attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets();
99         }
100         else
101         {
102             throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
103         }
104     }
105 
106     /**
107      * Constructor from a given details.
108      * <p>
109      * Only one parameter can be given. All other must be <code>null</code>.
110      *
111      * @param certificate          Given as Certificate
112      */
RequestedCertificate(Certificate certificate)113     public RequestedCertificate(Certificate certificate)
114     {
115         this.cert = certificate;
116     }
117 
RequestedCertificate(int type, byte[] certificateOctets)118     public RequestedCertificate(int type, byte[] certificateOctets)
119     {
120         this(new DERTaggedObject(type, new DEROctetString(certificateOctets)));
121     }
122 
getType()123     public int getType()
124     {
125         if (cert != null)
126         {
127             return certificate;
128         }
129         if (publicKeyCert != null)
130         {
131             return publicKeyCertificate;
132         }
133         return attributeCertificate;
134     }
135 
getCertificateBytes()136     public byte[] getCertificateBytes()
137     {
138         if (cert != null)
139         {
140             try
141             {
142                 return cert.getEncoded();
143             }
144             catch (IOException e)
145             {
146                 throw new IllegalStateException("can't decode certificate: " + e);
147             }
148         }
149         if (publicKeyCert != null)
150         {
151             return Arrays.clone(publicKeyCert);
152         }
153         return Arrays.clone(attributeCert);
154     }
155 
156     /**
157      * Produce an object suitable for an ASN1OutputStream.
158      * <p>
159      * Returns:
160      * <pre>
161      *            RequestedCertificate ::= CHOICE {
162      *              Certificate Certificate,
163      *              publicKeyCertificate [0] EXPLICIT OCTET STRING,
164      *              attributeCertificate [1] EXPLICIT OCTET STRING
165      *            }
166      * </pre>
167      *
168      * @return a DERObject
169      */
toASN1Primitive()170     public ASN1Primitive toASN1Primitive()
171     {
172         if (publicKeyCert != null)
173         {
174             return new DERTaggedObject(0, new DEROctetString(publicKeyCert));
175         }
176         if (attributeCert != null)
177         {
178             return new DERTaggedObject(1, new DEROctetString(attributeCert));
179         }
180         return cert.toASN1Primitive();
181     }
182 }
183