New OCSP extension functions.
[openssl.git] / crypto / ocsp / ocsp_ext.c
1 /* ocsp_ext.c */
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 <cryptlib.h>
66 #include <openssl/objects.h>
67 #include <openssl/x509.h>
68 #include <openssl/ocsp.h>
69 #include <openssl/x509v3.h>
70
71 /* Standard wrapper functions for extensions */
72
73 /* OCSP request extensions */
74
75 int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
76         {
77         return(X509v3_get_ext_count(x->tbsRequest->requestExtensions));
78         }
79
80 int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
81         {
82         return(X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions,nid,lastpos));
83         }
84
85 int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos)
86         {
87         return(X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions,obj,lastpos));
88         }
89
90 int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
91         {
92         return(X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,crit,lastpos));
93         }
94
95 X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
96         {
97         return(X509v3_get_ext(x->tbsRequest->requestExtensions,loc));
98         }
99
100 X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
101         {
102         return(X509v3_delete_ext(x->tbsRequest->requestExtensions,loc));
103         }
104
105 void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
106         {
107         return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx);
108         }
109
110 int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
111                                                         unsigned long flags)
112         {
113         return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, crit, flags);
114         }
115
116 int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
117         {
118         return(X509v3_add_ext(&(x->tbsRequest->requestExtensions),ex,loc) != NULL);
119         }
120
121 /* Single extensions */
122
123 int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
124         {
125         return(X509v3_get_ext_count(x->singleRequestExtensions));
126         }
127
128 int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
129         {
130         return(X509v3_get_ext_by_NID(x->singleRequestExtensions,nid,lastpos));
131         }
132
133 int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos)
134         {
135         return(X509v3_get_ext_by_OBJ(x->singleRequestExtensions,obj,lastpos));
136         }
137
138 int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
139         {
140         return(X509v3_get_ext_by_critical(x->singleRequestExtensions,crit,lastpos));
141         }
142
143 X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
144         {
145         return(X509v3_get_ext(x->singleRequestExtensions,loc));
146         }
147
148 X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
149         {
150         return(X509v3_delete_ext(x->singleRequestExtensions,loc));
151         }
152
153 void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
154         {
155         return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
156         }
157
158 int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
159                                                         unsigned long flags)
160         {
161         return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, flags);
162         }
163
164 int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
165         {
166         return(X509v3_add_ext(&(x->singleRequestExtensions),ex,loc) != NULL);
167         }
168
169 /* OCSP Basic response */
170
171 int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
172         {
173         return(X509v3_get_ext_count(x->tbsResponseData->responseExtensions));
174         }
175
176 int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
177         {
178         return(X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,nid,lastpos));
179         }
180
181 int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos)
182         {
183         return(X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,obj,lastpos));
184         }
185
186 int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos)
187         {
188         return(X509v3_get_ext_by_critical(x->tbsResponseData->responseExtensions,crit,lastpos));
189         }
190
191 X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
192         {
193         return(X509v3_get_ext(x->tbsResponseData->responseExtensions,loc));
194         }
195
196 X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
197         {
198         return(X509v3_delete_ext(x->tbsResponseData->responseExtensions,loc));
199         }
200
201 void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx)
202         {
203         return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, idx);
204         }
205
206 int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
207                                                         unsigned long flags)
208         {
209         return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, value, crit, flags);
210         }
211
212 int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
213         {
214         return(X509v3_add_ext(&(x->tbsResponseData->responseExtensions),ex,loc) != NULL);
215         }
216
217 /* OCSP single response extensions */
218
219 int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
220         {
221         return(X509v3_get_ext_count(x->singleExtensions));
222         }
223
224 int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
225         {
226         return(X509v3_get_ext_by_NID(x->singleExtensions,nid,lastpos));
227         }
228
229 int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos)
230         {
231         return(X509v3_get_ext_by_OBJ(x->singleExtensions,obj,lastpos));
232         }
233
234 int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos)
235         {
236         return(X509v3_get_ext_by_critical(x->singleExtensions,crit,lastpos));
237         }
238
239 X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
240         {
241         return(X509v3_get_ext(x->singleExtensions,loc));
242         }
243
244 X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
245         {
246         return(X509v3_delete_ext(x->singleExtensions,loc));
247         }
248
249 void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx)
250         {
251         return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
252         }
253
254 int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
255                                                         unsigned long flags)
256         {
257         return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
258         }
259
260 int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
261         {
262         return(X509v3_add_ext(&(x->singleExtensions),ex,loc) != NULL);
263         }
264
265 /* also CRL Entry Extensions */
266
267 ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, int (*i2d)(), 
268                                 char *data, STACK_OF(ASN1_OBJECT) *sk)
269         {
270         int i;
271         unsigned char *p, *b = NULL;
272
273         if (data)
274                 {
275                 if ((i=i2d(data,NULL)) <= 0) goto err;
276                 if (!(b=p=(unsigned char*)OPENSSL_malloc((unsigned int)i)))
277                         goto err;
278                 if (i2d(data, &p) <= 0) goto err;
279                 }
280         else if (sk)
281                 {
282                 if ((i=i2d_ASN1_SET_OF_ASN1_OBJECT(sk,NULL,i2d,V_ASN1_SEQUENCE,
283                                    V_ASN1_UNIVERSAL,IS_SEQUENCE))<=0) goto err;
284                 if (!(b=p=(unsigned char*)OPENSSL_malloc((unsigned int)i)))
285                         goto err;
286                 if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk,&p,i2d,V_ASN1_SEQUENCE,
287                                  V_ASN1_UNIVERSAL,IS_SEQUENCE)<=0) goto err;
288                 }
289         else
290                 {
291                 OCSPerr(OCSP_F_ASN1_STRING_ENCODE,OCSP_R_BAD_DATA);
292                 goto err;
293                 }
294         if (!s && !(s = ASN1_STRING_new())) goto err;
295         if (!(ASN1_STRING_set(s, b, i))) goto err;
296         OPENSSL_free(b);
297         return s;
298 err:
299         if (b) OPENSSL_free(b);
300         return NULL;
301         }
302
303 X509_EXTENSION *OCSP_nonce_new(void *p, unsigned int len)
304         {
305         X509_EXTENSION *x=NULL;
306         if (!(x = X509_EXTENSION_new())) goto err;
307         if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_Nonce))) goto err;
308         if (!(ASN1_OCTET_STRING_set(x->value, p, len))) goto err;
309         return x;
310 err:
311         if (x) X509_EXTENSION_free(x);
312         return NULL;
313         }
314
315 X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim)
316         {
317         X509_EXTENSION *x = NULL;
318         OCSP_CRLID *cid = NULL;
319         
320         if (!(cid = OCSP_CRLID_new())) goto err;
321         if (url)
322                 {
323                 if (!(cid->crlUrl = ASN1_IA5STRING_new())) goto err;
324                 if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err;
325                 }
326         if (n)
327                 {
328                 if (!(cid->crlNum = ASN1_INTEGER_new())) goto err;
329                 if (!(ASN1_INTEGER_set(cid->crlNum, *n))) goto err;
330                 }
331         if (tim)
332                 {
333                 if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) goto err;
334                 if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) 
335                         goto err;
336                 }
337         if (!(x = X509_EXTENSION_new())) goto err;
338         if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_CrlID))) goto err;
339         if (!(ASN1_STRING_encode(x->value,i2d_OCSP_CRLID,(char*)cid,NULL)))
340                 goto err;
341         OCSP_CRLID_free(cid);
342         return x;
343 err:
344         if (x) X509_EXTENSION_free(x);
345         if (cid) OCSP_CRLID_free(cid);
346         return NULL;
347         }
348
349 /*   AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
350 X509_EXTENSION *OCSP_accept_responses_new(char **oids)
351         {
352         int nid;
353         STACK_OF(ASN1_OBJECT) *sk = NULL;
354         ASN1_OBJECT *o = NULL;
355         X509_EXTENSION *x = NULL;
356
357         if (!(sk = sk_ASN1_OBJECT_new(NULL))) goto err;
358         while (oids && *oids)
359                 {
360                 if ((nid=OBJ_txt2nid(*oids))!=NID_undef&&(o=OBJ_nid2obj(nid))) 
361                         sk_ASN1_OBJECT_push(sk, o);
362                 oids++;
363                 }
364         if (!(x = X509_EXTENSION_new())) goto err;
365         if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_acceptableResponses)))
366                 goto err;
367         if (!(ASN1_STRING_encode(x->value,i2d_ASN1_OBJECT,NULL,sk)))
368                 goto err;
369         sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
370         return x;
371 err:
372         if (x) X509_EXTENSION_free(x);
373         if (sk) sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
374         return NULL;
375         }
376
377 /*  ArchiveCutoff ::= GeneralizedTime */
378 X509_EXTENSION *OCSP_archive_cutoff_new(char* tim)
379         {
380         X509_EXTENSION *x=NULL;
381         ASN1_GENERALIZEDTIME *gt = NULL;
382
383         if (!(gt = ASN1_GENERALIZEDTIME_new())) goto err;
384         if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) goto err;
385         if (!(x = X509_EXTENSION_new())) goto err;
386         if (!(x->object=OBJ_nid2obj(NID_id_pkix_OCSP_archiveCutoff)))goto err;
387         if (!(ASN1_STRING_encode(x->value,i2d_ASN1_GENERALIZEDTIME,
388                                  (char*)gt,NULL))) goto err;
389         ASN1_GENERALIZEDTIME_free(gt);
390         return x;
391 err:
392         if (gt) ASN1_GENERALIZEDTIME_free(gt);
393         if (x) X509_EXTENSION_free(x);
394         return NULL;
395         }
396
397 /* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
398  * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value.  This
399  * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
400  */
401 X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls)
402         {
403         X509_EXTENSION *x = NULL;
404         ASN1_IA5STRING *ia5 = NULL;
405         OCSP_SERVICELOC *sloc = NULL;
406         ACCESS_DESCRIPTION *ad = NULL;
407         
408         if (!(sloc = OCSP_SERVICELOC_new())) goto err;
409         if (!(sloc->issuer = X509_NAME_dup(issuer))) goto err;
410         if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new(NULL))) goto err;
411         while (urls && *urls)
412                 {
413                 if (!(ad = ACCESS_DESCRIPTION_new())) goto err;
414                 if (!(ad->method=OBJ_nid2obj(NID_ad_OCSP))) goto err;
415                 if (!(ad->location = GENERAL_NAME_new())) goto err;
416                 if (!(ia5 = ASN1_IA5STRING_new())) goto err;
417                 if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) goto err;
418                 ad->location->type = GEN_URI;
419                 ad->location->d.ia5 = ia5;
420                 if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) goto err;
421                 urls++;
422                 }
423         if (!(x = X509_EXTENSION_new())) goto err;
424         if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_serviceLocator))) 
425                 goto err;
426         if (!(ASN1_STRING_encode(x->value, i2d_OCSP_SERVICELOC,
427                                  (char*)sloc, NULL))) goto err;
428         OCSP_SERVICELOC_free(sloc);
429         return x;
430 err:
431         if (x) X509_EXTENSION_free(x);
432         if (sloc) OCSP_SERVICELOC_free(sloc);
433         return NULL;
434         }
435