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