1/* $OpenBSD: ocsp_prn.c,v 1.10 2023/07/08 10:44:00 beck Exp $ */ 2/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 3 * project. */ 4 5/* History: 6 This file was originally part of ocsp.c and was transfered to Richard 7 Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be included 8 in OpenSSL or released as a patch kit. */ 9 10/* ==================================================================== 11 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. All advertising materials mentioning features or use of this 26 * software must display the following acknowledgment: 27 * "This product includes software developed by the OpenSSL Project 28 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 29 * 30 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 31 * endorse or promote products derived from this software without 32 * prior written permission. For written permission, please contact 33 * openssl-core@openssl.org. 34 * 35 * 5. Products derived from this software may not be called "OpenSSL" 36 * nor may "OpenSSL" appear in their names without prior written 37 * permission of the OpenSSL Project. 38 * 39 * 6. Redistributions of any form whatsoever must retain the following 40 * acknowledgment: 41 * "This product includes software developed by the OpenSSL Project 42 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 45 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 47 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 48 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 49 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 * OF THE POSSIBILITY OF SUCH DAMAGE. 56 * ==================================================================== 57 * 58 * This product includes cryptographic software written by Eric Young 59 * (eay@cryptsoft.com). This product includes software written by Tim 60 * Hudson (tjh@cryptsoft.com). 61 * 62 */ 63 64#include <openssl/bio.h> 65#include <openssl/err.h> 66#include <openssl/ocsp.h> 67#include <openssl/pem.h> 68 69#include "ocsp_local.h" 70 71static int 72ocsp_certid_print(BIO *bp, OCSP_CERTID* a, int indent) 73{ 74 BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); 75 indent += 2; 76 BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); 77 i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm); 78 BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); 79 i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING); 80 BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); 81 i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING); 82 BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); 83 i2a_ASN1_INTEGER(bp, a->serialNumber); 84 BIO_printf(bp, "\n"); 85 return 1; 86} 87 88typedef struct { 89 long t; 90 const char *m; 91} OCSP_TBLSTR; 92 93static const char * 94table2string(long s, const OCSP_TBLSTR *ts, int len) 95{ 96 const OCSP_TBLSTR *p; 97 98 for (p = ts; p < ts + len; p++) 99 if (p->t == s) 100 return p->m; 101 return "(UNKNOWN)"; 102} 103 104const char * 105OCSP_response_status_str(long s) 106{ 107 static const OCSP_TBLSTR rstat_tbl[] = { 108 { OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" }, 109 { OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest" }, 110 { OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror" }, 111 { OCSP_RESPONSE_STATUS_TRYLATER, "trylater" }, 112 { OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired" }, 113 { OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized" } 114 }; 115 return table2string(s, rstat_tbl, 6); 116} 117LCRYPTO_ALIAS(OCSP_response_status_str); 118 119const char * 120OCSP_cert_status_str(long s) 121{ 122 static const OCSP_TBLSTR cstat_tbl[] = { 123 { V_OCSP_CERTSTATUS_GOOD, "good" }, 124 { V_OCSP_CERTSTATUS_REVOKED, "revoked" }, 125 { V_OCSP_CERTSTATUS_UNKNOWN, "unknown" } 126 }; 127 return table2string(s, cstat_tbl, 3); 128} 129LCRYPTO_ALIAS(OCSP_cert_status_str); 130 131const char * 132OCSP_crl_reason_str(long s) 133{ 134 static const OCSP_TBLSTR reason_tbl[] = { 135 { OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified" }, 136 { OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise" }, 137 { OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise" }, 138 { OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged" }, 139 { OCSP_REVOKED_STATUS_SUPERSEDED, "superseded" }, 140 { OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation" }, 141 { OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold" }, 142 { OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL" } 143 }; 144 return table2string(s, reason_tbl, 8); 145} 146LCRYPTO_ALIAS(OCSP_crl_reason_str); 147 148int 149OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags) 150{ 151 int i; 152 long l; 153 OCSP_CERTID* cid = NULL; 154 OCSP_ONEREQ *one = NULL; 155 OCSP_REQINFO *inf = o->tbsRequest; 156 OCSP_SIGNATURE *sig = o->optionalSignature; 157 158 if (BIO_write(bp, "OCSP Request Data:\n", 19) <= 0) 159 goto err; 160 l = ASN1_INTEGER_get(inf->version); 161 if (BIO_printf(bp, " Version: %lu (0x%lx)", l+1, l) <= 0) 162 goto err; 163 if (inf->requestorName != NULL) { 164 if (BIO_write(bp, "\n Requestor Name: ", 21) <= 0) 165 goto err; 166 GENERAL_NAME_print(bp, inf->requestorName); 167 } 168 if (BIO_write(bp, "\n Requestor List:\n", 21) <= 0) 169 goto err; 170 for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) { 171 one = sk_OCSP_ONEREQ_value(inf->requestList, i); 172 cid = one->reqCert; 173 ocsp_certid_print(bp, cid, 8); 174 if (!X509V3_extensions_print(bp, "Request Single Extensions", 175 one->singleRequestExtensions, flags, 8)) 176 goto err; 177 } 178 if (!X509V3_extensions_print(bp, "Request Extensions", 179 inf->requestExtensions, flags, 4)) 180 goto err; 181 if (sig) { 182 if (X509_signature_print(bp, sig->signatureAlgorithm, 183 sig->signature) == 0) 184 goto err; 185 for (i = 0; i < sk_X509_num(sig->certs); i++) { 186 if (X509_print(bp, sk_X509_value(sig->certs, i)) == 0) 187 goto err; 188 if (PEM_write_bio_X509(bp, 189 sk_X509_value(sig->certs, i)) == 0) 190 goto err; 191 } 192 } 193 return 1; 194 195err: 196 return 0; 197} 198LCRYPTO_ALIAS(OCSP_REQUEST_print); 199 200int 201OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags) 202{ 203 int i, ret = 0; 204 long l; 205 OCSP_CERTID *cid = NULL; 206 OCSP_BASICRESP *br = NULL; 207 OCSP_RESPID *rid = NULL; 208 OCSP_RESPDATA *rd = NULL; 209 OCSP_CERTSTATUS *cst = NULL; 210 OCSP_REVOKEDINFO *rev = NULL; 211 OCSP_SINGLERESP *single = NULL; 212 OCSP_RESPBYTES *rb = o->responseBytes; 213 214 if (BIO_puts(bp, "OCSP Response Data:\n") <= 0) 215 goto err; 216 l = ASN1_ENUMERATED_get(o->responseStatus); 217 if (BIO_printf(bp, " OCSP Response Status: %s (0x%lx)\n", 218 OCSP_response_status_str(l), l) <= 0) 219 goto err; 220 if (rb == NULL) 221 return 1; 222 if (BIO_puts(bp, " Response Type: ") <= 0) 223 goto err; 224 if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) 225 goto err; 226 if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) { 227 BIO_puts(bp, " (unknown response type)\n"); 228 return 1; 229 } 230 231 i = ASN1_STRING_length(rb->response); 232 if (!(br = OCSP_response_get1_basic(o))) 233 goto err; 234 rd = br->tbsResponseData; 235 l = ASN1_INTEGER_get(rd->version); 236 if (BIO_printf(bp, "\n Version: %lu (0x%lx)\n", l+1, l) <= 0) 237 goto err; 238 if (BIO_puts(bp, " Responder Id: ") <= 0) 239 goto err; 240 241 rid = rd->responderId; 242 switch (rid->type) { 243 case V_OCSP_RESPID_NAME: 244 X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); 245 break; 246 case V_OCSP_RESPID_KEY: 247 i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING); 248 break; 249 } 250 251 if (BIO_printf(bp, "\n Produced At: ")<=0) 252 goto err; 253 if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) 254 goto err; 255 if (BIO_printf(bp, "\n Responses:\n") <= 0) 256 goto err; 257 for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) { 258 if (! sk_OCSP_SINGLERESP_value(rd->responses, i)) 259 continue; 260 single = sk_OCSP_SINGLERESP_value(rd->responses, i); 261 cid = single->certId; 262 if (ocsp_certid_print(bp, cid, 4) <= 0) 263 goto err; 264 cst = single->certStatus; 265 if (BIO_printf(bp, " Cert Status: %s", 266 OCSP_cert_status_str(cst->type)) <= 0) 267 goto err; 268 if (cst->type == V_OCSP_CERTSTATUS_REVOKED) { 269 rev = cst->value.revoked; 270 if (BIO_printf(bp, "\n Revocation Time: ") <= 0) 271 goto err; 272 if (!ASN1_GENERALIZEDTIME_print(bp, 273 rev->revocationTime)) 274 goto err; 275 if (rev->revocationReason) { 276 l = ASN1_ENUMERATED_get(rev->revocationReason); 277 if (BIO_printf(bp, 278 "\n Revocation Reason: %s (0x%lx)", 279 OCSP_crl_reason_str(l), l) <= 0) 280 goto err; 281 } 282 } 283 if (BIO_printf(bp, "\n This Update: ") <= 0) 284 goto err; 285 if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) 286 goto err; 287 if (single->nextUpdate) { 288 if (BIO_printf(bp, "\n Next Update: ") <= 0) 289 goto err; 290 if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate)) 291 goto err; 292 } 293 if (BIO_write(bp, "\n", 1) <= 0) 294 goto err; 295 if (!X509V3_extensions_print(bp, "Response Single Extensions", 296 single->singleExtensions, flags, 8)) 297 goto err; 298 if (BIO_write(bp, "\n", 1) <= 0) 299 goto err; 300 } 301 if (!X509V3_extensions_print(bp, "Response Extensions", 302 rd->responseExtensions, flags, 4)) 303 goto err; 304 if (X509_signature_print(bp, br->signatureAlgorithm, br->signature) <= 305 0) 306 goto err; 307 308 for (i = 0; i < sk_X509_num(br->certs); i++) { 309 X509_print(bp, sk_X509_value(br->certs, i)); 310 PEM_write_bio_X509(bp, sk_X509_value(br->certs, i)); 311 } 312 313 ret = 1; 314 315err: 316 OCSP_BASICRESP_free(br); 317 return ret; 318} 319LCRYPTO_ALIAS(OCSP_RESPONSE_print); 320