1*65c90e3cSschwarze /* $OpenBSD: x509_ocsp.c,v 1.4 2024/12/24 09:14:33 schwarze Exp $ */ 2e500e238Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3e500e238Sjsing * project 1999. 4e500e238Sjsing */ 5e500e238Sjsing /* ==================================================================== 6e500e238Sjsing * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7e500e238Sjsing * 8e500e238Sjsing * Redistribution and use in source and binary forms, with or without 9e500e238Sjsing * modification, are permitted provided that the following conditions 10e500e238Sjsing * are met: 11e500e238Sjsing * 12e500e238Sjsing * 1. Redistributions of source code must retain the above copyright 13e500e238Sjsing * notice, this list of conditions and the following disclaimer. 14e500e238Sjsing * 15e500e238Sjsing * 2. Redistributions in binary form must reproduce the above copyright 16e500e238Sjsing * notice, this list of conditions and the following disclaimer in 17e500e238Sjsing * the documentation and/or other materials provided with the 18e500e238Sjsing * distribution. 19e500e238Sjsing * 20e500e238Sjsing * 3. All advertising materials mentioning features or use of this 21e500e238Sjsing * software must display the following acknowledgment: 22e500e238Sjsing * "This product includes software developed by the OpenSSL Project 23e500e238Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24e500e238Sjsing * 25e500e238Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26e500e238Sjsing * endorse or promote products derived from this software without 27e500e238Sjsing * prior written permission. For written permission, please contact 28e500e238Sjsing * licensing@OpenSSL.org. 29e500e238Sjsing * 30e500e238Sjsing * 5. Products derived from this software may not be called "OpenSSL" 31e500e238Sjsing * nor may "OpenSSL" appear in their names without prior written 32e500e238Sjsing * permission of the OpenSSL Project. 33e500e238Sjsing * 34e500e238Sjsing * 6. Redistributions of any form whatsoever must retain the following 35e500e238Sjsing * acknowledgment: 36e500e238Sjsing * "This product includes software developed by the OpenSSL Project 37e500e238Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38e500e238Sjsing * 39e500e238Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40e500e238Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41e500e238Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42e500e238Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43e500e238Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44e500e238Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45e500e238Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46e500e238Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47e500e238Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48e500e238Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49e500e238Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50e500e238Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 51e500e238Sjsing * ==================================================================== 52e500e238Sjsing * 53e500e238Sjsing * This product includes cryptographic software written by Eric Young 54e500e238Sjsing * (eay@cryptsoft.com). This product includes software written by Tim 55e500e238Sjsing * Hudson (tjh@cryptsoft.com). 56e500e238Sjsing * 57e500e238Sjsing */ 58e500e238Sjsing 59e500e238Sjsing #include <stdio.h> 60e500e238Sjsing #include <string.h> 61e500e238Sjsing 62e500e238Sjsing #include <openssl/opensslconf.h> 63e500e238Sjsing 64e500e238Sjsing #ifndef OPENSSL_NO_OCSP 65e500e238Sjsing 66e500e238Sjsing #include <openssl/asn1.h> 67e500e238Sjsing #include <openssl/conf.h> 68e500e238Sjsing #include <openssl/err.h> 69e500e238Sjsing #include <openssl/ocsp.h> 70e500e238Sjsing #include <openssl/x509v3.h> 71e500e238Sjsing 729f44a700Stb #include "ocsp_local.h" 739f44a700Stb 74e500e238Sjsing /* OCSP extensions and a couple of CRL entry extensions 75e500e238Sjsing */ 76e500e238Sjsing 77e500e238Sjsing static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *nonce, 78e500e238Sjsing BIO *out, int indent); 79e500e238Sjsing static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, 80e500e238Sjsing BIO *out, int indent); 81e500e238Sjsing static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out, 82e500e238Sjsing int indent); 83e500e238Sjsing 84e500e238Sjsing static void *ocsp_nonce_new(void); 85e500e238Sjsing static int i2d_ocsp_nonce(void *a, unsigned char **pp); 86e500e238Sjsing static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length); 87e500e238Sjsing static void ocsp_nonce_free(void *a); 88e500e238Sjsing static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, 89e500e238Sjsing BIO *out, int indent); 90e500e238Sjsing 91e500e238Sjsing static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, 92e500e238Sjsing void *nocheck, BIO *out, int indent); 93e500e238Sjsing static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 94e500e238Sjsing const char *str); 95e500e238Sjsing static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, 96e500e238Sjsing BIO *bp, int ind); 97e500e238Sjsing 988b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_CrlID = { 99e500e238Sjsing .ext_nid = NID_id_pkix_OCSP_CrlID, 100e500e238Sjsing .ext_flags = 0, 101e500e238Sjsing .it = &OCSP_CRLID_it, 102e500e238Sjsing .ext_new = NULL, 103e500e238Sjsing .ext_free = NULL, 104e500e238Sjsing .d2i = NULL, 105e500e238Sjsing .i2d = NULL, 106e500e238Sjsing .i2s = NULL, 107e500e238Sjsing .s2i = NULL, 108e500e238Sjsing .i2v = NULL, 109e500e238Sjsing .v2i = NULL, 110e500e238Sjsing .i2r = i2r_ocsp_crlid, 111e500e238Sjsing .r2i = NULL, 112e500e238Sjsing .usr_data = NULL, 113e500e238Sjsing }; 114e500e238Sjsing 1158b5faa71Stb const X509V3_EXT_METHOD * 1168b5faa71Stb x509v3_ext_method_id_pkix_OCSP_CrlID(void) 1178b5faa71Stb { 1188b5faa71Stb return &x509v3_ext_id_pkix_OCSP_CrlID; 1198b5faa71Stb } 1208b5faa71Stb 121*65c90e3cSschwarze static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_archiveCutoff = { 122e500e238Sjsing .ext_nid = NID_id_pkix_OCSP_archiveCutoff, 123e500e238Sjsing .ext_flags = 0, 124e500e238Sjsing .it = &ASN1_GENERALIZEDTIME_it, 125e500e238Sjsing .ext_new = NULL, 126e500e238Sjsing .ext_free = NULL, 127e500e238Sjsing .d2i = NULL, 128e500e238Sjsing .i2d = NULL, 129e500e238Sjsing .i2s = NULL, 130e500e238Sjsing .s2i = NULL, 131e500e238Sjsing .i2v = NULL, 132e500e238Sjsing .v2i = NULL, 133e500e238Sjsing .i2r = i2r_ocsp_acutoff, 134e500e238Sjsing .r2i = NULL, 135e500e238Sjsing .usr_data = NULL, 136e500e238Sjsing }; 137e500e238Sjsing 1388b5faa71Stb const X509V3_EXT_METHOD * 1398b5faa71Stb x509v3_ext_method_id_pkix_OCSP_archiveCutoff(void) 1408b5faa71Stb { 1418b5faa71Stb return &x509v3_ext_id_pkix_OCSP_archiveCutoff; 1428b5faa71Stb } 1438b5faa71Stb 1448b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_invalidity_date = { 145e500e238Sjsing .ext_nid = NID_invalidity_date, 146e500e238Sjsing .ext_flags = 0, 147e500e238Sjsing .it = &ASN1_GENERALIZEDTIME_it, 148e500e238Sjsing .ext_new = NULL, 149e500e238Sjsing .ext_free = NULL, 150e500e238Sjsing .d2i = NULL, 151e500e238Sjsing .i2d = NULL, 152e500e238Sjsing .i2s = NULL, 153e500e238Sjsing .s2i = NULL, 154e500e238Sjsing .i2v = NULL, 155e500e238Sjsing .v2i = NULL, 156e500e238Sjsing .i2r = i2r_ocsp_acutoff, 157e500e238Sjsing .r2i = NULL, 158e500e238Sjsing .usr_data = NULL, 159e500e238Sjsing }; 160e500e238Sjsing 1618b5faa71Stb const X509V3_EXT_METHOD * 1628b5faa71Stb x509v3_ext_method_invalidity_date(void) 1638b5faa71Stb { 1648b5faa71Stb return &x509v3_ext_invalidity_date; 1658b5faa71Stb } 1668b5faa71Stb 1678b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_hold_instruction_code = { 168e500e238Sjsing .ext_nid = NID_hold_instruction_code, 169e500e238Sjsing .ext_flags = 0, 170e500e238Sjsing .it = &ASN1_OBJECT_it, 171e500e238Sjsing .ext_new = NULL, 172e500e238Sjsing .ext_free = NULL, 173e500e238Sjsing .d2i = NULL, 174e500e238Sjsing .i2d = NULL, 175e500e238Sjsing .i2s = NULL, 176e500e238Sjsing .s2i = NULL, 177e500e238Sjsing .i2v = NULL, 178e500e238Sjsing .v2i = NULL, 179e500e238Sjsing .i2r = i2r_object, 180e500e238Sjsing .r2i = NULL, 181e500e238Sjsing .usr_data = NULL, 182e500e238Sjsing }; 183e500e238Sjsing 1848b5faa71Stb const X509V3_EXT_METHOD * 1858b5faa71Stb x509v3_ext_method_hold_instruction_code(void) 1868b5faa71Stb { 1878b5faa71Stb return &x509v3_ext_hold_instruction_code; 1888b5faa71Stb } 1898b5faa71Stb 1908b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_Nonce = { 191e500e238Sjsing .ext_nid = NID_id_pkix_OCSP_Nonce, 192e500e238Sjsing .ext_flags = 0, 193e500e238Sjsing .it = NULL, 194e500e238Sjsing .ext_new = ocsp_nonce_new, 195e500e238Sjsing .ext_free = ocsp_nonce_free, 196e500e238Sjsing .d2i = d2i_ocsp_nonce, 197e500e238Sjsing .i2d = i2d_ocsp_nonce, 198e500e238Sjsing .i2s = NULL, 199e500e238Sjsing .s2i = NULL, 200e500e238Sjsing .i2v = NULL, 201e500e238Sjsing .v2i = NULL, 202e500e238Sjsing .i2r = i2r_ocsp_nonce, 203e500e238Sjsing .r2i = NULL, 204e500e238Sjsing .usr_data = NULL, 205e500e238Sjsing }; 206e500e238Sjsing 2078b5faa71Stb const X509V3_EXT_METHOD * 2088b5faa71Stb x509v3_ext_method_id_pkix_OCSP_Nonce(void) 2098b5faa71Stb { 2108b5faa71Stb return &x509v3_ext_id_pkix_OCSP_Nonce; 2118b5faa71Stb } 2128b5faa71Stb 2138b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_noCheck = { 214e500e238Sjsing .ext_nid = NID_id_pkix_OCSP_noCheck, 215e500e238Sjsing .ext_flags = 0, 216e500e238Sjsing .it = &ASN1_NULL_it, 217e500e238Sjsing .ext_new = NULL, 218e500e238Sjsing .ext_free = NULL, 219e500e238Sjsing .d2i = NULL, 220e500e238Sjsing .i2d = NULL, 221e500e238Sjsing .i2s = NULL, 222e500e238Sjsing .s2i = s2i_ocsp_nocheck, 223e500e238Sjsing .i2v = NULL, 224e500e238Sjsing .v2i = NULL, 225e500e238Sjsing .i2r = i2r_ocsp_nocheck, 226e500e238Sjsing .r2i = NULL, 227e500e238Sjsing .usr_data = NULL, 228e500e238Sjsing }; 229e500e238Sjsing 2308b5faa71Stb const X509V3_EXT_METHOD * 2318b5faa71Stb x509v3_ext_method_id_pkix_OCSP_noCheck(void) 2328b5faa71Stb { 2338b5faa71Stb return &x509v3_ext_id_pkix_OCSP_noCheck; 2348b5faa71Stb } 2358b5faa71Stb 2368b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_id_pkix_OCSP_serviceLocator = { 237e500e238Sjsing .ext_nid = NID_id_pkix_OCSP_serviceLocator, 238e500e238Sjsing .ext_flags = 0, 239e500e238Sjsing .it = &OCSP_SERVICELOC_it, 240e500e238Sjsing .ext_new = NULL, 241e500e238Sjsing .ext_free = NULL, 242e500e238Sjsing .d2i = NULL, 243e500e238Sjsing .i2d = NULL, 244e500e238Sjsing .i2s = NULL, 245e500e238Sjsing .s2i = NULL, 246e500e238Sjsing .i2v = NULL, 247e500e238Sjsing .v2i = NULL, 248e500e238Sjsing .i2r = i2r_ocsp_serviceloc, 249e500e238Sjsing .r2i = NULL, 250e500e238Sjsing .usr_data = NULL, 251e500e238Sjsing }; 252e500e238Sjsing 2538b5faa71Stb const X509V3_EXT_METHOD * 2548b5faa71Stb x509v3_ext_method_id_pkix_OCSP_serviceLocator(void) 2558b5faa71Stb { 2568b5faa71Stb return &x509v3_ext_id_pkix_OCSP_serviceLocator; 2578b5faa71Stb } 2588b5faa71Stb 259e500e238Sjsing static int 260e500e238Sjsing i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 261e500e238Sjsing { 262e500e238Sjsing OCSP_CRLID *a = in; 263e500e238Sjsing if (a->crlUrl) { 264e500e238Sjsing if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) 265e500e238Sjsing goto err; 266e500e238Sjsing if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) 267e500e238Sjsing goto err; 268e500e238Sjsing if (BIO_write(bp, "\n", 1) <= 0) 269e500e238Sjsing goto err; 270e500e238Sjsing } 271e500e238Sjsing if (a->crlNum) { 272e500e238Sjsing if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) 273e500e238Sjsing goto err; 274e500e238Sjsing if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) 275e500e238Sjsing goto err; 276e500e238Sjsing if (BIO_write(bp, "\n", 1) <= 0) 277e500e238Sjsing goto err; 278e500e238Sjsing } 279e500e238Sjsing if (a->crlTime) { 280e500e238Sjsing if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) 281e500e238Sjsing goto err; 282e500e238Sjsing if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) 283e500e238Sjsing goto err; 284e500e238Sjsing if (BIO_write(bp, "\n", 1) <= 0) 285e500e238Sjsing goto err; 286e500e238Sjsing } 287e500e238Sjsing return 1; 288e500e238Sjsing 289e500e238Sjsing err: 290e500e238Sjsing return 0; 291e500e238Sjsing } 292e500e238Sjsing 293e500e238Sjsing static int 294e500e238Sjsing i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, 295e500e238Sjsing int ind) 296e500e238Sjsing { 297e500e238Sjsing if (BIO_printf(bp, "%*s", ind, "") <= 0) 298e500e238Sjsing return 0; 299e500e238Sjsing if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) 300e500e238Sjsing return 0; 301e500e238Sjsing return 1; 302e500e238Sjsing } 303e500e238Sjsing 304e500e238Sjsing static int 305e500e238Sjsing i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) 306e500e238Sjsing { 307e500e238Sjsing if (BIO_printf(bp, "%*s", ind, "") <= 0) 308e500e238Sjsing return 0; 309e500e238Sjsing if (i2a_ASN1_OBJECT(bp, oid) <= 0) 310e500e238Sjsing return 0; 311e500e238Sjsing return 1; 312e500e238Sjsing } 313e500e238Sjsing 314e500e238Sjsing /* OCSP nonce. This is needs special treatment because it doesn't have 315e500e238Sjsing * an ASN1 encoding at all: it just contains arbitrary data. 316e500e238Sjsing */ 317e500e238Sjsing 318e500e238Sjsing static void * 319e500e238Sjsing ocsp_nonce_new(void) 320e500e238Sjsing { 321e500e238Sjsing return ASN1_OCTET_STRING_new(); 322e500e238Sjsing } 323e500e238Sjsing 324e500e238Sjsing static int 325e500e238Sjsing i2d_ocsp_nonce(void *a, unsigned char **pp) 326e500e238Sjsing { 327e500e238Sjsing ASN1_OCTET_STRING *os = a; 328e500e238Sjsing 329e500e238Sjsing if (pp) { 330e500e238Sjsing memcpy(*pp, os->data, os->length); 331e500e238Sjsing *pp += os->length; 332e500e238Sjsing } 333e500e238Sjsing return os->length; 334e500e238Sjsing } 335e500e238Sjsing 336e500e238Sjsing static void * 337e500e238Sjsing d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) 338e500e238Sjsing { 339e500e238Sjsing ASN1_OCTET_STRING *os, **pos; 340e500e238Sjsing 341e500e238Sjsing pos = a; 342e500e238Sjsing if (pos == NULL || *pos == NULL) { 343e500e238Sjsing os = ASN1_OCTET_STRING_new(); 344e500e238Sjsing if (os == NULL) 345e500e238Sjsing goto err; 346e500e238Sjsing } else 347e500e238Sjsing os = *pos; 348e500e238Sjsing if (ASN1_OCTET_STRING_set(os, *pp, length) == 0) 349e500e238Sjsing goto err; 350e500e238Sjsing 351e500e238Sjsing *pp += length; 352e500e238Sjsing 353e500e238Sjsing if (pos != NULL) 354e500e238Sjsing *pos = os; 355e500e238Sjsing return os; 356e500e238Sjsing 357e500e238Sjsing err: 358e500e238Sjsing if (pos == NULL || *pos != os) 359e500e238Sjsing ASN1_OCTET_STRING_free(os); 360e500e238Sjsing OCSPerror(ERR_R_MALLOC_FAILURE); 361e500e238Sjsing return NULL; 362e500e238Sjsing } 363e500e238Sjsing 364e500e238Sjsing static void 365e500e238Sjsing ocsp_nonce_free(void *a) 366e500e238Sjsing { 367e500e238Sjsing ASN1_OCTET_STRING_free(a); 368e500e238Sjsing } 369e500e238Sjsing 370e500e238Sjsing static int 371e500e238Sjsing i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, 372e500e238Sjsing int indent) 373e500e238Sjsing { 374e500e238Sjsing if (BIO_printf(out, "%*s", indent, "") <= 0) 375e500e238Sjsing return 0; 376e500e238Sjsing if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) 377e500e238Sjsing return 0; 378e500e238Sjsing return 1; 379e500e238Sjsing } 380e500e238Sjsing 381e500e238Sjsing /* Nocheck is just a single NULL. Don't print anything and always set it */ 382e500e238Sjsing 383e500e238Sjsing static int 384e500e238Sjsing i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, BIO *out, 385e500e238Sjsing int indent) 386e500e238Sjsing { 387e500e238Sjsing return 1; 388e500e238Sjsing } 389e500e238Sjsing 390e500e238Sjsing static void * 391e500e238Sjsing s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 392e500e238Sjsing const char *str) 393e500e238Sjsing { 394e500e238Sjsing return ASN1_NULL_new(); 395e500e238Sjsing } 396e500e238Sjsing 397e500e238Sjsing static int 398e500e238Sjsing i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 399e500e238Sjsing { 400e500e238Sjsing int i; 401e500e238Sjsing OCSP_SERVICELOC *a = in; 402e500e238Sjsing ACCESS_DESCRIPTION *ad; 403e500e238Sjsing 404e500e238Sjsing if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) 405e500e238Sjsing goto err; 406e500e238Sjsing if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) 407e500e238Sjsing goto err; 408e500e238Sjsing for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { 409e500e238Sjsing ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); 410e500e238Sjsing if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) 411e500e238Sjsing goto err; 412e500e238Sjsing if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) 413e500e238Sjsing goto err; 414e500e238Sjsing if (BIO_puts(bp, " - ") <= 0) 415e500e238Sjsing goto err; 416e500e238Sjsing if (GENERAL_NAME_print(bp, ad->location) <= 0) 417e500e238Sjsing goto err; 418e500e238Sjsing } 419e500e238Sjsing return 1; 420e500e238Sjsing 421e500e238Sjsing err: 422e500e238Sjsing return 0; 423e500e238Sjsing } 424e500e238Sjsing #endif 425