ocsp_ext.c revision 280304
1/* ocsp_ext.c */ 2/* 3 * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 4 * project. 5 */ 6 7/* 8 * History: This file was transfered to Richard Levitte from CertCo by Kathy 9 * Weinhold in mid-spring 2000 to be included in OpenSSL or released as a 10 * patch kit. 11 */ 12 13/* ==================================================================== 14 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in 25 * the documentation and/or other materials provided with the 26 * distribution. 27 * 28 * 3. All advertising materials mentioning features or use of this 29 * software must display the following acknowledgment: 30 * "This product includes software developed by the OpenSSL Project 31 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 32 * 33 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 34 * endorse or promote products derived from this software without 35 * prior written permission. For written permission, please contact 36 * openssl-core@openssl.org. 37 * 38 * 5. Products derived from this software may not be called "OpenSSL" 39 * nor may "OpenSSL" appear in their names without prior written 40 * permission of the OpenSSL Project. 41 * 42 * 6. Redistributions of any form whatsoever must retain the following 43 * acknowledgment: 44 * "This product includes software developed by the OpenSSL Project 45 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 48 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 51 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 58 * OF THE POSSIBILITY OF SUCH DAMAGE. 59 * ==================================================================== 60 * 61 * This product includes cryptographic software written by Eric Young 62 * (eay@cryptsoft.com). This product includes software written by Tim 63 * Hudson (tjh@cryptsoft.com). 64 * 65 */ 66 67#include <stdio.h> 68#include <cryptlib.h> 69#include <openssl/objects.h> 70#include <openssl/x509.h> 71#include <openssl/ocsp.h> 72#include <openssl/rand.h> 73#include <openssl/x509v3.h> 74 75/* Standard wrapper functions for extensions */ 76 77/* OCSP request extensions */ 78 79int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) 80{ 81 return (X509v3_get_ext_count(x->tbsRequest->requestExtensions)); 82} 83 84int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos) 85{ 86 return (X509v3_get_ext_by_NID 87 (x->tbsRequest->requestExtensions, nid, lastpos)); 88} 89 90int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, 91 int lastpos) 92{ 93 return (X509v3_get_ext_by_OBJ 94 (x->tbsRequest->requestExtensions, obj, lastpos)); 95} 96 97int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos) 98{ 99 return (X509v3_get_ext_by_critical 100 (x->tbsRequest->requestExtensions, crit, lastpos)); 101} 102 103X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) 104{ 105 return (X509v3_get_ext(x->tbsRequest->requestExtensions, loc)); 106} 107 108X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) 109{ 110 return (X509v3_delete_ext(x->tbsRequest->requestExtensions, loc)); 111} 112 113void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx) 114{ 115 return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx); 116} 117 118int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, 119 unsigned long flags) 120{ 121 return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, 122 crit, flags); 123} 124 125int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc) 126{ 127 return (X509v3_add_ext(&(x->tbsRequest->requestExtensions), ex, loc) != 128 NULL); 129} 130 131/* Single extensions */ 132 133int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) 134{ 135 return (X509v3_get_ext_count(x->singleRequestExtensions)); 136} 137 138int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos) 139{ 140 return (X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos)); 141} 142 143int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos) 144{ 145 return (X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos)); 146} 147 148int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos) 149{ 150 return (X509v3_get_ext_by_critical 151 (x->singleRequestExtensions, crit, lastpos)); 152} 153 154X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) 155{ 156 return (X509v3_get_ext(x->singleRequestExtensions, loc)); 157} 158 159X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) 160{ 161 return (X509v3_delete_ext(x->singleRequestExtensions, loc)); 162} 163 164void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx) 165{ 166 return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx); 167} 168 169int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, 170 unsigned long flags) 171{ 172 return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, 173 flags); 174} 175 176int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc) 177{ 178 return (X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL); 179} 180 181/* OCSP Basic response */ 182 183int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) 184{ 185 return (X509v3_get_ext_count(x->tbsResponseData->responseExtensions)); 186} 187 188int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos) 189{ 190 return (X509v3_get_ext_by_NID 191 (x->tbsResponseData->responseExtensions, nid, lastpos)); 192} 193 194int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, 195 int lastpos) 196{ 197 return (X509v3_get_ext_by_OBJ 198 (x->tbsResponseData->responseExtensions, obj, lastpos)); 199} 200 201int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, 202 int lastpos) 203{ 204 return (X509v3_get_ext_by_critical 205 (x->tbsResponseData->responseExtensions, crit, lastpos)); 206} 207 208X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) 209{ 210 return (X509v3_get_ext(x->tbsResponseData->responseExtensions, loc)); 211} 212 213X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) 214{ 215 return (X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc)); 216} 217 218void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, 219 int *idx) 220{ 221 return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, 222 idx); 223} 224 225int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, 226 int crit, unsigned long flags) 227{ 228 return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, 229 value, crit, flags); 230} 231 232int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc) 233{ 234 return (X509v3_add_ext(&(x->tbsResponseData->responseExtensions), ex, loc) 235 != NULL); 236} 237 238/* OCSP single response extensions */ 239 240int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) 241{ 242 return (X509v3_get_ext_count(x->singleExtensions)); 243} 244 245int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos) 246{ 247 return (X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos)); 248} 249 250int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, 251 int lastpos) 252{ 253 return (X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos)); 254} 255 256int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, 257 int lastpos) 258{ 259 return (X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos)); 260} 261 262X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) 263{ 264 return (X509v3_get_ext(x->singleExtensions, loc)); 265} 266 267X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) 268{ 269 return (X509v3_delete_ext(x->singleExtensions, loc)); 270} 271 272void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, 273 int *idx) 274{ 275 return X509V3_get_d2i(x->singleExtensions, nid, crit, idx); 276} 277 278int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, 279 int crit, unsigned long flags) 280{ 281 return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags); 282} 283 284int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc) 285{ 286 return (X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL); 287} 288 289/* also CRL Entry Extensions */ 290#if 0 291ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d, 292 void *data, STACK_OF(ASN1_OBJECT) *sk) 293{ 294 int i; 295 unsigned char *p, *b = NULL; 296 297 if (data) { 298 if ((i = i2d(data, NULL)) <= 0) 299 goto err; 300 if (!(b = p = OPENSSL_malloc((unsigned int)i))) 301 goto err; 302 if (i2d(data, &p) <= 0) 303 goto err; 304 } else if (sk) { 305 if ((i = i2d_ASN1_SET_OF_ASN1_OBJECT(sk, NULL, 306 (I2D_OF(ASN1_OBJECT)) i2d, 307 V_ASN1_SEQUENCE, 308 V_ASN1_UNIVERSAL, 309 IS_SEQUENCE)) <= 0) 310 goto err; 311 if (!(b = p = OPENSSL_malloc((unsigned int)i))) 312 goto err; 313 if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk, &p, (I2D_OF(ASN1_OBJECT)) i2d, 314 V_ASN1_SEQUENCE, 315 V_ASN1_UNIVERSAL, IS_SEQUENCE) <= 0) 316 goto err; 317 } else { 318 OCSPerr(OCSP_F_ASN1_STRING_ENCODE, OCSP_R_BAD_DATA); 319 goto err; 320 } 321 if (!s && !(s = ASN1_STRING_new())) 322 goto err; 323 if (!(ASN1_STRING_set(s, b, i))) 324 goto err; 325 OPENSSL_free(b); 326 return s; 327 err: 328 if (b) 329 OPENSSL_free(b); 330 return NULL; 331} 332#endif 333 334/* Nonce handling functions */ 335 336/* 337 * Add a nonce to an extension stack. A nonce can be specificed or if NULL a 338 * random nonce will be generated. Note: OpenSSL 0.9.7d and later create an 339 * OCTET STRING containing the nonce, previous versions used the raw nonce. 340 */ 341 342static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, 343 unsigned char *val, int len) 344{ 345 unsigned char *tmpval; 346 ASN1_OCTET_STRING os; 347 int ret = 0; 348 if (len <= 0) 349 len = OCSP_DEFAULT_NONCE_LENGTH; 350 /* 351 * Create the OCTET STRING manually by writing out the header and 352 * appending the content octets. This avoids an extra memory allocation 353 * operation in some cases. Applications should *NOT* do this because it 354 * relies on library internals. 355 */ 356 os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING); 357 os.data = OPENSSL_malloc(os.length); 358 if (os.data == NULL) 359 goto err; 360 tmpval = os.data; 361 ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); 362 if (val) 363 memcpy(tmpval, val, len); 364 else 365 RAND_pseudo_bytes(tmpval, len); 366 if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, 367 &os, 0, X509V3_ADD_REPLACE)) 368 goto err; 369 ret = 1; 370 err: 371 if (os.data) 372 OPENSSL_free(os.data); 373 return ret; 374} 375 376/* Add nonce to an OCSP request */ 377 378int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) 379{ 380 return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len); 381} 382 383/* Same as above but for a response */ 384 385int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) 386{ 387 return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, 388 len); 389} 390 391/*- 392 * Check nonce validity in a request and response. 393 * Return value reflects result: 394 * 1: nonces present and equal. 395 * 2: nonces both absent. 396 * 3: nonce present in response only. 397 * 0: nonces both present and not equal. 398 * -1: nonce in request only. 399 * 400 * For most responders clients can check return > 0. 401 * If responder doesn't handle nonces return != 0 may be 402 * necessary. return == 0 is always an error. 403 */ 404 405int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) 406{ 407 /* 408 * Since we are only interested in the presence or absence of 409 * the nonce and comparing its value there is no need to use 410 * the X509V3 routines: this way we can avoid them allocating an 411 * ASN1_OCTET_STRING structure for the value which would be 412 * freed immediately anyway. 413 */ 414 415 int req_idx, resp_idx; 416 X509_EXTENSION *req_ext, *resp_ext; 417 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 418 resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1); 419 /* Check both absent */ 420 if ((req_idx < 0) && (resp_idx < 0)) 421 return 2; 422 /* Check in request only */ 423 if ((req_idx >= 0) && (resp_idx < 0)) 424 return -1; 425 /* Check in response but not request */ 426 if ((req_idx < 0) && (resp_idx >= 0)) 427 return 3; 428 /* 429 * Otherwise nonce in request and response so retrieve the extensions 430 */ 431 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 432 resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); 433 if (ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) 434 return 0; 435 return 1; 436} 437 438/* 439 * Copy the nonce value (if any) from an OCSP request to a response. 440 */ 441 442int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) 443{ 444 X509_EXTENSION *req_ext; 445 int req_idx; 446 /* Check for nonce in request */ 447 req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 448 /* If no nonce that's OK */ 449 if (req_idx < 0) 450 return 2; 451 req_ext = OCSP_REQUEST_get_ext(req, req_idx); 452 return OCSP_BASICRESP_add_ext(resp, req_ext, -1); 453} 454 455X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim) 456{ 457 X509_EXTENSION *x = NULL; 458 OCSP_CRLID *cid = NULL; 459 460 if (!(cid = OCSP_CRLID_new())) 461 goto err; 462 if (url) { 463 if (!(cid->crlUrl = ASN1_IA5STRING_new())) 464 goto err; 465 if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) 466 goto err; 467 } 468 if (n) { 469 if (!(cid->crlNum = ASN1_INTEGER_new())) 470 goto err; 471 if (!(ASN1_INTEGER_set(cid->crlNum, *n))) 472 goto err; 473 } 474 if (tim) { 475 if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) 476 goto err; 477 if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) 478 goto err; 479 } 480 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid); 481 err: 482 if (cid) 483 OCSP_CRLID_free(cid); 484 return x; 485} 486 487/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ 488X509_EXTENSION *OCSP_accept_responses_new(char **oids) 489{ 490 int nid; 491 STACK_OF(ASN1_OBJECT) *sk = NULL; 492 ASN1_OBJECT *o = NULL; 493 X509_EXTENSION *x = NULL; 494 495 if (!(sk = sk_ASN1_OBJECT_new_null())) 496 goto err; 497 while (oids && *oids) { 498 if ((nid = OBJ_txt2nid(*oids)) != NID_undef && (o = OBJ_nid2obj(nid))) 499 sk_ASN1_OBJECT_push(sk, o); 500 oids++; 501 } 502 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); 503 err: 504 if (sk) 505 sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); 506 return x; 507} 508 509/* ArchiveCutoff ::= GeneralizedTime */ 510X509_EXTENSION *OCSP_archive_cutoff_new(char *tim) 511{ 512 X509_EXTENSION *x = NULL; 513 ASN1_GENERALIZEDTIME *gt = NULL; 514 515 if (!(gt = ASN1_GENERALIZEDTIME_new())) 516 goto err; 517 if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) 518 goto err; 519 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt); 520 err: 521 if (gt) 522 ASN1_GENERALIZEDTIME_free(gt); 523 return x; 524} 525 526/* 527 * per ACCESS_DESCRIPTION parameter are oids, of which there are currently 528 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This method 529 * forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. 530 */ 531X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, char **urls) 532{ 533 X509_EXTENSION *x = NULL; 534 ASN1_IA5STRING *ia5 = NULL; 535 OCSP_SERVICELOC *sloc = NULL; 536 ACCESS_DESCRIPTION *ad = NULL; 537 538 if (!(sloc = OCSP_SERVICELOC_new())) 539 goto err; 540 if (!(sloc->issuer = X509_NAME_dup(issuer))) 541 goto err; 542 if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) 543 goto err; 544 while (urls && *urls) { 545 if (!(ad = ACCESS_DESCRIPTION_new())) 546 goto err; 547 if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP))) 548 goto err; 549 if (!(ad->location = GENERAL_NAME_new())) 550 goto err; 551 if (!(ia5 = ASN1_IA5STRING_new())) 552 goto err; 553 if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1)) 554 goto err; 555 ad->location->type = GEN_URI; 556 ad->location->d.ia5 = ia5; 557 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) 558 goto err; 559 urls++; 560 } 561 x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc); 562 err: 563 if (sloc) 564 OCSP_SERVICELOC_free(sloc); 565 return x; 566} 567