1 /* $OpenBSD: x509_ocsp.c,v 1.1 2020/06/04 15:19:31 jsing 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 /* OCSP extensions and a couple of CRL entry extensions 73 */ 74 75 static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *nonce, 76 BIO *out, int indent); 77 static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, 78 BIO *out, int indent); 79 static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out, 80 int indent); 81 82 static void *ocsp_nonce_new(void); 83 static int i2d_ocsp_nonce(void *a, unsigned char **pp); 84 static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length); 85 static void ocsp_nonce_free(void *a); 86 static int i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, 87 BIO *out, int indent); 88 89 static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, 90 void *nocheck, BIO *out, int indent); 91 static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 92 const char *str); 93 static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, 94 BIO *bp, int ind); 95 96 const X509V3_EXT_METHOD v3_ocsp_crlid = { 97 .ext_nid = NID_id_pkix_OCSP_CrlID, 98 .ext_flags = 0, 99 .it = &OCSP_CRLID_it, 100 .ext_new = NULL, 101 .ext_free = NULL, 102 .d2i = NULL, 103 .i2d = NULL, 104 .i2s = NULL, 105 .s2i = NULL, 106 .i2v = NULL, 107 .v2i = NULL, 108 .i2r = i2r_ocsp_crlid, 109 .r2i = NULL, 110 .usr_data = NULL, 111 }; 112 113 const X509V3_EXT_METHOD v3_ocsp_acutoff = { 114 .ext_nid = NID_id_pkix_OCSP_archiveCutoff, 115 .ext_flags = 0, 116 .it = &ASN1_GENERALIZEDTIME_it, 117 .ext_new = NULL, 118 .ext_free = NULL, 119 .d2i = NULL, 120 .i2d = NULL, 121 .i2s = NULL, 122 .s2i = NULL, 123 .i2v = NULL, 124 .v2i = NULL, 125 .i2r = i2r_ocsp_acutoff, 126 .r2i = NULL, 127 .usr_data = NULL, 128 }; 129 130 const X509V3_EXT_METHOD v3_crl_invdate = { 131 .ext_nid = NID_invalidity_date, 132 .ext_flags = 0, 133 .it = &ASN1_GENERALIZEDTIME_it, 134 .ext_new = NULL, 135 .ext_free = NULL, 136 .d2i = NULL, 137 .i2d = NULL, 138 .i2s = NULL, 139 .s2i = NULL, 140 .i2v = NULL, 141 .v2i = NULL, 142 .i2r = i2r_ocsp_acutoff, 143 .r2i = NULL, 144 .usr_data = NULL, 145 }; 146 147 const X509V3_EXT_METHOD v3_crl_hold = { 148 .ext_nid = NID_hold_instruction_code, 149 .ext_flags = 0, 150 .it = &ASN1_OBJECT_it, 151 .ext_new = NULL, 152 .ext_free = NULL, 153 .d2i = NULL, 154 .i2d = NULL, 155 .i2s = NULL, 156 .s2i = NULL, 157 .i2v = NULL, 158 .v2i = NULL, 159 .i2r = i2r_object, 160 .r2i = NULL, 161 .usr_data = NULL, 162 }; 163 164 const X509V3_EXT_METHOD v3_ocsp_nonce = { 165 .ext_nid = NID_id_pkix_OCSP_Nonce, 166 .ext_flags = 0, 167 .it = NULL, 168 .ext_new = ocsp_nonce_new, 169 .ext_free = ocsp_nonce_free, 170 .d2i = d2i_ocsp_nonce, 171 .i2d = i2d_ocsp_nonce, 172 .i2s = NULL, 173 .s2i = NULL, 174 .i2v = NULL, 175 .v2i = NULL, 176 .i2r = i2r_ocsp_nonce, 177 .r2i = NULL, 178 .usr_data = NULL, 179 }; 180 181 const X509V3_EXT_METHOD v3_ocsp_nocheck = { 182 .ext_nid = NID_id_pkix_OCSP_noCheck, 183 .ext_flags = 0, 184 .it = &ASN1_NULL_it, 185 .ext_new = NULL, 186 .ext_free = NULL, 187 .d2i = NULL, 188 .i2d = NULL, 189 .i2s = NULL, 190 .s2i = s2i_ocsp_nocheck, 191 .i2v = NULL, 192 .v2i = NULL, 193 .i2r = i2r_ocsp_nocheck, 194 .r2i = NULL, 195 .usr_data = NULL, 196 }; 197 198 const X509V3_EXT_METHOD v3_ocsp_serviceloc = { 199 .ext_nid = NID_id_pkix_OCSP_serviceLocator, 200 .ext_flags = 0, 201 .it = &OCSP_SERVICELOC_it, 202 .ext_new = NULL, 203 .ext_free = NULL, 204 .d2i = NULL, 205 .i2d = NULL, 206 .i2s = NULL, 207 .s2i = NULL, 208 .i2v = NULL, 209 .v2i = NULL, 210 .i2r = i2r_ocsp_serviceloc, 211 .r2i = NULL, 212 .usr_data = NULL, 213 }; 214 215 static int 216 i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 217 { 218 OCSP_CRLID *a = in; 219 if (a->crlUrl) { 220 if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) 221 goto err; 222 if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) 223 goto err; 224 if (BIO_write(bp, "\n", 1) <= 0) 225 goto err; 226 } 227 if (a->crlNum) { 228 if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) 229 goto err; 230 if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) 231 goto err; 232 if (BIO_write(bp, "\n", 1) <= 0) 233 goto err; 234 } 235 if (a->crlTime) { 236 if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) 237 goto err; 238 if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) 239 goto err; 240 if (BIO_write(bp, "\n", 1) <= 0) 241 goto err; 242 } 243 return 1; 244 245 err: 246 return 0; 247 } 248 249 static int 250 i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, 251 int ind) 252 { 253 if (BIO_printf(bp, "%*s", ind, "") <= 0) 254 return 0; 255 if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) 256 return 0; 257 return 1; 258 } 259 260 static int 261 i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) 262 { 263 if (BIO_printf(bp, "%*s", ind, "") <= 0) 264 return 0; 265 if (i2a_ASN1_OBJECT(bp, oid) <= 0) 266 return 0; 267 return 1; 268 } 269 270 /* OCSP nonce. This is needs special treatment because it doesn't have 271 * an ASN1 encoding at all: it just contains arbitrary data. 272 */ 273 274 static void * 275 ocsp_nonce_new(void) 276 { 277 return ASN1_OCTET_STRING_new(); 278 } 279 280 static int 281 i2d_ocsp_nonce(void *a, unsigned char **pp) 282 { 283 ASN1_OCTET_STRING *os = a; 284 285 if (pp) { 286 memcpy(*pp, os->data, os->length); 287 *pp += os->length; 288 } 289 return os->length; 290 } 291 292 static void * 293 d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) 294 { 295 ASN1_OCTET_STRING *os, **pos; 296 297 pos = a; 298 if (pos == NULL || *pos == NULL) { 299 os = ASN1_OCTET_STRING_new(); 300 if (os == NULL) 301 goto err; 302 } else 303 os = *pos; 304 if (ASN1_OCTET_STRING_set(os, *pp, length) == 0) 305 goto err; 306 307 *pp += length; 308 309 if (pos != NULL) 310 *pos = os; 311 return os; 312 313 err: 314 if (pos == NULL || *pos != os) 315 ASN1_OCTET_STRING_free(os); 316 OCSPerror(ERR_R_MALLOC_FAILURE); 317 return NULL; 318 } 319 320 static void 321 ocsp_nonce_free(void *a) 322 { 323 ASN1_OCTET_STRING_free(a); 324 } 325 326 static int 327 i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, 328 int indent) 329 { 330 if (BIO_printf(out, "%*s", indent, "") <= 0) 331 return 0; 332 if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) 333 return 0; 334 return 1; 335 } 336 337 /* Nocheck is just a single NULL. Don't print anything and always set it */ 338 339 static int 340 i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, BIO *out, 341 int indent) 342 { 343 return 1; 344 } 345 346 static void * 347 s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 348 const char *str) 349 { 350 return ASN1_NULL_new(); 351 } 352 353 static int 354 i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) 355 { 356 int i; 357 OCSP_SERVICELOC *a = in; 358 ACCESS_DESCRIPTION *ad; 359 360 if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) 361 goto err; 362 if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) 363 goto err; 364 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { 365 ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); 366 if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) 367 goto err; 368 if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) 369 goto err; 370 if (BIO_puts(bp, " - ") <= 0) 371 goto err; 372 if (GENERAL_NAME_print(bp, ad->location) <= 0) 373 goto err; 374 } 375 return 1; 376 377 err: 378 return 0; 379 } 380 #endif 381