ocsp_ext.c revision 1.21
1/* $OpenBSD: ocsp_ext.c,v 1.21 2022/11/26 16:08:53 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_local.h" 75 76/* Standard wrapper functions for extensions */ 77 78/* OCSP request extensions */ 79 80int 81OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) 82{ 83 return X509v3_get_ext_count(x->tbsRequest->requestExtensions); 84} 85 86int 87OCSP_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 93int 94OCSP_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 101int 102OCSP_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 108X509_EXTENSION * 109OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) 110{ 111 return X509v3_get_ext(x->tbsRequest->requestExtensions, loc); 112} 113 114X509_EXTENSION * 115OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) 116{ 117 return X509v3_delete_ext(x->tbsRequest->requestExtensions, loc); 118} 119 120void * 121OCSP_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 126int 127OCSP_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 134int 135OCSP_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 143int 144OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) 145{ 146 return X509v3_get_ext_count(x->singleRequestExtensions); 147} 148 149int 150OCSP_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 155int 156OCSP_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 161int 162OCSP_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 168X509_EXTENSION * 169OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) 170{ 171 return X509v3_get_ext(x->singleRequestExtensions, loc); 172} 173 174X509_EXTENSION * 175OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) 176{ 177 return X509v3_delete_ext(x->singleRequestExtensions, loc); 178} 179 180void * 181OCSP_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 186int 187OCSP_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 194int 195OCSP_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 202int 203OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) 204{ 205 return X509v3_get_ext_count(x->tbsResponseData->responseExtensions); 206} 207 208int 209OCSP_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 215int 216OCSP_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 223int 224OCSP_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 230X509_EXTENSION * 231OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) 232{ 233 return X509v3_get_ext(x->tbsResponseData->responseExtensions, loc); 234} 235 236X509_EXTENSION * 237OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) 238{ 239 return X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc); 240} 241 242void * 243OCSP_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 249int 250OCSP_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 257int 258OCSP_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 266int 267OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) 268{ 269 return X509v3_get_ext_count(x->singleExtensions); 270} 271 272int 273OCSP_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 278int 279OCSP_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 285int 286OCSP_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 291X509_EXTENSION * 292OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) 293{ 294 return X509v3_get_ext(x->singleExtensions, loc); 295} 296 297X509_EXTENSION * 298OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) 299{ 300 return X509v3_delete_ext(x->singleExtensions, loc); 301} 302 303void * 304OCSP_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 309int 310OCSP_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 316int 317OCSP_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 330static int 331ocsp_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 359err: 360 free(os.data); 361 return ret; 362} 363 364/* Add nonce to an OCSP request */ 365int 366OCSP_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 */ 372int 373OCSP_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 */ 391int 392OCSP_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 */ 427int 428OCSP_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 442X509_EXTENSION * 443OCSP_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 470err: 471 if (cid) 472 OCSP_CRLID_free(cid); 473 return x; 474} 475 476/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 477X509_EXTENSION * 478OCSP_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 */ 502X509_EXTENSION * 503OCSP_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 514err: 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 */ 524X509_EXTENSION * 525OCSP_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 560err: 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