001package org.apache.commons.ssl.org.bouncycastle.asn1.isismtt.ocsp;
002
003import java.io.IOException;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Choice;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
012import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
013import org.apache.commons.ssl.org.bouncycastle.asn1.x509.Certificate;
014
015/**
016 * ISIS-MTT-Optional: The certificate requested by the client by inserting the
017 * RetrieveIfAllowed extension in the request, will be returned in this
018 * extension.
019 * <p>
020 * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
021 * when the certificate owner gives his explicit permission. Accordingly, there
022 * may be �nondownloadable� certificates, about which the responder must provide
023 * status information, but MUST NOT include them in the response. Clients may
024 * get therefore the following three kind of answers on a single request
025 * including the RetrieveIfAllowed extension:
026 * <ul>
027 * <li> a) the responder supports the extension and is allowed to publish the
028 * certificate: RequestedCertificate returned including the requested
029 * certificate
030 * <li>b) the responder supports the extension but is NOT allowed to publish
031 * the certificate: RequestedCertificate returned including an empty OCTET
032 * STRING
033 * <li>c) the responder does not support the extension: RequestedCertificate is
034 * not included in the response
035 * </ul>
036 * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
037 * any of the OCTET STRING options is used, it MUST contain the DER encoding of
038 * the requested certificate.
039 * <pre>
040 *            RequestedCertificate ::= CHOICE {
041 *              Certificate Certificate,
042 *              publicKeyCertificate [0] EXPLICIT OCTET STRING,
043 *              attributeCertificate [1] EXPLICIT OCTET STRING
044 *            }
045 * </pre>
046 */
047public class RequestedCertificate
048    extends ASN1Object
049    implements ASN1Choice
050{
051    public static final int certificate = -1;
052    public static final int publicKeyCertificate = 0;
053    public static final int attributeCertificate = 1;
054
055    private Certificate cert;
056    private byte[] publicKeyCert;
057    private byte[] attributeCert;
058
059    public static RequestedCertificate getInstance(Object obj)
060    {
061        if (obj == null || obj instanceof RequestedCertificate)
062        {
063            return (RequestedCertificate)obj;
064        }
065
066        if (obj instanceof ASN1Sequence)
067        {
068            return new RequestedCertificate(Certificate.getInstance(obj));
069        }
070        if (obj instanceof ASN1TaggedObject)
071        {
072            return new RequestedCertificate((ASN1TaggedObject)obj);
073        }
074
075        throw new IllegalArgumentException("illegal object in getInstance: "
076            + obj.getClass().getName());
077    }
078
079    public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit)
080    {
081        if (!explicit)
082        {
083            throw new IllegalArgumentException("choice item must be explicitly tagged");
084        }
085
086        return getInstance(obj.getObject());
087    }
088
089    private RequestedCertificate(ASN1TaggedObject tagged)
090    {
091        if (tagged.getTagNo() == publicKeyCertificate)
092        {
093            publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets();
094        }
095        else if (tagged.getTagNo() == attributeCertificate)
096        {
097            attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets();
098        }
099        else
100        {
101            throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
102        }
103    }
104
105    /**
106     * Constructor from a given details.
107     * <p>
108     * Only one parameter can be given. All other must be <code>null</code>.
109     *
110     * @param certificate          Given as Certificate
111     */
112    public RequestedCertificate(Certificate certificate)
113    {
114        this.cert = certificate;
115    }
116
117    public RequestedCertificate(int type, byte[] certificateOctets)
118    {
119        this(new DERTaggedObject(type, new DEROctetString(certificateOctets)));
120    }
121
122    public int getType()
123    {
124        if (cert != null)
125        {
126            return certificate;
127        }
128        if (publicKeyCert != null)
129        {
130            return publicKeyCertificate;
131        }
132        return attributeCertificate;
133    }
134
135    public byte[] getCertificateBytes()
136    {
137        if (cert != null)
138        {
139            try
140            {
141                return cert.getEncoded();
142            }
143            catch (IOException e)
144            {
145                throw new IllegalStateException("can't decode certificate: " + e);
146            }
147        }
148        if (publicKeyCert != null)
149        {
150            return publicKeyCert;
151        }
152        return attributeCert;
153    }
154    
155    /**
156     * Produce an object suitable for an ASN1OutputStream.
157     * <p>
158     * Returns:
159     * <pre>
160     *            RequestedCertificate ::= CHOICE {
161     *              Certificate Certificate,
162     *              publicKeyCertificate [0] EXPLICIT OCTET STRING,
163     *              attributeCertificate [1] EXPLICIT OCTET STRING
164     *            }
165     * </pre>
166     *
167     * @return a DERObject
168     */
169    public ASN1Primitive toASN1Primitive()
170    {
171        if (publicKeyCert != null)
172        {
173            return new DERTaggedObject(0, new DEROctetString(publicKeyCert));
174        }
175        if (attributeCert != null)
176        {
177            return new DERTaggedObject(1, new DEROctetString(attributeCert));
178        }
179        return cert.toASN1Primitive();
180    }
181}