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