1package org.bouncycastle.cert.ocsp;
2
3import java.io.IOException;
4import java.io.OutputStream;
5import java.util.Date;
6import java.util.List;
7import java.util.Set;
8
9import org.bouncycastle.asn1.ASN1Encoding;
10import org.bouncycastle.asn1.ASN1ObjectIdentifier;
11import org.bouncycastle.asn1.ASN1Sequence;
12import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
13import org.bouncycastle.asn1.ocsp.ResponseData;
14import org.bouncycastle.asn1.ocsp.SingleResponse;
15import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
16import org.bouncycastle.asn1.x509.Certificate;
17import org.bouncycastle.asn1.x509.Extension;
18import org.bouncycastle.asn1.x509.Extensions;
19import org.bouncycastle.cert.X509CertificateHolder;
20import org.bouncycastle.operator.ContentVerifier;
21import org.bouncycastle.operator.ContentVerifierProvider;
22import org.bouncycastle.util.Encodable;
23
24/**
25 * <pre>
26 * BasicOCSPResponse       ::= SEQUENCE {
27 *    tbsResponseData      ResponseData,
28 *    signatureAlgorithm   AlgorithmIdentifier,
29 *    signature            BIT STRING,
30 *    certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
31 * </pre>
32 */
33public class BasicOCSPResp
34    implements Encodable
35{
36    private BasicOCSPResponse   resp;
37    private ResponseData        data;
38    private Extensions extensions;
39
40    public BasicOCSPResp(
41        BasicOCSPResponse   resp)
42    {
43        this.resp = resp;
44        this.data = resp.getTbsResponseData();
45        this.extensions = Extensions.getInstance(resp.getTbsResponseData().getResponseExtensions());
46    }
47
48    /**
49     * Return the DER encoding of the tbsResponseData field.
50     * @return DER encoding of tbsResponseData
51     */
52    public byte[] getTBSResponseData()
53    {
54        try
55        {
56            return resp.getTbsResponseData().getEncoded(ASN1Encoding.DER);
57        }
58        catch (IOException e)
59        {
60            return null;
61        }
62    }
63
64    /**
65     * Return the algorithm identifier describing the signature used in the response.
66     *
67     * @return an AlgorithmIdentifier
68     */
69    public AlgorithmIdentifier getSignatureAlgorithmID()
70    {
71        return resp.getSignatureAlgorithm();
72    }
73
74    public int getVersion()
75    {
76        return data.getVersion().getValue().intValue() + 1;
77    }
78
79    public RespID getResponderId()
80    {
81        return new RespID(data.getResponderID());
82    }
83
84    public Date getProducedAt()
85    {
86        return OCSPUtils.extractDate(data.getProducedAt());
87    }
88
89    public SingleResp[] getResponses()
90    {
91        ASN1Sequence    s = data.getResponses();
92        SingleResp[]    rs = new SingleResp[s.size()];
93
94        for (int i = 0; i != rs.length; i++)
95        {
96            rs[i] = new SingleResp(SingleResponse.getInstance(s.getObjectAt(i)));
97        }
98
99        return rs;
100    }
101
102    public boolean hasExtensions()
103   {
104       return extensions != null;
105   }
106
107   public Extension getExtension(ASN1ObjectIdentifier oid)
108   {
109       if (extensions != null)
110       {
111           return extensions.getExtension(oid);
112       }
113
114       return null;
115   }
116
117   public List getExtensionOIDs()
118   {
119       return OCSPUtils.getExtensionOIDs(extensions);
120   }
121
122   public Set getCriticalExtensionOIDs()
123   {
124       return OCSPUtils.getCriticalExtensionOIDs(extensions);
125   }
126
127   public Set getNonCriticalExtensionOIDs()
128   {
129       return OCSPUtils.getNonCriticalExtensionOIDs(extensions);
130   }
131
132
133    public ASN1ObjectIdentifier getSignatureAlgOID()
134    {
135        return resp.getSignatureAlgorithm().getAlgorithm();
136    }
137
138    public byte[] getSignature()
139    {
140        return resp.getSignature().getOctets();
141    }
142
143    public X509CertificateHolder[] getCerts()
144    {
145        //
146        // load the certificates if we have any
147        //
148        if (resp.getCerts() != null)
149        {
150            ASN1Sequence s = resp.getCerts();
151
152            if (s != null)
153            {
154                X509CertificateHolder[] certs = new X509CertificateHolder[s.size()];
155
156                for (int i = 0; i != certs.length; i++)
157                {
158                    certs[i] = new X509CertificateHolder(Certificate.getInstance(s.getObjectAt(i)));
159                }
160
161                return certs;
162            }
163
164            return OCSPUtils.EMPTY_CERTS;
165        }
166        else
167        {
168            return OCSPUtils.EMPTY_CERTS;
169        }
170    }
171
172    /**
173     * verify the signature against the tbsResponseData object we contain.
174     */
175    public boolean isSignatureValid(
176        ContentVerifierProvider verifierProvider)
177        throws OCSPException
178    {
179        try
180        {
181            ContentVerifier verifier = verifierProvider.get(resp.getSignatureAlgorithm());
182            OutputStream vOut = verifier.getOutputStream();
183
184            vOut.write(resp.getTbsResponseData().getEncoded(ASN1Encoding.DER));
185            vOut.close();
186
187            return verifier.verify(this.getSignature());
188        }
189        catch (Exception e)
190        {
191            throw new OCSPException("exception processing sig: " + e, e);
192        }
193    }
194
195    /**
196     * return the ASN.1 encoded representation of this object.
197     */
198    public byte[] getEncoded()
199        throws IOException
200    {
201        return resp.getEncoded();
202    }
203
204    public boolean equals(Object o)
205    {
206        if (o == this)
207        {
208            return true;
209        }
210
211        if (!(o instanceof BasicOCSPResp))
212        {
213            return false;
214        }
215
216        BasicOCSPResp r = (BasicOCSPResp)o;
217
218        return resp.equals(r.resp);
219    }
220
221    public int hashCode()
222    {
223        return resp.hashCode();
224    }
225}
226