1 /* $OpenBSD: ocsp_ext.c,v 1.19 2021/11/01 20:53:08 tb Exp $ */ 2 /* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 3 * project. */ 4 5 /* History: 6 This file was transfered to Richard Levitte from CertCo by Kathy 7 Weinhold in mid-spring 2000 to be included in OpenSSL or released 8 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 <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 68 #include <openssl/objects.h> 69 #include <openssl/ocsp.h> 70 #include <openssl/x509.h> 71 #include <openssl/x509v3.h> 72 73 #include "x509_lcl.h" 74 75 /* Standard wrapper functions for extensions */ 76 77 /* OCSP request extensions */ 78 79 int 80 OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) 81 { 82 return X509v3_get_ext_count(x->tbsRequest->requestExtensions); 83 } 84 85 int 86 OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos) 87 { 88 return X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions, nid, 89 lastpos); 90 } 91 92 int 93 OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj, 94 int lastpos) 95 { 96 return X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions, obj, 97 lastpos); 98 } 99 100 int 101 OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos) 102 { 103 return X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions, 104 crit, lastpos); 105 } 106 107 X509_EXTENSION * 108 OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) 109 { 110 return X509v3_get_ext(x->tbsRequest->requestExtensions, loc); 111 } 112 113 X509_EXTENSION * 114 OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) 115 { 116 return X509v3_delete_ext(x->tbsRequest->requestExtensions, loc); 117 } 118 119 void * 120 OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx) 121 { 122 return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx); 123 } 124 125 int 126 OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, 127 unsigned long flags) 128 { 129 return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, 130 crit, flags); 131 } 132 133 int 134 OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc) 135 { 136 return X509v3_add_ext(&(x->tbsRequest->requestExtensions), ex, 137 loc) != NULL; 138 } 139 140 /* Single extensions */ 141 142 int 143 OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) 144 { 145 return X509v3_get_ext_count(x->singleRequestExtensions); 146 } 147 148 int 149 OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos) 150 { 151 return X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos); 152 } 153 154 int 155 OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos) 156 { 157 return X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos); 158 } 159 160 int 161 OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos) 162 { 163 return X509v3_get_ext_by_critical(x->singleRequestExtensions, crit, 164 lastpos); 165 } 166 167 X509_EXTENSION * 168 OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) 169 { 170 return X509v3_get_ext(x->singleRequestExtensions, loc); 171 } 172 173 X509_EXTENSION * 174 OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) 175 { 176 return X509v3_delete_ext(x->singleRequestExtensions, loc); 177 } 178 179 void * 180 OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx) 181 { 182 return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx); 183 } 184 185 int 186 OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, 187 unsigned long flags) 188 { 189 return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, 190 flags); 191 } 192 193 int 194 OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc) 195 { 196 return X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL; 197 } 198 199 /* OCSP Basic response */ 200 201 int 202 OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) 203 { 204 return X509v3_get_ext_count(x->tbsResponseData->responseExtensions); 205 } 206 207 int 208 OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos) 209 { 210 return X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions, 211 nid, lastpos); 212 } 213 214 int 215 OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj, 216 int lastpos) 217 { 218 return X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions, 219 obj, lastpos); 220 } 221 222 int 223 OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos) 224 { 225 return X509v3_get_ext_by_critical( 226 x->tbsResponseData->responseExtensions, crit, lastpos); 227 } 228 229 X509_EXTENSION * 230 OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) 231 { 232 return X509v3_get_ext(x->tbsResponseData->responseExtensions, loc); 233 } 234 235 X509_EXTENSION * 236 OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) 237 { 238 return X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc); 239 } 240 241 void * 242 OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx) 243 { 244 return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, 245 crit, idx); 246 } 247 248 int 249 OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit, 250 unsigned long flags) 251 { 252 return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, 253 value, crit, flags); 254 } 255 256 int 257 OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc) 258 { 259 return X509v3_add_ext(&(x->tbsResponseData->responseExtensions), ex, 260 loc) != NULL; 261 } 262 263 /* OCSP single response extensions */ 264 265 int 266 OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) 267 { 268 return X509v3_get_ext_count(x->singleExtensions); 269 } 270 271 int 272 OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos) 273 { 274 return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos); 275 } 276 277 int 278 OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj, 279 int lastpos) 280 { 281 return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos); 282 } 283 284 int 285 OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos) 286 { 287 return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos); 288 } 289 290 X509_EXTENSION * 291 OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) 292 { 293 return X509v3_get_ext(x->singleExtensions, loc); 294 } 295 296 X509_EXTENSION * 297 OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) 298 { 299 return X509v3_delete_ext(x->singleExtensions, loc); 300 } 301 302 void * 303 OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx) 304 { 305 return X509V3_get_d2i(x->singleExtensions, nid, crit, idx); 306 } 307 308 int 309 OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit, 310 unsigned long flags) 311 { 312 return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags); 313 } 314 315 int 316 OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc) 317 { 318 return X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL; 319 } 320 321 /* Nonce handling functions */ 322 323 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL 324 * a random nonce will be generated. 325 * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the 326 * nonce, previous versions used the raw nonce. 327 */ 328 329 static int 330 ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len) 331 { 332 unsigned char *tmpval; 333 ASN1_OCTET_STRING os; 334 int ret = 0; 335 336 if (len <= 0) 337 len = OCSP_DEFAULT_NONCE_LENGTH; 338 /* Create the OCTET STRING manually by writing out the header and 339 * appending the content octets. This avoids an extra memory allocation 340 * operation in some cases. Applications should *NOT* do this because 341 * it relies on library internals. 342 */ 343 os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING); 344 os.data = malloc(os.length); 345 if (os.data == NULL) 346 goto err; 347 tmpval = os.data; 348 ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); 349 if (val) 350 memcpy(tmpval, val, len); 351 else 352 arc4random_buf(tmpval, len); 353 if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, &os, 0, 354 X509V3_ADD_REPLACE)) 355 goto err; 356 ret = 1; 357 358 err: 359 free(os.data); 360 return ret; 361 } 362 363 /* Add nonce to an OCSP request */ 364 int 365 OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) 366 { 367 return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len); 368 } 369 370 /* Same as above but for a response */ 371 int 372 OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) 373 { 374 return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, 375 len); 376 } 377 378 /* Check nonce validity in a request and response. 379 * Return value reflects result: 380 * 1: nonces present and equal. 381 * 2: nonces both absent. 382 * 3: nonce present in response only. 383 * 0: nonces both present and not equal. 384 * -1: nonce in request only. 385 * 386 * For most responders clients can check return > 0. 387 * If responder doesn't handle nonces return != 0 may be 388 * necessary. return == 0 is always an error. 389 */ 390 int 391 OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) 392 { 393 /* 394 * Since we are only interested in the presence or absence of 395 * the nonce and comparing its value there is no need to use 396 * the X509V3 routines: this way we can avoid them allocating an 397 * ASN1_OCTET_STRING structure for the value which would be 398 * freed immediately anyway. 399 */ 400 int req_idx, resp_idx; 401 X509_EXTENSION *req_ext, *resp_ext; 402 403 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 404 resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, 405 NID_id_pkix_OCSP_Nonce, -1); 406 /* Check both absent */ 407 if (req_idx < 0 && resp_idx < 0) 408 return 2; 409 /* Check in request only */ 410 if (req_idx >= 0 && resp_idx < 0) 411 return -1; 412 /* Check in response but not request */ 413 if (req_idx < 0 && resp_idx >= 0) 414 return 3; 415 /* Otherwise nonce in request and response so retrieve the extensions */ 416 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 417 resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); 418 if (ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) 419 return 0; 420 return 1; 421 } 422 423 /* Copy the nonce value (if any) from an OCSP request to 424 * a response. 425 */ 426 int 427 OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) 428 { 429 X509_EXTENSION *req_ext; 430 int req_idx; 431 432 /* Check for nonce in request */ 433 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 434 /* If no nonce that's OK */ 435 if (req_idx < 0) 436 return 2; 437 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 438 return OCSP_BASICRESP_add_ext(resp, req_ext, -1); 439 } 440 441 X509_EXTENSION * 442 OCSP_crlID_new(const char *url, long *n, char *tim) 443 { 444 X509_EXTENSION *x = NULL; 445 OCSP_CRLID *cid = NULL; 446 447 if (!(cid = OCSP_CRLID_new())) 448 goto err; 449 if (url) { 450 if (!(cid->crlUrl = ASN1_IA5STRING_new())) 451 goto err; 452 if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) 453 goto err; 454 } 455 if (n) { 456 if (!(cid->crlNum = ASN1_INTEGER_new())) 457 goto err; 458 if (!(ASN1_INTEGER_set(cid->crlNum, *n))) 459 goto err; 460 } 461 if (tim) { 462 if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) 463 goto err; 464 if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) 465 goto err; 466 } 467 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid); 468 469 err: 470 if (cid) 471 OCSP_CRLID_free(cid); 472 return x; 473 } 474 475 /* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 476 X509_EXTENSION * 477 OCSP_accept_responses_new(char **oids) 478 { 479 int nid; 480 STACK_OF(ASN1_OBJECT) *sk = NULL; 481 ASN1_OBJECT *o = NULL; 482 X509_EXTENSION *x = NULL; 483 484 if (!(sk = sk_ASN1_OBJECT_new_null())) 485 return NULL; 486 while (oids && *oids) { 487 if ((nid = OBJ_txt2nid(*oids)) != NID_undef && 488 (o = OBJ_nid2obj(nid))) 489 if (sk_ASN1_OBJECT_push(sk, o) == 0) { 490 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 491 return NULL; 492 } 493 oids++; 494 } 495 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); 496 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 497 return x; 498 } 499 500 /* ArchiveCutoff ::= GeneralizedTime */ 501 X509_EXTENSION * 502 OCSP_archive_cutoff_new(char* tim) 503 { 504 X509_EXTENSION *x = NULL; 505 ASN1_GENERALIZEDTIME *gt = NULL; 506 507 if (!(gt = ASN1_GENERALIZEDTIME_new())) 508 return NULL; 509 if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) 510 goto err; 511 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); 512 513 err: 514 if (gt) 515 ASN1_GENERALIZEDTIME_free(gt); 516 return x; 517 } 518 519 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently 520 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This 521 * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. 522 */ 523 X509_EXTENSION * 524 OCSP_url_svcloc_new(X509_NAME* issuer, const char **urls) 525 { 526 X509_EXTENSION *x = NULL; 527 ASN1_IA5STRING *ia5 = NULL; 528 OCSP_SERVICELOC *sloc = NULL; 529 ACCESS_DESCRIPTION *ad = NULL; 530 531 if (!(sloc = OCSP_SERVICELOC_new())) 532 goto err; 533 if (!(sloc->issuer = X509_NAME_dup(issuer))) 534 goto err; 535 if (urls && *urls && 536 !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) 537 goto err; 538 while (urls && *urls) { 539 if (!(ad = ACCESS_DESCRIPTION_new())) 540 goto err; 541 if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP))) 542 goto err; 543 if (!(ad->location = GENERAL_NAME_new())) 544 goto err; 545 if (!(ia5 = ASN1_IA5STRING_new())) 546 goto err; 547 if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) 548 goto err; 549 ad->location->type = GEN_URI; 550 ad->location->d.ia5 = ia5; 551 ia5 = NULL; 552 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) 553 goto err; 554 ad = NULL; 555 urls++; 556 } 557 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); 558 559 err: 560 if (ia5) 561 ASN1_IA5STRING_free(ia5); 562 if (ad) 563 ACCESS_DESCRIPTION_free(ad); 564 if (sloc) 565 OCSP_SERVICELOC_free(sloc); 566 return x; 567 } 568