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