1109998Smarkm/* ocsp_prn.c */ 2109998Smarkm/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 3109998Smarkm * project. */ 4109998Smarkm 5109998Smarkm/* History: 6109998Smarkm This file was originally part of ocsp.c and was transfered to Richard 7109998Smarkm Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be included 8109998Smarkm in OpenSSL or released as a patch kit. */ 9109998Smarkm 10109998Smarkm/* ==================================================================== 11109998Smarkm * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 12109998Smarkm * 13109998Smarkm * Redistribution and use in source and binary forms, with or without 14109998Smarkm * modification, are permitted provided that the following conditions 15109998Smarkm * are met: 16109998Smarkm * 17109998Smarkm * 1. Redistributions of source code must retain the above copyright 18109998Smarkm * notice, this list of conditions and the following disclaimer. 19109998Smarkm * 20109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 21109998Smarkm * notice, this list of conditions and the following disclaimer in 22109998Smarkm * the documentation and/or other materials provided with the 23109998Smarkm * distribution. 24109998Smarkm * 25109998Smarkm * 3. All advertising materials mentioning features or use of this 26109998Smarkm * software must display the following acknowledgment: 27109998Smarkm * "This product includes software developed by the OpenSSL Project 28109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 29109998Smarkm * 30109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 31109998Smarkm * endorse or promote products derived from this software without 32109998Smarkm * prior written permission. For written permission, please contact 33109998Smarkm * openssl-core@openssl.org. 34109998Smarkm * 35109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 36109998Smarkm * nor may "OpenSSL" appear in their names without prior written 37109998Smarkm * permission of the OpenSSL Project. 38109998Smarkm * 39109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 40109998Smarkm * acknowledgment: 41109998Smarkm * "This product includes software developed by the OpenSSL Project 42109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 43109998Smarkm * 44109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 45109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 47109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 48109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 49109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 51109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 56109998Smarkm * ==================================================================== 57109998Smarkm * 58109998Smarkm * This product includes cryptographic software written by Eric Young 59109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 60109998Smarkm * Hudson (tjh@cryptsoft.com). 61109998Smarkm * 62109998Smarkm */ 63109998Smarkm 64109998Smarkm#include <openssl/bio.h> 65109998Smarkm#include <openssl/err.h> 66109998Smarkm#include <openssl/ocsp.h> 67109998Smarkm#include <openssl/pem.h> 68109998Smarkm 69109998Smarkmstatic int ocsp_certid_print(BIO *bp, OCSP_CERTID* a, int indent) 70109998Smarkm { 71109998Smarkm BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); 72109998Smarkm indent += 2; 73109998Smarkm BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); 74109998Smarkm i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm); 75109998Smarkm BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); 76109998Smarkm i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING); 77109998Smarkm BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); 78109998Smarkm i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING); 79109998Smarkm BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); 80109998Smarkm i2a_ASN1_INTEGER(bp, a->serialNumber); 81109998Smarkm BIO_printf(bp, "\n"); 82109998Smarkm return 1; 83109998Smarkm } 84109998Smarkm 85109998Smarkmtypedef struct 86109998Smarkm { 87109998Smarkm long t; 88238405Sjkim const char *m; 89109998Smarkm } OCSP_TBLSTR; 90109998Smarkm 91238405Sjkimstatic const char *table2string(long s, const OCSP_TBLSTR *ts, int len) 92109998Smarkm{ 93238405Sjkim const OCSP_TBLSTR *p; 94109998Smarkm for (p=ts; p < ts + len; p++) 95109998Smarkm if (p->t == s) 96109998Smarkm return p->m; 97109998Smarkm return "(UNKNOWN)"; 98109998Smarkm} 99109998Smarkm 100238405Sjkimconst char *OCSP_response_status_str(long s) 101109998Smarkm { 102238405Sjkim static const OCSP_TBLSTR rstat_tbl[] = { 103109998Smarkm { OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" }, 104109998Smarkm { OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest" }, 105109998Smarkm { OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror" }, 106109998Smarkm { OCSP_RESPONSE_STATUS_TRYLATER, "trylater" }, 107109998Smarkm { OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired" }, 108109998Smarkm { OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized" } }; 109109998Smarkm return table2string(s, rstat_tbl, 6); 110109998Smarkm } 111109998Smarkm 112238405Sjkimconst char *OCSP_cert_status_str(long s) 113109998Smarkm { 114238405Sjkim static const OCSP_TBLSTR cstat_tbl[] = { 115109998Smarkm { V_OCSP_CERTSTATUS_GOOD, "good" }, 116109998Smarkm { V_OCSP_CERTSTATUS_REVOKED, "revoked" }, 117109998Smarkm { V_OCSP_CERTSTATUS_UNKNOWN, "unknown" } }; 118109998Smarkm return table2string(s, cstat_tbl, 3); 119109998Smarkm } 120109998Smarkm 121238405Sjkimconst char *OCSP_crl_reason_str(long s) 122109998Smarkm { 123238405Sjkim static const OCSP_TBLSTR reason_tbl[] = { 124109998Smarkm { OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified" }, 125109998Smarkm { OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise" }, 126109998Smarkm { OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise" }, 127109998Smarkm { OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged" }, 128109998Smarkm { OCSP_REVOKED_STATUS_SUPERSEDED, "superseded" }, 129109998Smarkm { OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation" }, 130109998Smarkm { OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold" }, 131109998Smarkm { OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL" } }; 132109998Smarkm return table2string(s, reason_tbl, 8); 133109998Smarkm } 134109998Smarkm 135109998Smarkmint OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags) 136109998Smarkm { 137109998Smarkm int i; 138109998Smarkm long l; 139109998Smarkm OCSP_CERTID* cid = NULL; 140109998Smarkm OCSP_ONEREQ *one = NULL; 141109998Smarkm OCSP_REQINFO *inf = o->tbsRequest; 142109998Smarkm OCSP_SIGNATURE *sig = o->optionalSignature; 143109998Smarkm 144109998Smarkm if (BIO_write(bp,"OCSP Request Data:\n",19) <= 0) goto err; 145109998Smarkm l=ASN1_INTEGER_get(inf->version); 146109998Smarkm if (BIO_printf(bp," Version: %lu (0x%lx)",l+1,l) <= 0) goto err; 147109998Smarkm if (inf->requestorName != NULL) 148109998Smarkm { 149109998Smarkm if (BIO_write(bp,"\n Requestor Name: ",21) <= 0) 150109998Smarkm goto err; 151109998Smarkm GENERAL_NAME_print(bp, inf->requestorName); 152109998Smarkm } 153109998Smarkm if (BIO_write(bp,"\n Requestor List:\n",21) <= 0) goto err; 154109998Smarkm for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) 155109998Smarkm { 156109998Smarkm one = sk_OCSP_ONEREQ_value(inf->requestList, i); 157109998Smarkm cid = one->reqCert; 158109998Smarkm ocsp_certid_print(bp, cid, 8); 159109998Smarkm if (!X509V3_extensions_print(bp, 160109998Smarkm "Request Single Extensions", 161109998Smarkm one->singleRequestExtensions, flags, 8)) 162109998Smarkm goto err; 163109998Smarkm } 164109998Smarkm if (!X509V3_extensions_print(bp, "Request Extensions", 165109998Smarkm inf->requestExtensions, flags, 4)) 166109998Smarkm goto err; 167109998Smarkm if (sig) 168109998Smarkm { 169109998Smarkm X509_signature_print(bp, sig->signatureAlgorithm, sig->signature); 170109998Smarkm for (i=0; i<sk_X509_num(sig->certs); i++) 171109998Smarkm { 172109998Smarkm X509_print(bp, sk_X509_value(sig->certs,i)); 173109998Smarkm PEM_write_bio_X509(bp,sk_X509_value(sig->certs,i)); 174109998Smarkm } 175109998Smarkm } 176109998Smarkm return 1; 177109998Smarkmerr: 178109998Smarkm return 0; 179109998Smarkm } 180109998Smarkm 181109998Smarkmint OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags) 182109998Smarkm { 183109998Smarkm int i, ret = 0; 184109998Smarkm long l; 185109998Smarkm OCSP_CERTID *cid = NULL; 186109998Smarkm OCSP_BASICRESP *br = NULL; 187109998Smarkm OCSP_RESPID *rid = NULL; 188109998Smarkm OCSP_RESPDATA *rd = NULL; 189109998Smarkm OCSP_CERTSTATUS *cst = NULL; 190109998Smarkm OCSP_REVOKEDINFO *rev = NULL; 191109998Smarkm OCSP_SINGLERESP *single = NULL; 192109998Smarkm OCSP_RESPBYTES *rb = o->responseBytes; 193109998Smarkm 194109998Smarkm if (BIO_puts(bp,"OCSP Response Data:\n") <= 0) goto err; 195109998Smarkm l=ASN1_ENUMERATED_get(o->responseStatus); 196160814Ssimon if (BIO_printf(bp," OCSP Response Status: %s (0x%lx)\n", 197109998Smarkm OCSP_response_status_str(l), l) <= 0) goto err; 198109998Smarkm if (rb == NULL) return 1; 199109998Smarkm if (BIO_puts(bp," Response Type: ") <= 0) 200109998Smarkm goto err; 201109998Smarkm if(i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) 202109998Smarkm goto err; 203109998Smarkm if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) 204109998Smarkm { 205109998Smarkm BIO_puts(bp," (unknown response type)\n"); 206109998Smarkm return 1; 207109998Smarkm } 208109998Smarkm 209109998Smarkm i = ASN1_STRING_length(rb->response); 210109998Smarkm if (!(br = OCSP_response_get1_basic(o))) goto err; 211109998Smarkm rd = br->tbsResponseData; 212109998Smarkm l=ASN1_INTEGER_get(rd->version); 213109998Smarkm if (BIO_printf(bp,"\n Version: %lu (0x%lx)\n", 214109998Smarkm l+1,l) <= 0) goto err; 215109998Smarkm if (BIO_puts(bp," Responder Id: ") <= 0) goto err; 216109998Smarkm 217109998Smarkm rid = rd->responderId; 218109998Smarkm switch (rid->type) 219109998Smarkm { 220109998Smarkm case V_OCSP_RESPID_NAME: 221109998Smarkm X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); 222109998Smarkm break; 223109998Smarkm case V_OCSP_RESPID_KEY: 224109998Smarkm i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING); 225109998Smarkm break; 226109998Smarkm } 227109998Smarkm 228109998Smarkm if (BIO_printf(bp,"\n Produced At: ")<=0) goto err; 229109998Smarkm if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) goto err; 230109998Smarkm if (BIO_printf(bp,"\n Responses:\n") <= 0) goto err; 231109998Smarkm for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) 232109998Smarkm { 233109998Smarkm if (! sk_OCSP_SINGLERESP_value(rd->responses, i)) continue; 234109998Smarkm single = sk_OCSP_SINGLERESP_value(rd->responses, i); 235109998Smarkm cid = single->certId; 236109998Smarkm if(ocsp_certid_print(bp, cid, 4) <= 0) goto err; 237109998Smarkm cst = single->certStatus; 238109998Smarkm if (BIO_printf(bp," Cert Status: %s", 239109998Smarkm OCSP_cert_status_str(cst->type)) <= 0) 240109998Smarkm goto err; 241109998Smarkm if (cst->type == V_OCSP_CERTSTATUS_REVOKED) 242109998Smarkm { 243109998Smarkm rev = cst->value.revoked; 244109998Smarkm if (BIO_printf(bp, "\n Revocation Time: ") <= 0) 245109998Smarkm goto err; 246109998Smarkm if (!ASN1_GENERALIZEDTIME_print(bp, 247109998Smarkm rev->revocationTime)) 248109998Smarkm goto err; 249109998Smarkm if (rev->revocationReason) 250109998Smarkm { 251109998Smarkm l=ASN1_ENUMERATED_get(rev->revocationReason); 252109998Smarkm if (BIO_printf(bp, 253160814Ssimon "\n Revocation Reason: %s (0x%lx)", 254109998Smarkm OCSP_crl_reason_str(l), l) <= 0) 255109998Smarkm goto err; 256109998Smarkm } 257109998Smarkm } 258109998Smarkm if (BIO_printf(bp,"\n This Update: ") <= 0) goto err; 259109998Smarkm if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) 260109998Smarkm goto err; 261109998Smarkm if (single->nextUpdate) 262109998Smarkm { 263109998Smarkm if (BIO_printf(bp,"\n Next Update: ") <= 0)goto err; 264109998Smarkm if (!ASN1_GENERALIZEDTIME_print(bp,single->nextUpdate)) 265109998Smarkm goto err; 266109998Smarkm } 267205128Ssimon if (BIO_write(bp,"\n",1) <= 0) goto err; 268109998Smarkm if (!X509V3_extensions_print(bp, 269109998Smarkm "Response Single Extensions", 270109998Smarkm single->singleExtensions, flags, 8)) 271109998Smarkm goto err; 272205128Ssimon if (BIO_write(bp,"\n",1) <= 0) goto err; 273109998Smarkm } 274109998Smarkm if (!X509V3_extensions_print(bp, "Response Extensions", 275109998Smarkm rd->responseExtensions, flags, 4)) 276206046Ssimon goto err; 277109998Smarkm if(X509_signature_print(bp, br->signatureAlgorithm, br->signature) <= 0) 278109998Smarkm goto err; 279109998Smarkm 280109998Smarkm for (i=0; i<sk_X509_num(br->certs); i++) 281109998Smarkm { 282109998Smarkm X509_print(bp, sk_X509_value(br->certs,i)); 283109998Smarkm PEM_write_bio_X509(bp,sk_X509_value(br->certs,i)); 284109998Smarkm } 285109998Smarkm 286109998Smarkm ret = 1; 287109998Smarkmerr: 288109998Smarkm OCSP_BASICRESP_free(br); 289109998Smarkm return ret; 290109998Smarkm } 291