1 /* $OpenBSD: x509_ocsp.c,v 1.2 2022/01/07 09:45:52 tb Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 1999. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <openssl/opensslconf.h> 63 64 #ifndef OPENSSL_NO_OCSP 65 66 #include <openssl/asn1.h> 67 #include <openssl/conf.h> 68 #include <openssl/err.h> 69 #include <openssl/ocsp.h> 70 #include <openssl/x509v3.h> 71 72 #include "ocsp_local.h" 73 74 /* OCSP extensions and a couple of CRL entry extensions 75 */ 76 77 static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *nonce, 78 BIO *out, int indent); 79 static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, 80 BIO *out, int indent); 81 static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out, 82 int indent); 83 84 static void *ocsp_nonce_new(void); 85 static int i2d_ocsp_nonce(void *a, unsigned char **pp); 86 static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length); 87 static void ocsp_nonce_free(void *a); 88 static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, 89 BIO *out, int indent); 90 91 static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, 92 void *nocheck, BIO *out, int indent); 93 static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 94 const char *str); 95 static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, 96 BIO *bp, int ind); 97 98 const X509V3_EXT_METHOD v3_ocsp_crlid = { 99 .ext_nid = NID_id_pkix_OCSP_CrlID, 100 .ext_flags = 0, 101 .it = &OCSP_CRLID_it, 102 .ext_new = NULL, 103 .ext_free = NULL, 104 .d2i = NULL, 105 .i2d = NULL, 106 .i2s = NULL, 107 .s2i = NULL, 108 .i2v = NULL, 109 .v2i = NULL, 110 .i2r = i2r_ocsp_crlid, 111 .r2i = NULL, 112 .usr_data = NULL, 113 }; 114 115 const X509V3_EXT_METHOD v3_ocsp_acutoff = { 116 .ext_nid = NID_id_pkix_OCSP_archiveCutoff, 117 .ext_flags = 0, 118 .it = &ASN1_GENERALIZEDTIME_it, 119 .ext_new = NULL, 120 .ext_free = NULL, 121 .d2i = NULL, 122 .i2d = NULL, 123 .i2s = NULL, 124 .s2i = NULL, 125 .i2v = NULL, 126 .v2i = NULL, 127 .i2r = i2r_ocsp_acutoff, 128 .r2i = NULL, 129 .usr_data = NULL, 130 }; 131 132 const X509V3_EXT_METHOD v3_crl_invdate = { 133 .ext_nid = NID_invalidity_date, 134 .ext_flags = 0, 135 .it = &ASN1_GENERALIZEDTIME_it, 136 .ext_new = NULL, 137 .ext_free = NULL, 138 .d2i = NULL, 139 .i2d = NULL, 140 .i2s = NULL, 141 .s2i = NULL, 142 .i2v = NULL, 143 .v2i = NULL, 144 .i2r = i2r_ocsp_acutoff, 145 .r2i = NULL, 146 .usr_data = NULL, 147 }; 148 149 const X509V3_EXT_METHOD v3_crl_hold = { 150 .ext_nid = NID_hold_instruction_code, 151 .ext_flags = 0, 152 .it = &ASN1_OBJECT_it, 153 .ext_new = NULL, 154 .ext_free = NULL, 155 .d2i = NULL, 156 .i2d = NULL, 157 .i2s = NULL, 158 .s2i = NULL, 159 .i2v = NULL, 160 .v2i = NULL, 161 .i2r = i2r_object, 162 .r2i = NULL, 163 .usr_data = NULL, 164 }; 165 166 const X509V3_EXT_METHOD v3_ocsp_nonce = { 167 .ext_nid = NID_id_pkix_OCSP_Nonce, 168 .ext_flags = 0, 169 .it = NULL, 170 .ext_new = ocsp_nonce_new, 171 .ext_free = ocsp_nonce_free, 172 .d2i = d2i_ocsp_nonce, 173 .i2d = i2d_ocsp_nonce, 174 .i2s = NULL, 175 .s2i = NULL, 176 .i2v = NULL, 177 .v2i = NULL, 178 .i2r = i2r_ocsp_nonce, 179 .r2i = NULL, 180 .usr_data = NULL, 181 }; 182 183 const X509V3_EXT_METHOD v3_ocsp_nocheck = { 184 .ext_nid = NID_id_pkix_OCSP_noCheck, 185 .ext_flags = 0, 186 .it = &ASN1_NULL_it, 187 .ext_new = NULL, 188 .ext_free = NULL, 189 .d2i = NULL, 190 .i2d = NULL, 191 .i2s = NULL, 192 .s2i = s2i_ocsp_nocheck, 193 .i2v = NULL, 194 .v2i = NULL, 195 .i2r = i2r_ocsp_nocheck, 196 .r2i = NULL, 197 .usr_data = NULL, 198 }; 199 200 const X509V3_EXT_METHOD v3_ocsp_serviceloc = { 201 .ext_nid = NID_id_pkix_OCSP_serviceLocator, 202 .ext_flags = 0, 203 .it = &OCSP_SERVICELOC_it, 204 .ext_new = NULL, 205 .ext_free = NULL, 206 .d2i = NULL, 207 .i2d = NULL, 208 .i2s = NULL, 209 .s2i = NULL, 210 .i2v = NULL, 211 .v2i = NULL, 212 .i2r = i2r_ocsp_serviceloc, 213 .r2i = NULL, 214 .usr_data = NULL, 215 }; 216 217 static int 218 i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 219 { 220 OCSP_CRLID *a = in; 221 if (a->crlUrl) { 222 if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) 223 goto err; 224 if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) 225 goto err; 226 if (BIO_write(bp, "\n", 1) <= 0) 227 goto err; 228 } 229 if (a->crlNum) { 230 if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) 231 goto err; 232 if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) 233 goto err; 234 if (BIO_write(bp, "\n", 1) <= 0) 235 goto err; 236 } 237 if (a->crlTime) { 238 if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) 239 goto err; 240 if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) 241 goto err; 242 if (BIO_write(bp, "\n", 1) <= 0) 243 goto err; 244 } 245 return 1; 246 247 err: 248 return 0; 249 } 250 251 static int 252 i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, 253 int ind) 254 { 255 if (BIO_printf(bp, "%*s", ind, "") <= 0) 256 return 0; 257 if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) 258 return 0; 259 return 1; 260 } 261 262 static int 263 i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) 264 { 265 if (BIO_printf(bp, "%*s", ind, "") <= 0) 266 return 0; 267 if (i2a_ASN1_OBJECT(bp, oid) <= 0) 268 return 0; 269 return 1; 270 } 271 272 /* OCSP nonce. This is needs special treatment because it doesn't have 273 * an ASN1 encoding at all: it just contains arbitrary data. 274 */ 275 276 static void * 277 ocsp_nonce_new(void) 278 { 279 return ASN1_OCTET_STRING_new(); 280 } 281 282 static int 283 i2d_ocsp_nonce(void *a, unsigned char **pp) 284 { 285 ASN1_OCTET_STRING *os = a; 286 287 if (pp) { 288 memcpy(*pp, os->data, os->length); 289 *pp += os->length; 290 } 291 return os->length; 292 } 293 294 static void * 295 d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) 296 { 297 ASN1_OCTET_STRING *os, **pos; 298 299 pos = a; 300 if (pos == NULL || *pos == NULL) { 301 os = ASN1_OCTET_STRING_new(); 302 if (os == NULL) 303 goto err; 304 } else 305 os = *pos; 306 if (ASN1_OCTET_STRING_set(os, *pp, length) == 0) 307 goto err; 308 309 *pp += length; 310 311 if (pos != NULL) 312 *pos = os; 313 return os; 314 315 err: 316 if (pos == NULL || *pos != os) 317 ASN1_OCTET_STRING_free(os); 318 OCSPerror(ERR_R_MALLOC_FAILURE); 319 return NULL; 320 } 321 322 static void 323 ocsp_nonce_free(void *a) 324 { 325 ASN1_OCTET_STRING_free(a); 326 } 327 328 static int 329 i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, 330 int indent) 331 { 332 if (BIO_printf(out, "%*s", indent, "") <= 0) 333 return 0; 334 if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) 335 return 0; 336 return 1; 337 } 338 339 /* Nocheck is just a single NULL. Don't print anything and always set it */ 340 341 static int 342 i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, BIO *out, 343 int indent) 344 { 345 return 1; 346 } 347 348 static void * 349 s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 350 const char *str) 351 { 352 return ASN1_NULL_new(); 353 } 354 355 static int 356 i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 357 { 358 int i; 359 OCSP_SERVICELOC *a = in; 360 ACCESS_DESCRIPTION *ad; 361 362 if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) 363 goto err; 364 if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) 365 goto err; 366 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { 367 ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); 368 if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) 369 goto err; 370 if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) 371 goto err; 372 if (BIO_puts(bp, " - ") <= 0) 373 goto err; 374 if (GENERAL_NAME_print(bp, ad->location) <= 0) 375 goto err; 376 } 377 return 1; 378 379 err: 380 return 0; 381 } 382 #endif 383