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