1 /* $OpenBSD: x509_ocsp.c,v 1.4 2024/12/24 09:14:33 schwarze 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 static const X509V3_EXT_METHOD x509v3_ext_id_pkix_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 * 116 x509v3_ext_method_id_pkix_OCSP_CrlID(void) 117 { 118 return &x509v3_ext_id_pkix_OCSP_CrlID; 119 } 120 121 static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_archiveCutoff = { 122 .ext_nid = NID_id_pkix_OCSP_archiveCutoff, 123 .ext_flags = 0, 124 .it = &ASN1_GENERALIZEDTIME_it, 125 .ext_new = NULL, 126 .ext_free = NULL, 127 .d2i = NULL, 128 .i2d = NULL, 129 .i2s = NULL, 130 .s2i = NULL, 131 .i2v = NULL, 132 .v2i = NULL, 133 .i2r = i2r_ocsp_acutoff, 134 .r2i = NULL, 135 .usr_data = NULL, 136 }; 137 138 const X509V3_EXT_METHOD * 139 x509v3_ext_method_id_pkix_OCSP_archiveCutoff(void) 140 { 141 return &x509v3_ext_id_pkix_OCSP_archiveCutoff; 142 } 143 144 static const X509V3_EXT_METHOD x509v3_ext_invalidity_date = { 145 .ext_nid = NID_invalidity_date, 146 .ext_flags = 0, 147 .it = &ASN1_GENERALIZEDTIME_it, 148 .ext_new = NULL, 149 .ext_free = NULL, 150 .d2i = NULL, 151 .i2d = NULL, 152 .i2s = NULL, 153 .s2i = NULL, 154 .i2v = NULL, 155 .v2i = NULL, 156 .i2r = i2r_ocsp_acutoff, 157 .r2i = NULL, 158 .usr_data = NULL, 159 }; 160 161 const X509V3_EXT_METHOD * 162 x509v3_ext_method_invalidity_date(void) 163 { 164 return &x509v3_ext_invalidity_date; 165 } 166 167 static const X509V3_EXT_METHOD x509v3_ext_hold_instruction_code = { 168 .ext_nid = NID_hold_instruction_code, 169 .ext_flags = 0, 170 .it = &ASN1_OBJECT_it, 171 .ext_new = NULL, 172 .ext_free = NULL, 173 .d2i = NULL, 174 .i2d = NULL, 175 .i2s = NULL, 176 .s2i = NULL, 177 .i2v = NULL, 178 .v2i = NULL, 179 .i2r = i2r_object, 180 .r2i = NULL, 181 .usr_data = NULL, 182 }; 183 184 const X509V3_EXT_METHOD * 185 x509v3_ext_method_hold_instruction_code(void) 186 { 187 return &x509v3_ext_hold_instruction_code; 188 } 189 190 static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_Nonce = { 191 .ext_nid = NID_id_pkix_OCSP_Nonce, 192 .ext_flags = 0, 193 .it = NULL, 194 .ext_new = ocsp_nonce_new, 195 .ext_free = ocsp_nonce_free, 196 .d2i = d2i_ocsp_nonce, 197 .i2d = i2d_ocsp_nonce, 198 .i2s = NULL, 199 .s2i = NULL, 200 .i2v = NULL, 201 .v2i = NULL, 202 .i2r = i2r_ocsp_nonce, 203 .r2i = NULL, 204 .usr_data = NULL, 205 }; 206 207 const X509V3_EXT_METHOD * 208 x509v3_ext_method_id_pkix_OCSP_Nonce(void) 209 { 210 return &x509v3_ext_id_pkix_OCSP_Nonce; 211 } 212 213 static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_noCheck = { 214 .ext_nid = NID_id_pkix_OCSP_noCheck, 215 .ext_flags = 0, 216 .it = &ASN1_NULL_it, 217 .ext_new = NULL, 218 .ext_free = NULL, 219 .d2i = NULL, 220 .i2d = NULL, 221 .i2s = NULL, 222 .s2i = s2i_ocsp_nocheck, 223 .i2v = NULL, 224 .v2i = NULL, 225 .i2r = i2r_ocsp_nocheck, 226 .r2i = NULL, 227 .usr_data = NULL, 228 }; 229 230 const X509V3_EXT_METHOD * 231 x509v3_ext_method_id_pkix_OCSP_noCheck(void) 232 { 233 return &x509v3_ext_id_pkix_OCSP_noCheck; 234 } 235 236 static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_serviceLocator = { 237 .ext_nid = NID_id_pkix_OCSP_serviceLocator, 238 .ext_flags = 0, 239 .it = &OCSP_SERVICELOC_it, 240 .ext_new = NULL, 241 .ext_free = NULL, 242 .d2i = NULL, 243 .i2d = NULL, 244 .i2s = NULL, 245 .s2i = NULL, 246 .i2v = NULL, 247 .v2i = NULL, 248 .i2r = i2r_ocsp_serviceloc, 249 .r2i = NULL, 250 .usr_data = NULL, 251 }; 252 253 const X509V3_EXT_METHOD * 254 x509v3_ext_method_id_pkix_OCSP_serviceLocator(void) 255 { 256 return &x509v3_ext_id_pkix_OCSP_serviceLocator; 257 } 258 259 static int 260 i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 261 { 262 OCSP_CRLID *a = in; 263 if (a->crlUrl) { 264 if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) 265 goto err; 266 if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) 267 goto err; 268 if (BIO_write(bp, "\n", 1) <= 0) 269 goto err; 270 } 271 if (a->crlNum) { 272 if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) 273 goto err; 274 if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) 275 goto err; 276 if (BIO_write(bp, "\n", 1) <= 0) 277 goto err; 278 } 279 if (a->crlTime) { 280 if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) 281 goto err; 282 if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) 283 goto err; 284 if (BIO_write(bp, "\n", 1) <= 0) 285 goto err; 286 } 287 return 1; 288 289 err: 290 return 0; 291 } 292 293 static int 294 i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, 295 int ind) 296 { 297 if (BIO_printf(bp, "%*s", ind, "") <= 0) 298 return 0; 299 if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) 300 return 0; 301 return 1; 302 } 303 304 static int 305 i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) 306 { 307 if (BIO_printf(bp, "%*s", ind, "") <= 0) 308 return 0; 309 if (i2a_ASN1_OBJECT(bp, oid) <= 0) 310 return 0; 311 return 1; 312 } 313 314 /* OCSP nonce. This is needs special treatment because it doesn't have 315 * an ASN1 encoding at all: it just contains arbitrary data. 316 */ 317 318 static void * 319 ocsp_nonce_new(void) 320 { 321 return ASN1_OCTET_STRING_new(); 322 } 323 324 static int 325 i2d_ocsp_nonce(void *a, unsigned char **pp) 326 { 327 ASN1_OCTET_STRING *os = a; 328 329 if (pp) { 330 memcpy(*pp, os->data, os->length); 331 *pp += os->length; 332 } 333 return os->length; 334 } 335 336 static void * 337 d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) 338 { 339 ASN1_OCTET_STRING *os, **pos; 340 341 pos = a; 342 if (pos == NULL || *pos == NULL) { 343 os = ASN1_OCTET_STRING_new(); 344 if (os == NULL) 345 goto err; 346 } else 347 os = *pos; 348 if (ASN1_OCTET_STRING_set(os, *pp, length) == 0) 349 goto err; 350 351 *pp += length; 352 353 if (pos != NULL) 354 *pos = os; 355 return os; 356 357 err: 358 if (pos == NULL || *pos != os) 359 ASN1_OCTET_STRING_free(os); 360 OCSPerror(ERR_R_MALLOC_FAILURE); 361 return NULL; 362 } 363 364 static void 365 ocsp_nonce_free(void *a) 366 { 367 ASN1_OCTET_STRING_free(a); 368 } 369 370 static int 371 i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, 372 int indent) 373 { 374 if (BIO_printf(out, "%*s", indent, "") <= 0) 375 return 0; 376 if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) 377 return 0; 378 return 1; 379 } 380 381 /* Nocheck is just a single NULL. Don't print anything and always set it */ 382 383 static int 384 i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, BIO *out, 385 int indent) 386 { 387 return 1; 388 } 389 390 static void * 391 s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 392 const char *str) 393 { 394 return ASN1_NULL_new(); 395 } 396 397 static int 398 i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 399 { 400 int i; 401 OCSP_SERVICELOC *a = in; 402 ACCESS_DESCRIPTION *ad; 403 404 if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) 405 goto err; 406 if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) 407 goto err; 408 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { 409 ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); 410 if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) 411 goto err; 412 if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) 413 goto err; 414 if (BIO_puts(bp, " - ") <= 0) 415 goto err; 416 if (GENERAL_NAME_print(bp, ad->location) <= 0) 417 goto err; 418 } 419 return 1; 420 421 err: 422 return 0; 423 } 424 #endif 425