Home | History | Annotate | Download | only in ocsp
      1 /* ocsp_ext.c */
      2 /* Written by Tom Titchener <Tom_Titchener (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     60  * Hudson (tjh (at) cryptsoft.com).
     61  *
     62  */
     63 
     64 #include <stdio.h>
     65 #include <cryptlib.h>
     66 #include <openssl/objects.h>
     67 #include <openssl/x509.h>
     68 #include <openssl/ocsp.h>
     69 #include <openssl/rand.h>
     70 #include <openssl/x509v3.h>
     71 
     72 /* Standard wrapper functions for extensions */
     73 
     74 /* OCSP request extensions */
     75 
     76 int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
     77 	{
     78 	return(X509v3_get_ext_count(x->tbsRequest->requestExtensions));
     79 	}
     80 
     81 int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
     82 	{
     83 	return(X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions,nid,lastpos));
     84 	}
     85 
     86 int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos)
     87 	{
     88 	return(X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions,obj,lastpos));
     89 	}
     90 
     91 int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
     92 	{
     93 	return(X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,crit,lastpos));
     94 	}
     95 
     96 X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
     97 	{
     98 	return(X509v3_get_ext(x->tbsRequest->requestExtensions,loc));
     99 	}
    100 
    101 X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
    102 	{
    103 	return(X509v3_delete_ext(x->tbsRequest->requestExtensions,loc));
    104 	}
    105 
    106 void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
    107 	{
    108 	return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx);
    109 	}
    110 
    111 int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
    112 							unsigned long flags)
    113 	{
    114 	return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, crit, flags);
    115 	}
    116 
    117 int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
    118 	{
    119 	return(X509v3_add_ext(&(x->tbsRequest->requestExtensions),ex,loc) != NULL);
    120 	}
    121 
    122 /* Single extensions */
    123 
    124 int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
    125 	{
    126 	return(X509v3_get_ext_count(x->singleRequestExtensions));
    127 	}
    128 
    129 int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
    130 	{
    131 	return(X509v3_get_ext_by_NID(x->singleRequestExtensions,nid,lastpos));
    132 	}
    133 
    134 int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos)
    135 	{
    136 	return(X509v3_get_ext_by_OBJ(x->singleRequestExtensions,obj,lastpos));
    137 	}
    138 
    139 int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
    140 	{
    141 	return(X509v3_get_ext_by_critical(x->singleRequestExtensions,crit,lastpos));
    142 	}
    143 
    144 X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
    145 	{
    146 	return(X509v3_get_ext(x->singleRequestExtensions,loc));
    147 	}
    148 
    149 X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
    150 	{
    151 	return(X509v3_delete_ext(x->singleRequestExtensions,loc));
    152 	}
    153 
    154 void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
    155 	{
    156 	return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
    157 	}
    158 
    159 int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
    160 							unsigned long flags)
    161 	{
    162 	return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, flags);
    163 	}
    164 
    165 int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
    166 	{
    167 	return(X509v3_add_ext(&(x->singleRequestExtensions),ex,loc) != NULL);
    168 	}
    169 
    170 /* OCSP Basic response */
    171 
    172 int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
    173 	{
    174 	return(X509v3_get_ext_count(x->tbsResponseData->responseExtensions));
    175 	}
    176 
    177 int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
    178 	{
    179 	return(X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,nid,lastpos));
    180 	}
    181 
    182 int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos)
    183 	{
    184 	return(X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,obj,lastpos));
    185 	}
    186 
    187 int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos)
    188 	{
    189 	return(X509v3_get_ext_by_critical(x->tbsResponseData->responseExtensions,crit,lastpos));
    190 	}
    191 
    192 X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
    193 	{
    194 	return(X509v3_get_ext(x->tbsResponseData->responseExtensions,loc));
    195 	}
    196 
    197 X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
    198 	{
    199 	return(X509v3_delete_ext(x->tbsResponseData->responseExtensions,loc));
    200 	}
    201 
    202 void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx)
    203 	{
    204 	return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, idx);
    205 	}
    206 
    207 int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
    208 							unsigned long flags)
    209 	{
    210 	return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, value, crit, flags);
    211 	}
    212 
    213 int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
    214 	{
    215 	return(X509v3_add_ext(&(x->tbsResponseData->responseExtensions),ex,loc) != NULL);
    216 	}
    217 
    218 /* OCSP single response extensions */
    219 
    220 int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
    221 	{
    222 	return(X509v3_get_ext_count(x->singleExtensions));
    223 	}
    224 
    225 int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
    226 	{
    227 	return(X509v3_get_ext_by_NID(x->singleExtensions,nid,lastpos));
    228 	}
    229 
    230 int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos)
    231 	{
    232 	return(X509v3_get_ext_by_OBJ(x->singleExtensions,obj,lastpos));
    233 	}
    234 
    235 int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos)
    236 	{
    237 	return(X509v3_get_ext_by_critical(x->singleExtensions,crit,lastpos));
    238 	}
    239 
    240 X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
    241 	{
    242 	return(X509v3_get_ext(x->singleExtensions,loc));
    243 	}
    244 
    245 X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
    246 	{
    247 	return(X509v3_delete_ext(x->singleExtensions,loc));
    248 	}
    249 
    250 void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx)
    251 	{
    252 	return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
    253 	}
    254 
    255 int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
    256 							unsigned long flags)
    257 	{
    258 	return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
    259 	}
    260 
    261 int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
    262 	{
    263 	return(X509v3_add_ext(&(x->singleExtensions),ex,loc) != NULL);
    264 	}
    265 
    266 /* also CRL Entry Extensions */
    267 
    268 ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
    269 				void *data, STACK_OF(ASN1_OBJECT) *sk)
    270         {
    271 	int i;
    272 	unsigned char *p, *b = NULL;
    273 
    274 	if (data)
    275 	        {
    276 		if ((i=i2d(data,NULL)) <= 0) goto err;
    277 		if (!(b=p=OPENSSL_malloc((unsigned int)i)))
    278 			goto err;
    279 	        if (i2d(data, &p) <= 0) goto err;
    280 		}
    281 	else if (sk)
    282 	        {
    283 		if ((i=i2d_ASN1_SET_OF_ASN1_OBJECT(sk,NULL,
    284 						   (I2D_OF(ASN1_OBJECT))i2d,
    285 						   V_ASN1_SEQUENCE,
    286 						   V_ASN1_UNIVERSAL,
    287 						   IS_SEQUENCE))<=0) goto err;
    288 		if (!(b=p=OPENSSL_malloc((unsigned int)i)))
    289 			goto err;
    290 		if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk,&p,(I2D_OF(ASN1_OBJECT))i2d,
    291 						V_ASN1_SEQUENCE,
    292 						V_ASN1_UNIVERSAL,
    293 						IS_SEQUENCE)<=0) goto err;
    294 		}
    295 	else
    296 		{
    297 		OCSPerr(OCSP_F_ASN1_STRING_ENCODE,OCSP_R_BAD_DATA);
    298 		goto err;
    299 		}
    300 	if (!s && !(s = ASN1_STRING_new())) goto err;
    301 	if (!(ASN1_STRING_set(s, b, i))) goto err;
    302 	OPENSSL_free(b);
    303 	return s;
    304 err:
    305 	if (b) OPENSSL_free(b);
    306 	return NULL;
    307 	}
    308 
    309 /* Nonce handling functions */
    310 
    311 /* Add a nonce to an extension stack. A nonce can be specificed or if NULL
    312  * a random nonce will be generated.
    313  * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the
    314  * nonce, previous versions used the raw nonce.
    315  */
    316 
    317 static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len)
    318 	{
    319 	unsigned char *tmpval;
    320 	ASN1_OCTET_STRING os;
    321 	int ret = 0;
    322 	if (len <= 0) len = OCSP_DEFAULT_NONCE_LENGTH;
    323 	/* Create the OCTET STRING manually by writing out the header and
    324 	 * appending the content octets. This avoids an extra memory allocation
    325 	 * operation in some cases. Applications should *NOT* do this because
    326          * it relies on library internals.
    327 	 */
    328 	os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING);
    329 	os.data = OPENSSL_malloc(os.length);
    330 	if (os.data == NULL)
    331 		goto err;
    332 	tmpval = os.data;
    333 	ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL);
    334 	if (val)
    335 		memcpy(tmpval, val, len);
    336 	else
    337 		RAND_pseudo_bytes(tmpval, len);
    338 	if(!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
    339 			&os, 0, X509V3_ADD_REPLACE))
    340 				goto err;
    341 	ret = 1;
    342 	err:
    343 	if (os.data)
    344 		OPENSSL_free(os.data);
    345 	return ret;
    346 	}
    347 
    348 
    349 /* Add nonce to an OCSP request */
    350 
    351 int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
    352 	{
    353 	return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len);
    354 	}
    355 
    356 /* Same as above but for a response */
    357 
    358 int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
    359 	{
    360 	return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, len);
    361 	}
    362 
    363 /* Check nonce validity in a request and response.
    364  * Return value reflects result:
    365  *  1: nonces present and equal.
    366  *  2: nonces both absent.
    367  *  3: nonce present in response only.
    368  *  0: nonces both present and not equal.
    369  * -1: nonce in request only.
    370  *
    371  *  For most responders clients can check return > 0.
    372  *  If responder doesn't handle nonces return != 0 may be
    373  *  necessary. return == 0 is always an error.
    374  */
    375 
    376 int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
    377 	{
    378 	/*
    379 	 * Since we are only interested in the presence or absence of
    380 	 * the nonce and comparing its value there is no need to use
    381 	 * the X509V3 routines: this way we can avoid them allocating an
    382 	 * ASN1_OCTET_STRING structure for the value which would be
    383 	 * freed immediately anyway.
    384 	 */
    385 
    386 	int req_idx, resp_idx;
    387 	X509_EXTENSION *req_ext, *resp_ext;
    388 	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
    389 	resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1);
    390 	/* Check both absent */
    391 	if((req_idx < 0) && (resp_idx < 0))
    392 		return 2;
    393 	/* Check in request only */
    394 	if((req_idx >= 0) && (resp_idx < 0))
    395 		return -1;
    396 	/* Check in response but not request */
    397 	if((req_idx < 0) && (resp_idx >= 0))
    398 		return 3;
    399 	/* Otherwise nonce in request and response so retrieve the extensions */
    400 	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
    401 	resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
    402 	if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value))
    403 		return 0;
    404 	return 1;
    405 	}
    406 
    407 /* Copy the nonce value (if any) from an OCSP request to
    408  * a response.
    409  */
    410 
    411 int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req)
    412 	{
    413 	X509_EXTENSION *req_ext;
    414 	int req_idx;
    415 	/* Check for nonce in request */
    416 	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
    417 	/* If no nonce that's OK */
    418 	if (req_idx < 0) return 2;
    419 	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
    420 	return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
    421 	}
    422 
    423 X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim)
    424         {
    425 	X509_EXTENSION *x = NULL;
    426 	OCSP_CRLID *cid = NULL;
    427 
    428 	if (!(cid = OCSP_CRLID_new())) goto err;
    429 	if (url)
    430 	        {
    431 		if (!(cid->crlUrl = ASN1_IA5STRING_new())) goto err;
    432 		if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err;
    433 		}
    434 	if (n)
    435 	        {
    436 		if (!(cid->crlNum = ASN1_INTEGER_new())) goto err;
    437 		if (!(ASN1_INTEGER_set(cid->crlNum, *n))) goto err;
    438 		}
    439 	if (tim)
    440 	        {
    441 		if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) goto err;
    442 		if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
    443 		        goto err;
    444 		}
    445 	if (!(x = X509_EXTENSION_new())) goto err;
    446 	if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_CrlID))) goto err;
    447 	if (!(ASN1_STRING_encode_of(OCSP_CRLID,x->value,i2d_OCSP_CRLID,cid,
    448 				    NULL)))
    449 	        goto err;
    450 	OCSP_CRLID_free(cid);
    451 	return x;
    452 err:
    453 	if (x) X509_EXTENSION_free(x);
    454 	if (cid) OCSP_CRLID_free(cid);
    455 	return NULL;
    456 	}
    457 
    458 /*   AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
    459 X509_EXTENSION *OCSP_accept_responses_new(char **oids)
    460         {
    461 	int nid;
    462 	STACK_OF(ASN1_OBJECT) *sk = NULL;
    463 	ASN1_OBJECT *o = NULL;
    464         X509_EXTENSION *x = NULL;
    465 
    466 	if (!(sk = sk_ASN1_OBJECT_new_null())) goto err;
    467 	while (oids && *oids)
    468 	        {
    469 		if ((nid=OBJ_txt2nid(*oids))!=NID_undef&&(o=OBJ_nid2obj(nid)))
    470 		        sk_ASN1_OBJECT_push(sk, o);
    471 		oids++;
    472 		}
    473 	if (!(x = X509_EXTENSION_new())) goto err;
    474 	if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_acceptableResponses)))
    475 		goto err;
    476 	if (!(ASN1_STRING_encode_of(ASN1_OBJECT,x->value,i2d_ASN1_OBJECT,NULL,
    477 				    sk)))
    478 	        goto err;
    479 	sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
    480 	return x;
    481 err:
    482 	if (x) X509_EXTENSION_free(x);
    483 	if (sk) sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
    484 	return NULL;
    485         }
    486 
    487 /*  ArchiveCutoff ::= GeneralizedTime */
    488 X509_EXTENSION *OCSP_archive_cutoff_new(char* tim)
    489         {
    490 	X509_EXTENSION *x=NULL;
    491 	ASN1_GENERALIZEDTIME *gt = NULL;
    492 
    493 	if (!(gt = ASN1_GENERALIZEDTIME_new())) goto err;
    494 	if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) goto err;
    495 	if (!(x = X509_EXTENSION_new())) goto err;
    496 	if (!(x->object=OBJ_nid2obj(NID_id_pkix_OCSP_archiveCutoff)))goto err;
    497 	if (!(ASN1_STRING_encode_of(ASN1_GENERALIZEDTIME,x->value,
    498 				    i2d_ASN1_GENERALIZEDTIME,gt,NULL))) goto err;
    499 	ASN1_GENERALIZEDTIME_free(gt);
    500 	return x;
    501 err:
    502 	if (gt) ASN1_GENERALIZEDTIME_free(gt);
    503 	if (x) X509_EXTENSION_free(x);
    504 	return NULL;
    505 	}
    506 
    507 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
    508  * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value.  This
    509  * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
    510  */
    511 X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls)
    512         {
    513 	X509_EXTENSION *x = NULL;
    514 	ASN1_IA5STRING *ia5 = NULL;
    515 	OCSP_SERVICELOC *sloc = NULL;
    516 	ACCESS_DESCRIPTION *ad = NULL;
    517 
    518 	if (!(sloc = OCSP_SERVICELOC_new())) goto err;
    519 	if (!(sloc->issuer = X509_NAME_dup(issuer))) goto err;
    520 	if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) goto err;
    521 	while (urls && *urls)
    522 	        {
    523 		if (!(ad = ACCESS_DESCRIPTION_new())) goto err;
    524 		if (!(ad->method=OBJ_nid2obj(NID_ad_OCSP))) goto err;
    525 		if (!(ad->location = GENERAL_NAME_new())) goto err;
    526 	        if (!(ia5 = ASN1_IA5STRING_new())) goto err;
    527 		if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) goto err;
    528 		ad->location->type = GEN_URI;
    529 		ad->location->d.ia5 = ia5;
    530 		if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) goto err;
    531 		urls++;
    532 		}
    533 	if (!(x = X509_EXTENSION_new())) goto err;
    534 	if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_serviceLocator)))
    535 	        goto err;
    536 	if (!(ASN1_STRING_encode_of(OCSP_SERVICELOC,x->value,
    537 				    i2d_OCSP_SERVICELOC,sloc,NULL))) goto err;
    538 	OCSP_SERVICELOC_free(sloc);
    539 	return x;
    540 err:
    541 	if (x) X509_EXTENSION_free(x);
    542 	if (sloc) OCSP_SERVICELOC_free(sloc);
    543 	return NULL;
    544 	}
    545 
    546