ocsp_ext.c revision 1.11
1/* $OpenBSD: ocsp_ext.c,v 1.11 2014/07/11 08:44:49 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 <string.h> 66 67#include <openssl/objects.h> 68#include <openssl/ocsp.h> 69#include <openssl/rand.h> 70#include <openssl/x509.h> 71#include <openssl/x509v3.h> 72 73/* Standard wrapper functions for extensions */ 74 75/* OCSP request extensions */ 76 77int 78OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) 79{ 80 return X509v3_get_ext_count(x->tbsRequest->requestExtensions); 81} 82 83int 84OCSP_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 90int 91OCSP_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 97int 98OCSP_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 104X509_EXTENSION * 105OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) 106{ 107 return X509v3_get_ext(x->tbsRequest->requestExtensions, loc); 108} 109 110X509_EXTENSION * 111OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) 112{ 113 return X509v3_delete_ext(x->tbsRequest->requestExtensions, loc); 114} 115 116void * 117OCSP_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 122int 123OCSP_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 130int 131OCSP_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 139int 140OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) 141{ 142 return X509v3_get_ext_count(x->singleRequestExtensions); 143} 144 145int 146OCSP_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 151int 152OCSP_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 157int 158OCSP_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 164X509_EXTENSION * 165OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) 166{ 167 return X509v3_get_ext(x->singleRequestExtensions, loc); 168} 169 170X509_EXTENSION * 171OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) 172{ 173 return X509v3_delete_ext(x->singleRequestExtensions, loc); 174} 175 176void * 177OCSP_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 182int 183OCSP_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 190int 191OCSP_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 198int 199OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) 200{ 201 return X509v3_get_ext_count(x->tbsResponseData->responseExtensions); 202} 203 204int 205OCSP_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 211int 212OCSP_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 218int 219OCSP_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 225X509_EXTENSION * 226OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) 227{ 228 return X509v3_get_ext(x->tbsResponseData->responseExtensions, loc); 229} 230 231X509_EXTENSION * 232OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) 233{ 234 return X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc); 235} 236 237void * 238OCSP_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 244int 245OCSP_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 252int 253OCSP_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 261int 262OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) 263{ 264 return X509v3_get_ext_count(x->singleExtensions); 265} 266 267int 268OCSP_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 273int 274OCSP_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 280int 281OCSP_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 286X509_EXTENSION * 287OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) 288{ 289 return X509v3_get_ext(x->singleExtensions, loc); 290} 291 292X509_EXTENSION * 293OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) 294{ 295 return X509v3_delete_ext(x->singleExtensions, loc); 296} 297 298void * 299OCSP_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 304int 305OCSP_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 311int 312OCSP_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 319ASN1_STRING * 320ASN1_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((unsigned int)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((unsigned int)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 355err: 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 369static int 370ocsp_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 RAND_pseudo_bytes(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 398err: 399 free(os.data); 400 return ret; 401} 402 403/* Add nonce to an OCSP request */ 404int 405OCSP_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 */ 411int 412OCSP_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 */ 430int 431OCSP_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 */ 466int 467OCSP_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 481X509_EXTENSION * 482OCSP_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 509err: 510 if (cid) 511 OCSP_CRLID_free(cid); 512 return x; 513} 514 515/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 516X509_EXTENSION * 517OCSP_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 sk_ASN1_OBJECT_push(sk, o); 530 oids++; 531 } 532 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); 533 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 534 return x; 535} 536 537/* ArchiveCutoff ::= GeneralizedTime */ 538X509_EXTENSION * 539OCSP_archive_cutoff_new(char* tim) 540{ 541 X509_EXTENSION *x = NULL; 542 ASN1_GENERALIZEDTIME *gt = NULL; 543 544 if (!(gt = ASN1_GENERALIZEDTIME_new())) 545 return NULL; 546 if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) 547 goto err; 548 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); 549 550err: 551 if (gt) 552 ASN1_GENERALIZEDTIME_free(gt); 553 return x; 554} 555 556/* per ACCESS_DESCRIPTION parameter are oids, of which there are currently 557 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This 558 * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. 559 */ 560X509_EXTENSION * 561OCSP_url_svcloc_new(X509_NAME* issuer, char **urls) 562{ 563 X509_EXTENSION *x = NULL; 564 ASN1_IA5STRING *ia5 = NULL; 565 OCSP_SERVICELOC *sloc = NULL; 566 ACCESS_DESCRIPTION *ad = NULL; 567 568 if (!(sloc = OCSP_SERVICELOC_new())) 569 goto err; 570 if (!(sloc->issuer = X509_NAME_dup(issuer))) 571 goto err; 572 if (urls && *urls && 573 !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) 574 goto err; 575 while (urls && *urls) { 576 if (!(ad = ACCESS_DESCRIPTION_new())) 577 goto err; 578 if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP))) 579 goto err; 580 if (!(ad->location = GENERAL_NAME_new())) 581 goto err; 582 if (!(ia5 = ASN1_IA5STRING_new())) 583 goto err; 584 if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) 585 goto err; 586 ad->location->type = GEN_URI; 587 ad->location->d.ia5 = ia5; 588 ia5 = NULL; 589 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) 590 goto err; 591 ad = NULL; 592 urls++; 593 } 594 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); 595 596err: 597 if (ia5) 598 ASN1_IA5STRING_free(ia5); 599 if (ad) 600 ACCESS_DESCRIPTION_free(ad); 601 if (sloc) 602 OCSP_SERVICELOC_free(sloc); 603 return x; 604} 605