1109998Smarkm/* ocsp_prn.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
4296465Sdelphij * project.
5296465Sdelphij */
6109998Smarkm
7296465Sdelphij/*
8296465Sdelphij * History: This file was originally part of ocsp.c and was transfered to
9296465Sdelphij * Richard Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be
10296465Sdelphij * included in OpenSSL or released as a patch kit.
11296465Sdelphij */
12109998Smarkm
13109998Smarkm/* ====================================================================
14109998Smarkm * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
15109998Smarkm *
16109998Smarkm * Redistribution and use in source and binary forms, with or without
17109998Smarkm * modification, are permitted provided that the following conditions
18109998Smarkm * are met:
19109998Smarkm *
20109998Smarkm * 1. Redistributions of source code must retain the above copyright
21296465Sdelphij *    notice, this list of conditions and the following disclaimer.
22109998Smarkm *
23109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
24109998Smarkm *    notice, this list of conditions and the following disclaimer in
25109998Smarkm *    the documentation and/or other materials provided with the
26109998Smarkm *    distribution.
27109998Smarkm *
28109998Smarkm * 3. All advertising materials mentioning features or use of this
29109998Smarkm *    software must display the following acknowledgment:
30109998Smarkm *    "This product includes software developed by the OpenSSL Project
31109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
32109998Smarkm *
33109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
34109998Smarkm *    endorse or promote products derived from this software without
35109998Smarkm *    prior written permission. For written permission, please contact
36109998Smarkm *    openssl-core@openssl.org.
37109998Smarkm *
38109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
39109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
40109998Smarkm *    permission of the OpenSSL Project.
41109998Smarkm *
42109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
43109998Smarkm *    acknowledgment:
44109998Smarkm *    "This product includes software developed by the OpenSSL Project
45109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
46109998Smarkm *
47109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
48109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
51109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
59109998Smarkm * ====================================================================
60109998Smarkm *
61109998Smarkm * This product includes cryptographic software written by Eric Young
62109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
63109998Smarkm * Hudson (tjh@cryptsoft.com).
64109998Smarkm *
65109998Smarkm */
66109998Smarkm
67109998Smarkm#include <openssl/bio.h>
68109998Smarkm#include <openssl/err.h>
69109998Smarkm#include <openssl/ocsp.h>
70109998Smarkm#include <openssl/pem.h>
71109998Smarkm
72296465Sdelphijstatic int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent)
73296465Sdelphij{
74296465Sdelphij    BIO_printf(bp, "%*sCertificate ID:\n", indent, "");
75296465Sdelphij    indent += 2;
76296465Sdelphij    BIO_printf(bp, "%*sHash Algorithm: ", indent, "");
77296465Sdelphij    i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm);
78296465Sdelphij    BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, "");
79296465Sdelphij    i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING);
80296465Sdelphij    BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, "");
81296465Sdelphij    i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING);
82296465Sdelphij    BIO_printf(bp, "\n%*sSerial Number: ", indent, "");
83296465Sdelphij    i2a_ASN1_INTEGER(bp, a->serialNumber);
84296465Sdelphij    BIO_printf(bp, "\n");
85296465Sdelphij    return 1;
86296465Sdelphij}
87109998Smarkm
88296465Sdelphijtypedef struct {
89296465Sdelphij    long t;
90296465Sdelphij    char *m;
91296465Sdelphij} OCSP_TBLSTR;
92109998Smarkm
93109998Smarkmstatic char *table2string(long s, OCSP_TBLSTR *ts, int len)
94109998Smarkm{
95296465Sdelphij    OCSP_TBLSTR *p;
96296465Sdelphij    for (p = ts; p < ts + len; p++)
97296465Sdelphij        if (p->t == s)
98296465Sdelphij            return p->m;
99296465Sdelphij    return "(UNKNOWN)";
100109998Smarkm}
101109998Smarkm
102109998Smarkmchar *OCSP_response_status_str(long s)
103296465Sdelphij{
104296465Sdelphij    static OCSP_TBLSTR rstat_tbl[] = {
105296465Sdelphij        {OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful"},
106296465Sdelphij        {OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest"},
107296465Sdelphij        {OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror"},
108296465Sdelphij        {OCSP_RESPONSE_STATUS_TRYLATER, "trylater"},
109296465Sdelphij        {OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired"},
110296465Sdelphij        {OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized"}
111296465Sdelphij    };
112296465Sdelphij    return table2string(s, rstat_tbl, 6);
113296465Sdelphij}
114109998Smarkm
115109998Smarkmchar *OCSP_cert_status_str(long s)
116296465Sdelphij{
117296465Sdelphij    static OCSP_TBLSTR cstat_tbl[] = {
118296465Sdelphij        {V_OCSP_CERTSTATUS_GOOD, "good"},
119296465Sdelphij        {V_OCSP_CERTSTATUS_REVOKED, "revoked"},
120296465Sdelphij        {V_OCSP_CERTSTATUS_UNKNOWN, "unknown"}
121296465Sdelphij    };
122296465Sdelphij    return table2string(s, cstat_tbl, 3);
123296465Sdelphij}
124109998Smarkm
125109998Smarkmchar *OCSP_crl_reason_str(long s)
126296465Sdelphij{
127296465Sdelphij    OCSP_TBLSTR reason_tbl[] = {
128296465Sdelphij        {OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified"},
129296465Sdelphij        {OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise"},
130296465Sdelphij        {OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise"},
131296465Sdelphij        {OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged"},
132296465Sdelphij        {OCSP_REVOKED_STATUS_SUPERSEDED, "superseded"},
133296465Sdelphij        {OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation"},
134296465Sdelphij        {OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold"},
135296465Sdelphij        {OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL"}
136296465Sdelphij    };
137296465Sdelphij    return table2string(s, reason_tbl, 8);
138296465Sdelphij}
139109998Smarkm
140296465Sdelphijint OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *o, unsigned long flags)
141296465Sdelphij{
142296465Sdelphij    int i;
143296465Sdelphij    long l;
144296465Sdelphij    OCSP_CERTID *cid = NULL;
145296465Sdelphij    OCSP_ONEREQ *one = NULL;
146296465Sdelphij    OCSP_REQINFO *inf = o->tbsRequest;
147296465Sdelphij    OCSP_SIGNATURE *sig = o->optionalSignature;
148109998Smarkm
149296465Sdelphij    if (BIO_write(bp, "OCSP Request Data:\n", 19) <= 0)
150296465Sdelphij        goto err;
151296465Sdelphij    l = ASN1_INTEGER_get(inf->version);
152296465Sdelphij    if (BIO_printf(bp, "    Version: %lu (0x%lx)", l + 1, l) <= 0)
153296465Sdelphij        goto err;
154296465Sdelphij    if (inf->requestorName != NULL) {
155296465Sdelphij        if (BIO_write(bp, "\n    Requestor Name: ", 21) <= 0)
156296465Sdelphij            goto err;
157296465Sdelphij        GENERAL_NAME_print(bp, inf->requestorName);
158296465Sdelphij    }
159296465Sdelphij    if (BIO_write(bp, "\n    Requestor List:\n", 21) <= 0)
160296465Sdelphij        goto err;
161296465Sdelphij    for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) {
162296465Sdelphij        one = sk_OCSP_ONEREQ_value(inf->requestList, i);
163296465Sdelphij        cid = one->reqCert;
164296465Sdelphij        ocsp_certid_print(bp, cid, 8);
165296465Sdelphij        if (!X509V3_extensions_print(bp,
166296465Sdelphij                                     "Request Single Extensions",
167296465Sdelphij                                     one->singleRequestExtensions, flags, 8))
168296465Sdelphij            goto err;
169296465Sdelphij    }
170296465Sdelphij    if (!X509V3_extensions_print(bp, "Request Extensions",
171296465Sdelphij                                 inf->requestExtensions, flags, 4))
172296465Sdelphij        goto err;
173296465Sdelphij    if (sig) {
174296465Sdelphij        X509_signature_print(bp, sig->signatureAlgorithm, sig->signature);
175296465Sdelphij        for (i = 0; i < sk_X509_num(sig->certs); i++) {
176296465Sdelphij            X509_print(bp, sk_X509_value(sig->certs, i));
177296465Sdelphij            PEM_write_bio_X509(bp, sk_X509_value(sig->certs, i));
178296465Sdelphij        }
179296465Sdelphij    }
180296465Sdelphij    return 1;
181296465Sdelphij err:
182296465Sdelphij    return 0;
183296465Sdelphij}
184109998Smarkm
185296465Sdelphijint OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags)
186296465Sdelphij{
187296465Sdelphij    int i, ret = 0;
188296465Sdelphij    long l;
189296465Sdelphij    OCSP_CERTID *cid = NULL;
190296465Sdelphij    OCSP_BASICRESP *br = NULL;
191296465Sdelphij    OCSP_RESPID *rid = NULL;
192296465Sdelphij    OCSP_RESPDATA *rd = NULL;
193296465Sdelphij    OCSP_CERTSTATUS *cst = NULL;
194296465Sdelphij    OCSP_REVOKEDINFO *rev = NULL;
195296465Sdelphij    OCSP_SINGLERESP *single = NULL;
196296465Sdelphij    OCSP_RESPBYTES *rb = o->responseBytes;
197109998Smarkm
198296465Sdelphij    if (BIO_puts(bp, "OCSP Response Data:\n") <= 0)
199296465Sdelphij        goto err;
200296465Sdelphij    l = ASN1_ENUMERATED_get(o->responseStatus);
201296465Sdelphij    if (BIO_printf(bp, "    OCSP Response Status: %s (0x%lx)\n",
202296465Sdelphij                   OCSP_response_status_str(l), l) <= 0)
203296465Sdelphij        goto err;
204296465Sdelphij    if (rb == NULL)
205296465Sdelphij        return 1;
206296465Sdelphij    if (BIO_puts(bp, "    Response Type: ") <= 0)
207296465Sdelphij        goto err;
208296465Sdelphij    if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0)
209296465Sdelphij        goto err;
210296465Sdelphij    if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
211296465Sdelphij        BIO_puts(bp, " (unknown response type)\n");
212296465Sdelphij        return 1;
213296465Sdelphij    }
214109998Smarkm
215296465Sdelphij    i = ASN1_STRING_length(rb->response);
216296465Sdelphij    if (!(br = OCSP_response_get1_basic(o)))
217296465Sdelphij        goto err;
218296465Sdelphij    rd = br->tbsResponseData;
219296465Sdelphij    l = ASN1_INTEGER_get(rd->version);
220296465Sdelphij    if (BIO_printf(bp, "\n    Version: %lu (0x%lx)\n", l + 1, l) <= 0)
221296465Sdelphij        goto err;
222296465Sdelphij    if (BIO_puts(bp, "    Responder Id: ") <= 0)
223296465Sdelphij        goto err;
224109998Smarkm
225296465Sdelphij    rid = rd->responderId;
226296465Sdelphij    switch (rid->type) {
227296465Sdelphij    case V_OCSP_RESPID_NAME:
228296465Sdelphij        X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE);
229296465Sdelphij        break;
230296465Sdelphij    case V_OCSP_RESPID_KEY:
231296465Sdelphij        i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING);
232296465Sdelphij        break;
233296465Sdelphij    }
234109998Smarkm
235296465Sdelphij    if (BIO_printf(bp, "\n    Produced At: ") <= 0)
236296465Sdelphij        goto err;
237296465Sdelphij    if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt))
238296465Sdelphij        goto err;
239296465Sdelphij    if (BIO_printf(bp, "\n    Responses:\n") <= 0)
240296465Sdelphij        goto err;
241296465Sdelphij    for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) {
242296465Sdelphij        if (!sk_OCSP_SINGLERESP_value(rd->responses, i))
243296465Sdelphij            continue;
244296465Sdelphij        single = sk_OCSP_SINGLERESP_value(rd->responses, i);
245296465Sdelphij        cid = single->certId;
246296465Sdelphij        if (ocsp_certid_print(bp, cid, 4) <= 0)
247296465Sdelphij            goto err;
248296465Sdelphij        cst = single->certStatus;
249296465Sdelphij        if (BIO_printf(bp, "    Cert Status: %s",
250296465Sdelphij                       OCSP_cert_status_str(cst->type)) <= 0)
251296465Sdelphij            goto err;
252296465Sdelphij        if (cst->type == V_OCSP_CERTSTATUS_REVOKED) {
253296465Sdelphij            rev = cst->value.revoked;
254296465Sdelphij            if (BIO_printf(bp, "\n    Revocation Time: ") <= 0)
255296465Sdelphij                goto err;
256296465Sdelphij            if (!ASN1_GENERALIZEDTIME_print(bp, rev->revocationTime))
257296465Sdelphij                goto err;
258296465Sdelphij            if (rev->revocationReason) {
259296465Sdelphij                l = ASN1_ENUMERATED_get(rev->revocationReason);
260296465Sdelphij                if (BIO_printf(bp,
261296465Sdelphij                               "\n    Revocation Reason: %s (0x%lx)",
262296465Sdelphij                               OCSP_crl_reason_str(l), l) <= 0)
263296465Sdelphij                    goto err;
264296465Sdelphij            }
265296465Sdelphij        }
266296465Sdelphij        if (BIO_printf(bp, "\n    This Update: ") <= 0)
267296465Sdelphij            goto err;
268296465Sdelphij        if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate))
269296465Sdelphij            goto err;
270296465Sdelphij        if (single->nextUpdate) {
271296465Sdelphij            if (BIO_printf(bp, "\n    Next Update: ") <= 0)
272296465Sdelphij                goto err;
273296465Sdelphij            if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate))
274296465Sdelphij                goto err;
275296465Sdelphij        }
276296465Sdelphij        if (BIO_write(bp, "\n", 1) <= 0)
277296465Sdelphij            goto err;
278296465Sdelphij        if (!X509V3_extensions_print(bp,
279296465Sdelphij                                     "Response Single Extensions",
280296465Sdelphij                                     single->singleExtensions, flags, 8))
281296465Sdelphij            goto err;
282296465Sdelphij        if (BIO_write(bp, "\n", 1) <= 0)
283296465Sdelphij            goto err;
284296465Sdelphij    }
285296465Sdelphij    if (!X509V3_extensions_print(bp, "Response Extensions",
286296465Sdelphij                                 rd->responseExtensions, flags, 4))
287296465Sdelphij        goto err;
288296465Sdelphij    if (X509_signature_print(bp, br->signatureAlgorithm, br->signature) <= 0)
289296465Sdelphij        goto err;
290109998Smarkm
291296465Sdelphij    for (i = 0; i < sk_X509_num(br->certs); i++) {
292296465Sdelphij        X509_print(bp, sk_X509_value(br->certs, i));
293296465Sdelphij        PEM_write_bio_X509(bp, sk_X509_value(br->certs, i));
294296465Sdelphij    }
295109998Smarkm
296296465Sdelphij    ret = 1;
297296465Sdelphij err:
298296465Sdelphij    OCSP_BASICRESP_free(br);
299296465Sdelphij    return ret;
300296465Sdelphij}
301