1109998Smarkm/* ocsp_prn.c */
2280297Sjkim/*
3280297Sjkim * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
4280297Sjkim * project.
5280297Sjkim */
6109998Smarkm
7280297Sjkim/*
8280297Sjkim * History: This file was originally part of ocsp.c and was transfered to
9280297Sjkim * Richard Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be
10280297Sjkim * included in OpenSSL or released as a patch kit.
11280297Sjkim */
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
21280297Sjkim *    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
72280297Sjkimstatic int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent)
73280297Sjkim{
74280297Sjkim    BIO_printf(bp, "%*sCertificate ID:\n", indent, "");
75280297Sjkim    indent += 2;
76280297Sjkim    BIO_printf(bp, "%*sHash Algorithm: ", indent, "");
77280297Sjkim    i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm);
78280297Sjkim    BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, "");
79280297Sjkim    i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING);
80280297Sjkim    BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, "");
81280297Sjkim    i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING);
82280297Sjkim    BIO_printf(bp, "\n%*sSerial Number: ", indent, "");
83280297Sjkim    i2a_ASN1_INTEGER(bp, a->serialNumber);
84280297Sjkim    BIO_printf(bp, "\n");
85280297Sjkim    return 1;
86280297Sjkim}
87109998Smarkm
88280297Sjkimtypedef struct {
89280297Sjkim    long t;
90280297Sjkim    const char *m;
91280297Sjkim} OCSP_TBLSTR;
92109998Smarkm
93238405Sjkimstatic const char *table2string(long s, const OCSP_TBLSTR *ts, int len)
94109998Smarkm{
95280297Sjkim    const OCSP_TBLSTR *p;
96280297Sjkim    for (p = ts; p < ts + len; p++)
97280297Sjkim        if (p->t == s)
98280297Sjkim            return p->m;
99280297Sjkim    return "(UNKNOWN)";
100109998Smarkm}
101109998Smarkm
102238405Sjkimconst char *OCSP_response_status_str(long s)
103280297Sjkim{
104280297Sjkim    static const OCSP_TBLSTR rstat_tbl[] = {
105280297Sjkim        {OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful"},
106280297Sjkim        {OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest"},
107280297Sjkim        {OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror"},
108280297Sjkim        {OCSP_RESPONSE_STATUS_TRYLATER, "trylater"},
109280297Sjkim        {OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired"},
110280297Sjkim        {OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized"}
111280297Sjkim    };
112280297Sjkim    return table2string(s, rstat_tbl, 6);
113280297Sjkim}
114109998Smarkm
115238405Sjkimconst char *OCSP_cert_status_str(long s)
116280297Sjkim{
117280297Sjkim    static const OCSP_TBLSTR cstat_tbl[] = {
118280297Sjkim        {V_OCSP_CERTSTATUS_GOOD, "good"},
119280297Sjkim        {V_OCSP_CERTSTATUS_REVOKED, "revoked"},
120280297Sjkim        {V_OCSP_CERTSTATUS_UNKNOWN, "unknown"}
121280297Sjkim    };
122280297Sjkim    return table2string(s, cstat_tbl, 3);
123280297Sjkim}
124109998Smarkm
125238405Sjkimconst char *OCSP_crl_reason_str(long s)
126280297Sjkim{
127280297Sjkim    static const OCSP_TBLSTR reason_tbl[] = {
128280297Sjkim        {OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified"},
129280297Sjkim        {OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise"},
130280297Sjkim        {OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise"},
131280297Sjkim        {OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged"},
132280297Sjkim        {OCSP_REVOKED_STATUS_SUPERSEDED, "superseded"},
133280297Sjkim        {OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation"},
134280297Sjkim        {OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold"},
135280297Sjkim        {OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL"}
136280297Sjkim    };
137280297Sjkim    return table2string(s, reason_tbl, 8);
138280297Sjkim}
139109998Smarkm
140280297Sjkimint OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *o, unsigned long flags)
141280297Sjkim{
142280297Sjkim    int i;
143280297Sjkim    long l;
144280297Sjkim    OCSP_CERTID *cid = NULL;
145280297Sjkim    OCSP_ONEREQ *one = NULL;
146280297Sjkim    OCSP_REQINFO *inf = o->tbsRequest;
147280297Sjkim    OCSP_SIGNATURE *sig = o->optionalSignature;
148109998Smarkm
149280297Sjkim    if (BIO_write(bp, "OCSP Request Data:\n", 19) <= 0)
150280297Sjkim        goto err;
151280297Sjkim    l = ASN1_INTEGER_get(inf->version);
152280297Sjkim    if (BIO_printf(bp, "    Version: %lu (0x%lx)", l + 1, l) <= 0)
153280297Sjkim        goto err;
154280297Sjkim    if (inf->requestorName != NULL) {
155280297Sjkim        if (BIO_write(bp, "\n    Requestor Name: ", 21) <= 0)
156280297Sjkim            goto err;
157280297Sjkim        GENERAL_NAME_print(bp, inf->requestorName);
158280297Sjkim    }
159280297Sjkim    if (BIO_write(bp, "\n    Requestor List:\n", 21) <= 0)
160280297Sjkim        goto err;
161280297Sjkim    for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) {
162280297Sjkim        one = sk_OCSP_ONEREQ_value(inf->requestList, i);
163280297Sjkim        cid = one->reqCert;
164280297Sjkim        ocsp_certid_print(bp, cid, 8);
165280297Sjkim        if (!X509V3_extensions_print(bp,
166280297Sjkim                                     "Request Single Extensions",
167280297Sjkim                                     one->singleRequestExtensions, flags, 8))
168280297Sjkim            goto err;
169280297Sjkim    }
170280297Sjkim    if (!X509V3_extensions_print(bp, "Request Extensions",
171280297Sjkim                                 inf->requestExtensions, flags, 4))
172280297Sjkim        goto err;
173280297Sjkim    if (sig) {
174280297Sjkim        X509_signature_print(bp, sig->signatureAlgorithm, sig->signature);
175280297Sjkim        for (i = 0; i < sk_X509_num(sig->certs); i++) {
176280297Sjkim            X509_print(bp, sk_X509_value(sig->certs, i));
177280297Sjkim            PEM_write_bio_X509(bp, sk_X509_value(sig->certs, i));
178280297Sjkim        }
179280297Sjkim    }
180280297Sjkim    return 1;
181280297Sjkim err:
182280297Sjkim    return 0;
183280297Sjkim}
184109998Smarkm
185280297Sjkimint OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags)
186280297Sjkim{
187280297Sjkim    int i, ret = 0;
188280297Sjkim    long l;
189280297Sjkim    OCSP_CERTID *cid = NULL;
190280297Sjkim    OCSP_BASICRESP *br = NULL;
191280297Sjkim    OCSP_RESPID *rid = NULL;
192280297Sjkim    OCSP_RESPDATA *rd = NULL;
193280297Sjkim    OCSP_CERTSTATUS *cst = NULL;
194280297Sjkim    OCSP_REVOKEDINFO *rev = NULL;
195280297Sjkim    OCSP_SINGLERESP *single = NULL;
196280297Sjkim    OCSP_RESPBYTES *rb = o->responseBytes;
197109998Smarkm
198280297Sjkim    if (BIO_puts(bp, "OCSP Response Data:\n") <= 0)
199280297Sjkim        goto err;
200280297Sjkim    l = ASN1_ENUMERATED_get(o->responseStatus);
201280297Sjkim    if (BIO_printf(bp, "    OCSP Response Status: %s (0x%lx)\n",
202280297Sjkim                   OCSP_response_status_str(l), l) <= 0)
203280297Sjkim        goto err;
204280297Sjkim    if (rb == NULL)
205280297Sjkim        return 1;
206280297Sjkim    if (BIO_puts(bp, "    Response Type: ") <= 0)
207280297Sjkim        goto err;
208280297Sjkim    if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0)
209280297Sjkim        goto err;
210280297Sjkim    if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
211280297Sjkim        BIO_puts(bp, " (unknown response type)\n");
212280297Sjkim        return 1;
213280297Sjkim    }
214109998Smarkm
215291719Sjkim    if ((br = OCSP_response_get1_basic(o)) == NULL)
216280297Sjkim        goto err;
217280297Sjkim    rd = br->tbsResponseData;
218280297Sjkim    l = ASN1_INTEGER_get(rd->version);
219280297Sjkim    if (BIO_printf(bp, "\n    Version: %lu (0x%lx)\n", l + 1, l) <= 0)
220280297Sjkim        goto err;
221280297Sjkim    if (BIO_puts(bp, "    Responder Id: ") <= 0)
222280297Sjkim        goto err;
223109998Smarkm
224280297Sjkim    rid = rd->responderId;
225280297Sjkim    switch (rid->type) {
226280297Sjkim    case V_OCSP_RESPID_NAME:
227280297Sjkim        X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE);
228280297Sjkim        break;
229280297Sjkim    case V_OCSP_RESPID_KEY:
230280297Sjkim        i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING);
231280297Sjkim        break;
232280297Sjkim    }
233109998Smarkm
234280297Sjkim    if (BIO_printf(bp, "\n    Produced At: ") <= 0)
235280297Sjkim        goto err;
236280297Sjkim    if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt))
237280297Sjkim        goto err;
238280297Sjkim    if (BIO_printf(bp, "\n    Responses:\n") <= 0)
239280297Sjkim        goto err;
240280297Sjkim    for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) {
241280297Sjkim        if (!sk_OCSP_SINGLERESP_value(rd->responses, i))
242280297Sjkim            continue;
243280297Sjkim        single = sk_OCSP_SINGLERESP_value(rd->responses, i);
244280297Sjkim        cid = single->certId;
245280297Sjkim        if (ocsp_certid_print(bp, cid, 4) <= 0)
246280297Sjkim            goto err;
247280297Sjkim        cst = single->certStatus;
248280297Sjkim        if (BIO_printf(bp, "    Cert Status: %s",
249280297Sjkim                       OCSP_cert_status_str(cst->type)) <= 0)
250280297Sjkim            goto err;
251280297Sjkim        if (cst->type == V_OCSP_CERTSTATUS_REVOKED) {
252280297Sjkim            rev = cst->value.revoked;
253280297Sjkim            if (BIO_printf(bp, "\n    Revocation Time: ") <= 0)
254280297Sjkim                goto err;
255280297Sjkim            if (!ASN1_GENERALIZEDTIME_print(bp, rev->revocationTime))
256280297Sjkim                goto err;
257280297Sjkim            if (rev->revocationReason) {
258280297Sjkim                l = ASN1_ENUMERATED_get(rev->revocationReason);
259280297Sjkim                if (BIO_printf(bp,
260280297Sjkim                               "\n    Revocation Reason: %s (0x%lx)",
261280297Sjkim                               OCSP_crl_reason_str(l), l) <= 0)
262280297Sjkim                    goto err;
263280297Sjkim            }
264280297Sjkim        }
265280297Sjkim        if (BIO_printf(bp, "\n    This Update: ") <= 0)
266280297Sjkim            goto err;
267280297Sjkim        if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate))
268280297Sjkim            goto err;
269280297Sjkim        if (single->nextUpdate) {
270280297Sjkim            if (BIO_printf(bp, "\n    Next Update: ") <= 0)
271280297Sjkim                goto err;
272280297Sjkim            if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate))
273280297Sjkim                goto err;
274280297Sjkim        }
275280297Sjkim        if (BIO_write(bp, "\n", 1) <= 0)
276280297Sjkim            goto err;
277280297Sjkim        if (!X509V3_extensions_print(bp,
278280297Sjkim                                     "Response Single Extensions",
279280297Sjkim                                     single->singleExtensions, flags, 8))
280280297Sjkim            goto err;
281280297Sjkim        if (BIO_write(bp, "\n", 1) <= 0)
282280297Sjkim            goto err;
283280297Sjkim    }
284280297Sjkim    if (!X509V3_extensions_print(bp, "Response Extensions",
285280297Sjkim                                 rd->responseExtensions, flags, 4))
286280297Sjkim        goto err;
287280297Sjkim    if (X509_signature_print(bp, br->signatureAlgorithm, br->signature) <= 0)
288280297Sjkim        goto err;
289109998Smarkm
290280297Sjkim    for (i = 0; i < sk_X509_num(br->certs); i++) {
291280297Sjkim        X509_print(bp, sk_X509_value(br->certs, i));
292280297Sjkim        PEM_write_bio_X509(bp, sk_X509_value(br->certs, i));
293280297Sjkim    }
294109998Smarkm
295280297Sjkim    ret = 1;
296280297Sjkim err:
297280297Sjkim    OCSP_BASICRESP_free(br);
298280297Sjkim    return ret;
299280297Sjkim}
300