1 /* $OpenBSD: ocsp_ext.c,v 1.10 2014/07/10 13:58:23 jsing 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 <cryptlib.h> 65 #include <stdio.h> 66 #include <string.h> 67 68 #include <openssl/objects.h> 69 #include <openssl/x509.h> 70 #include <openssl/ocsp.h> 71 #include <openssl/rand.h> 72 #include <openssl/x509v3.h> 73 74 /* Standard wrapper functions for extensions */ 75 76 /* OCSP request extensions */ 77 78 int 79 OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) 80 { 81 return X509v3_get_ext_count(x->tbsRequest->requestExtensions); 82 } 83 84 int 85 OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos) 86 { 87 return X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions, nid, 88 lastpos); 89 } 90 91 int 92 OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, 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, 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, ASN1_OBJECT *obj, int lastpos) 214 { 215 return X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions, 216 obj, lastpos); 217 } 218 219 int 220 OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos) 221 { 222 return X509v3_get_ext_by_critical( 223 x->tbsResponseData->responseExtensions, crit, lastpos); 224 } 225 226 X509_EXTENSION * 227 OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) 228 { 229 return X509v3_get_ext(x->tbsResponseData->responseExtensions, loc); 230 } 231 232 X509_EXTENSION * 233 OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) 234 { 235 return X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc); 236 } 237 238 void * 239 OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx) 240 { 241 return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, 242 crit, idx); 243 } 244 245 int 246 OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit, 247 unsigned long flags) 248 { 249 return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, 250 value, crit, flags); 251 } 252 253 int 254 OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc) 255 { 256 return X509v3_add_ext(&(x->tbsResponseData->responseExtensions), ex, 257 loc) != NULL; 258 } 259 260 /* OCSP single response extensions */ 261 262 int 263 OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) 264 { 265 return X509v3_get_ext_count(x->singleExtensions); 266 } 267 268 int 269 OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos) 270 { 271 return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos); 272 } 273 274 int 275 OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, 276 int lastpos) 277 { 278 return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos); 279 } 280 281 int 282 OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos) 283 { 284 return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos); 285 } 286 287 X509_EXTENSION * 288 OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) 289 { 290 return X509v3_get_ext(x->singleExtensions, loc); 291 } 292 293 X509_EXTENSION * 294 OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) 295 { 296 return X509v3_delete_ext(x->singleExtensions, loc); 297 } 298 299 void * 300 OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx) 301 { 302 return X509V3_get_d2i(x->singleExtensions, nid, crit, idx); 303 } 304 305 int 306 OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit, 307 unsigned long flags) 308 { 309 return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags); 310 } 311 312 int 313 OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc) 314 { 315 return X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL; 316 } 317 318 /* also CRL Entry Extensions */ 319 #if 0 320 ASN1_STRING * 321 ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d, void *data, 322 STACK_OF(ASN1_OBJECT) *sk) 323 { 324 int i; 325 unsigned char *p, *b = NULL; 326 327 if (data) { 328 if ((i = i2d(data, NULL)) <= 0) 329 goto err; 330 if (!(b = p = malloc((unsigned int)i))) 331 goto err; 332 if (i2d(data, &p) <= 0) 333 goto err; 334 } else if (sk) { 335 if ((i = i2d_ASN1_SET_OF_ASN1_OBJECT(sk, NULL, 336 (I2D_OF(ASN1_OBJECT))i2d, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 337 IS_SEQUENCE)) <= 0) 338 goto err; 339 if (!(b = p = malloc((unsigned int)i))) 340 goto err; 341 if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk, &p, 342 (I2D_OF(ASN1_OBJECT))i2d, V_ASN1_SEQUENCE, 343 V_ASN1_UNIVERSAL, IS_SEQUENCE) <= 0) 344 goto err; 345 } else { 346 OCSPerr(OCSP_F_ASN1_STRING_ENCODE, OCSP_R_BAD_DATA); 347 goto err; 348 } 349 if (!s && !(s = ASN1_STRING_new())) 350 goto err; 351 if (!(ASN1_STRING_set(s, b, i))) 352 goto err; 353 free(b); 354 return s; 355 356 err: 357 free(b); 358 return NULL; 359 } 360 #endif 361 362 /* Nonce handling functions */ 363 364 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL 365 * a random nonce will be generated. 366 * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the 367 * nonce, previous versions used the raw nonce. 368 */ 369 370 static int 371 ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len) 372 { 373 unsigned char *tmpval; 374 ASN1_OCTET_STRING os; 375 int ret = 0; 376 377 if (len <= 0) 378 len = OCSP_DEFAULT_NONCE_LENGTH; 379 /* Create the OCTET STRING manually by writing out the header and 380 * appending the content octets. This avoids an extra memory allocation 381 * operation in some cases. Applications should *NOT* do this because 382 * it relies on library internals. 383 */ 384 os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING); 385 os.data = malloc(os.length); 386 if (os.data == NULL) 387 goto err; 388 tmpval = os.data; 389 ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); 390 if (val) 391 memcpy(tmpval, val, len); 392 else 393 RAND_pseudo_bytes(tmpval, len); 394 if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, &os, 0, 395 X509V3_ADD_REPLACE)) 396 goto err; 397 ret = 1; 398 399 err: 400 free(os.data); 401 return ret; 402 } 403 404 /* Add nonce to an OCSP request */ 405 int 406 OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) 407 { 408 return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len); 409 } 410 411 /* Same as above but for a response */ 412 int 413 OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) 414 { 415 return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, 416 len); 417 } 418 419 /* Check nonce validity in a request and response. 420 * Return value reflects result: 421 * 1: nonces present and equal. 422 * 2: nonces both absent. 423 * 3: nonce present in response only. 424 * 0: nonces both present and not equal. 425 * -1: nonce in request only. 426 * 427 * For most responders clients can check return > 0. 428 * If responder doesn't handle nonces return != 0 may be 429 * necessary. return == 0 is always an error. 430 */ 431 int 432 OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) 433 { 434 /* 435 * Since we are only interested in the presence or absence of 436 * the nonce and comparing its value there is no need to use 437 * the X509V3 routines: this way we can avoid them allocating an 438 * ASN1_OCTET_STRING structure for the value which would be 439 * freed immediately anyway. 440 */ 441 int req_idx, resp_idx; 442 X509_EXTENSION *req_ext, *resp_ext; 443 444 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 445 resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, 446 NID_id_pkix_OCSP_Nonce, -1); 447 /* Check both absent */ 448 if (req_idx < 0 && resp_idx < 0) 449 return 2; 450 /* Check in request only */ 451 if (req_idx >= 0 && resp_idx < 0) 452 return -1; 453 /* Check in response but not request */ 454 if (req_idx < 0 && resp_idx >= 0) 455 return 3; 456 /* Otherwise nonce in request and response so retrieve the extensions */ 457 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 458 resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); 459 if (ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) 460 return 0; 461 return 1; 462 } 463 464 /* Copy the nonce value (if any) from an OCSP request to 465 * a response. 466 */ 467 int 468 OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) 469 { 470 X509_EXTENSION *req_ext; 471 int req_idx; 472 473 /* Check for nonce in request */ 474 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 475 /* If no nonce that's OK */ 476 if (req_idx < 0) 477 return 2; 478 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 479 return OCSP_BASICRESP_add_ext(resp, req_ext, -1); 480 } 481 482 X509_EXTENSION * 483 OCSP_crlID_new(char *url, long *n, char *tim) 484 { 485 X509_EXTENSION *x = NULL; 486 OCSP_CRLID *cid = NULL; 487 488 if (!(cid = OCSP_CRLID_new())) 489 goto err; 490 if (url) { 491 if (!(cid->crlUrl = ASN1_IA5STRING_new())) 492 goto err; 493 if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) 494 goto err; 495 } 496 if (n) { 497 if (!(cid->crlNum = ASN1_INTEGER_new())) 498 goto err; 499 if (!(ASN1_INTEGER_set(cid->crlNum, *n))) 500 goto err; 501 } 502 if (tim) { 503 if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) 504 goto err; 505 if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) 506 goto err; 507 } 508 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid); 509 510 err: 511 if (cid) 512 OCSP_CRLID_free(cid); 513 return x; 514 } 515 516 /* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 517 X509_EXTENSION * 518 OCSP_accept_responses_new(char **oids) 519 { 520 int nid; 521 STACK_OF(ASN1_OBJECT) *sk = NULL; 522 ASN1_OBJECT *o = NULL; 523 X509_EXTENSION *x = NULL; 524 525 if (!(sk = sk_ASN1_OBJECT_new_null())) 526 return NULL; 527 while (oids && *oids) { 528 if ((nid = OBJ_txt2nid(*oids)) != NID_undef && 529 (o = OBJ_nid2obj(nid))) 530 sk_ASN1_OBJECT_push(sk, o); 531 oids++; 532 } 533 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); 534 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 535 return x; 536 } 537 538 /* ArchiveCutoff ::= GeneralizedTime */ 539 X509_EXTENSION * 540 OCSP_archive_cutoff_new(char* tim) 541 { 542 X509_EXTENSION *x = NULL; 543 ASN1_GENERALIZEDTIME *gt = NULL; 544 545 if (!(gt = ASN1_GENERALIZEDTIME_new())) 546 return NULL; 547 if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) 548 goto err; 549 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); 550 551 err: 552 if (gt) 553 ASN1_GENERALIZEDTIME_free(gt); 554 return x; 555 } 556 557 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently 558 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This 559 * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. 560 */ 561 X509_EXTENSION * 562 OCSP_url_svcloc_new(X509_NAME* issuer, char **urls) 563 { 564 X509_EXTENSION *x = NULL; 565 ASN1_IA5STRING *ia5 = NULL; 566 OCSP_SERVICELOC *sloc = NULL; 567 ACCESS_DESCRIPTION *ad = NULL; 568 569 if (!(sloc = OCSP_SERVICELOC_new())) 570 goto err; 571 if (!(sloc->issuer = X509_NAME_dup(issuer))) 572 goto err; 573 if (urls && *urls && 574 !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) 575 goto err; 576 while (urls && *urls) { 577 if (!(ad = ACCESS_DESCRIPTION_new())) 578 goto err; 579 if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP))) 580 goto err; 581 if (!(ad->location = GENERAL_NAME_new())) 582 goto err; 583 if (!(ia5 = ASN1_IA5STRING_new())) 584 goto err; 585 if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) 586 goto err; 587 ad->location->type = GEN_URI; 588 ad->location->d.ia5 = ia5; 589 ia5 = NULL; 590 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) 591 goto err; 592 ad = NULL; 593 urls++; 594 } 595 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); 596 597 err: 598 if (ia5) 599 ASN1_IA5STRING_free(ia5); 600 if (ad) 601 ACCESS_DESCRIPTION_free(ad); 602 if (sloc) 603 OCSP_SERVICELOC_free(sloc); 604 return x; 605 } 606