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