1 /* $OpenBSD: ocsp_ext.c,v 1.15 2016/12/27 16:01:19 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 <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 /* Nonce handling functions */ 318 319 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL 320 * a random nonce will be generated. 321 * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the 322 * nonce, previous versions used the raw nonce. 323 */ 324 325 static int 326 ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len) 327 { 328 unsigned char *tmpval; 329 ASN1_OCTET_STRING os; 330 int ret = 0; 331 332 if (len <= 0) 333 len = OCSP_DEFAULT_NONCE_LENGTH; 334 /* Create the OCTET STRING manually by writing out the header and 335 * appending the content octets. This avoids an extra memory allocation 336 * operation in some cases. Applications should *NOT* do this because 337 * it relies on library internals. 338 */ 339 os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING); 340 os.data = malloc(os.length); 341 if (os.data == NULL) 342 goto err; 343 tmpval = os.data; 344 ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); 345 if (val) 346 memcpy(tmpval, val, len); 347 else 348 arc4random_buf(tmpval, len); 349 if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, &os, 0, 350 X509V3_ADD_REPLACE)) 351 goto err; 352 ret = 1; 353 354 err: 355 free(os.data); 356 return ret; 357 } 358 359 /* Add nonce to an OCSP request */ 360 int 361 OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) 362 { 363 return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len); 364 } 365 366 /* Same as above but for a response */ 367 int 368 OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) 369 { 370 return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, 371 len); 372 } 373 374 /* Check nonce validity in a request and response. 375 * Return value reflects result: 376 * 1: nonces present and equal. 377 * 2: nonces both absent. 378 * 3: nonce present in response only. 379 * 0: nonces both present and not equal. 380 * -1: nonce in request only. 381 * 382 * For most responders clients can check return > 0. 383 * If responder doesn't handle nonces return != 0 may be 384 * necessary. return == 0 is always an error. 385 */ 386 int 387 OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) 388 { 389 /* 390 * Since we are only interested in the presence or absence of 391 * the nonce and comparing its value there is no need to use 392 * the X509V3 routines: this way we can avoid them allocating an 393 * ASN1_OCTET_STRING structure for the value which would be 394 * freed immediately anyway. 395 */ 396 int req_idx, resp_idx; 397 X509_EXTENSION *req_ext, *resp_ext; 398 399 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 400 resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, 401 NID_id_pkix_OCSP_Nonce, -1); 402 /* Check both absent */ 403 if (req_idx < 0 && resp_idx < 0) 404 return 2; 405 /* Check in request only */ 406 if (req_idx >= 0 && resp_idx < 0) 407 return -1; 408 /* Check in response but not request */ 409 if (req_idx < 0 && resp_idx >= 0) 410 return 3; 411 /* Otherwise nonce in request and response so retrieve the extensions */ 412 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 413 resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); 414 if (ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) 415 return 0; 416 return 1; 417 } 418 419 /* Copy the nonce value (if any) from an OCSP request to 420 * a response. 421 */ 422 int 423 OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) 424 { 425 X509_EXTENSION *req_ext; 426 int req_idx; 427 428 /* Check for nonce in request */ 429 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 430 /* If no nonce that's OK */ 431 if (req_idx < 0) 432 return 2; 433 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 434 return OCSP_BASICRESP_add_ext(resp, req_ext, -1); 435 } 436 437 X509_EXTENSION * 438 OCSP_crlID_new(char *url, long *n, char *tim) 439 { 440 X509_EXTENSION *x = NULL; 441 OCSP_CRLID *cid = NULL; 442 443 if (!(cid = OCSP_CRLID_new())) 444 goto err; 445 if (url) { 446 if (!(cid->crlUrl = ASN1_IA5STRING_new())) 447 goto err; 448 if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) 449 goto err; 450 } 451 if (n) { 452 if (!(cid->crlNum = ASN1_INTEGER_new())) 453 goto err; 454 if (!(ASN1_INTEGER_set(cid->crlNum, *n))) 455 goto err; 456 } 457 if (tim) { 458 if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) 459 goto err; 460 if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) 461 goto err; 462 } 463 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid); 464 465 err: 466 if (cid) 467 OCSP_CRLID_free(cid); 468 return x; 469 } 470 471 /* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 472 X509_EXTENSION * 473 OCSP_accept_responses_new(char **oids) 474 { 475 int nid; 476 STACK_OF(ASN1_OBJECT) *sk = NULL; 477 ASN1_OBJECT *o = NULL; 478 X509_EXTENSION *x = NULL; 479 480 if (!(sk = sk_ASN1_OBJECT_new_null())) 481 return NULL; 482 while (oids && *oids) { 483 if ((nid = OBJ_txt2nid(*oids)) != NID_undef && 484 (o = OBJ_nid2obj(nid))) 485 if (sk_ASN1_OBJECT_push(sk, o) == 0) { 486 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 487 return NULL; 488 } 489 oids++; 490 } 491 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); 492 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 493 return x; 494 } 495 496 /* ArchiveCutoff ::= GeneralizedTime */ 497 X509_EXTENSION * 498 OCSP_archive_cutoff_new(char* tim) 499 { 500 X509_EXTENSION *x = NULL; 501 ASN1_GENERALIZEDTIME *gt = NULL; 502 503 if (!(gt = ASN1_GENERALIZEDTIME_new())) 504 return NULL; 505 if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) 506 goto err; 507 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); 508 509 err: 510 if (gt) 511 ASN1_GENERALIZEDTIME_free(gt); 512 return x; 513 } 514 515 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently 516 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This 517 * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. 518 */ 519 X509_EXTENSION * 520 OCSP_url_svcloc_new(X509_NAME* issuer, char **urls) 521 { 522 X509_EXTENSION *x = NULL; 523 ASN1_IA5STRING *ia5 = NULL; 524 OCSP_SERVICELOC *sloc = NULL; 525 ACCESS_DESCRIPTION *ad = NULL; 526 527 if (!(sloc = OCSP_SERVICELOC_new())) 528 goto err; 529 if (!(sloc->issuer = X509_NAME_dup(issuer))) 530 goto err; 531 if (urls && *urls && 532 !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) 533 goto err; 534 while (urls && *urls) { 535 if (!(ad = ACCESS_DESCRIPTION_new())) 536 goto err; 537 if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP))) 538 goto err; 539 if (!(ad->location = GENERAL_NAME_new())) 540 goto err; 541 if (!(ia5 = ASN1_IA5STRING_new())) 542 goto err; 543 if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) 544 goto err; 545 ad->location->type = GEN_URI; 546 ad->location->d.ia5 = ia5; 547 ia5 = NULL; 548 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) 549 goto err; 550 ad = NULL; 551 urls++; 552 } 553 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); 554 555 err: 556 if (ia5) 557 ASN1_IA5STRING_free(ia5); 558 if (ad) 559 ACCESS_DESCRIPTION_free(ad); 560 if (sloc) 561 OCSP_SERVICELOC_free(sloc); 562 return x; 563 } 564