This commit was generated by cvs2svn to track changes on a CVS vendor
[openssl.git] / crypto / x509 / x509_v3.c
1 /* crypto/x509/x509_v3.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "stack.h"
61 #include "cryptlib.h"
62 #include "asn1.h"
63 #include "objects.h"
64 #include "evp.h"
65 #include "x509.h"
66
67 #ifndef NOPROTO
68 static X509_EXTENSION_METHOD *find_by_nid(int nid);
69 static int xem_cmp(X509_EXTENSION_METHOD **a, X509_EXTENSION_METHOD **b);
70 #else
71 static X509_EXTENSION_METHOD *find_by_nid();
72 static int xem_cmp();
73 #endif
74
75 static STACK *extensions=NULL;
76
77 int X509v3_get_ext_count(x)
78 STACK *x;
79         {
80         if (x == NULL) return(0);
81         return(sk_num(x));
82         }
83
84 int X509v3_get_ext_by_NID(x,nid,oldpos)
85 STACK *x;
86 int nid;
87 int oldpos;
88         {
89         ASN1_OBJECT *obj;
90
91         obj=OBJ_nid2obj(nid);
92         if (obj == NULL) return(-2);
93         return(X509v3_get_ext_by_OBJ(x,obj,oldpos));
94         }
95
96 int X509v3_get_ext_by_OBJ(sk,obj,oldpos)
97 STACK *sk;
98 ASN1_OBJECT *obj;
99 int oldpos;
100         {
101         int n;
102         X509_EXTENSION *ex;
103
104         if (sk == NULL) return(-1);
105         oldpos++;
106         if (oldpos < 0)
107                 oldpos=0;
108         n=sk_num(sk);
109         for ( ; oldpos < n; oldpos++)
110                 {
111                 ex=(X509_EXTENSION *)sk_value(sk,oldpos);
112                 if (OBJ_cmp(ex->object,obj) == 0)
113                         return(oldpos);
114                 }
115         return(-1);
116         }
117
118 int X509v3_get_ext_by_critical(sk,crit,oldpos)
119 STACK *sk;
120 int crit;
121 int oldpos;
122         {
123         int n;
124         X509_EXTENSION *ex;
125
126         if (sk == NULL) return(-1);
127         oldpos++;
128         if (oldpos < 0)
129                 oldpos=0;
130         n=sk_num(sk);
131         for ( ; oldpos < n; oldpos++)
132                 {
133                 ex=(X509_EXTENSION *)sk_value(sk,oldpos);
134                 if (    (ex->critical && crit) ||
135                         (!ex->critical && !crit))
136                         return(oldpos);
137                 }
138         return(-1);
139         }
140
141 X509_EXTENSION *X509v3_get_ext(x,loc)
142 STACK *x;
143 int loc;
144         {
145         if ((x == NULL) || (sk_num(x) <= loc) || (loc < 0))
146                 return(NULL);
147         else
148                 return((X509_EXTENSION *)sk_value(x,loc));
149         }
150
151 X509_EXTENSION *X509v3_delete_ext(x,loc)
152 STACK *x;
153 int loc;
154         {
155         X509_EXTENSION *ret;
156
157         if ((x == NULL) || (sk_num(x) <= loc) || (loc < 0))
158                 return(NULL);
159         ret=(X509_EXTENSION *)sk_delete(x,loc);
160         return(ret);
161         }
162
163 STACK *X509v3_add_ext(x,ex,loc)
164 STACK **x;
165 X509_EXTENSION *ex;
166 int loc;
167         {
168         X509_EXTENSION *new_ex=NULL;
169         int n;
170         STACK *sk=NULL;
171
172         if ((x != NULL) && (*x == NULL))
173                 {
174                 if ((sk=sk_new_null()) == NULL)
175                         goto err;
176                 }
177         else
178                 sk= *x;
179
180         n=sk_num(sk);
181         if (loc > n) loc=n;
182         else if (loc < 0) loc=n;
183
184         if ((new_ex=X509_EXTENSION_dup(ex)) == NULL)
185                 goto err2;
186         if (!sk_insert(sk,(char *)new_ex,loc))
187                 goto err;
188         if ((x != NULL) && (*x == NULL))
189                 *x=sk;
190         return(sk);
191 err:
192         X509err(X509_F_X509V3_ADD_EXT,ERR_R_MALLOC_FAILURE);
193 err2:
194         if (new_ex != NULL) X509_EXTENSION_free(new_ex);
195         if (sk != NULL) sk_free(sk);
196         return(NULL);
197         }
198
199 X509_EXTENSION *X509_EXTENSION_create_by_NID(ex,nid,crit,data)
200 X509_EXTENSION **ex;
201 int nid;
202 int crit;
203 ASN1_OCTET_STRING *data;
204         {
205         ASN1_OBJECT *obj;
206         X509_EXTENSION *ret;
207
208         obj=OBJ_nid2obj(nid);
209         if (obj == NULL)
210                 {
211                 X509err(X509_F_X509_EXTENSION_CREATE_BY_NID,X509_R_UNKNOWN_NID);
212                 return(NULL);
213                 }
214         ret=X509_EXTENSION_create_by_OBJ(ex,obj,crit,data);
215         if (ret == NULL) ASN1_OBJECT_free(obj);
216         return(ret);
217         }
218
219 X509_EXTENSION *X509_EXTENSION_create_by_OBJ(ex,obj,crit,data)
220 X509_EXTENSION **ex;
221 ASN1_OBJECT *obj;
222 int crit;
223 ASN1_OCTET_STRING *data;
224         {
225         X509_EXTENSION *ret;
226
227         if ((ex == NULL) || (*ex == NULL))
228                 {
229                 if ((ret=X509_EXTENSION_new()) == NULL)
230                         {
231                         X509err(X509_F_X509_EXTENSION_CREATE_BY_OBJ,ERR_R_MALLOC_FAILURE);
232                         return(NULL);
233                         }
234                 }
235         else
236                 ret= *ex;
237
238         if (!X509_EXTENSION_set_object(ret,obj))
239                 goto err;
240         if (!X509_EXTENSION_set_critical(ret,crit))
241                 goto err;
242         if (!X509_EXTENSION_set_data(ret,data))
243                 goto err;
244         
245         if ((ex != NULL) && (*ex == NULL)) *ex=ret;
246         return(ret);
247 err:
248         if ((ex == NULL) || (ret != *ex))
249                 X509_EXTENSION_free(ret);
250         return(NULL);
251         }
252
253 int X509_EXTENSION_set_object(ex,obj)
254 X509_EXTENSION *ex;
255 ASN1_OBJECT *obj;
256         {
257         if ((ex == NULL) || (obj == NULL))
258                 return(0);
259         ASN1_OBJECT_free(ex->object);
260         ex->object=OBJ_dup(obj);
261         return(1);
262         }
263
264 int X509_EXTENSION_set_critical(ex,crit)
265 X509_EXTENSION *ex;
266 int crit;
267         {
268         if (ex == NULL) return(0);
269         ex->critical=(crit)?0xFF:0;
270         return(1);
271         }
272
273 int X509_EXTENSION_set_data(ex,data)
274 X509_EXTENSION *ex;
275 ASN1_OCTET_STRING *data;
276         {
277         int i;
278
279         if (ex == NULL) return(0);
280         i=ASN1_OCTET_STRING_set(ex->value,data->data,data->length);
281         if (!i) return(0);
282         return(1);
283         }
284
285 ASN1_OBJECT *X509_EXTENSION_get_object(ex)
286 X509_EXTENSION *ex;
287         {
288         if (ex == NULL) return(NULL);
289         return(ex->object);
290         }
291
292 ASN1_OCTET_STRING *X509_EXTENSION_get_data(ex)
293 X509_EXTENSION *ex;
294         {
295         if (ex == NULL) return(NULL);
296         return(ex->value);
297         }
298
299 int X509_EXTENSION_get_critical(ex)
300 X509_EXTENSION *ex;
301         {
302         if (ex == NULL) return(0);
303         return(ex->critical);
304         }
305
306 int X509v3_data_type_by_OBJ(obj)
307 ASN1_OBJECT *obj;
308         {
309         int nid;
310
311         nid=OBJ_obj2nid(obj);
312         if (nid == V_ASN1_UNDEF) return(V_ASN1_UNDEF);
313         return(X509v3_data_type_by_NID(nid));
314         }
315
316 int X509v3_data_type_by_NID(nid)
317 int nid;
318         {
319         X509_EXTENSION_METHOD *x;
320
321         x=find_by_nid(nid);
322         if (x == NULL)
323                 return(V_ASN1_UNDEF);
324         else
325                 return(x->data_type);
326         }
327
328 int X509v3_pack_type_by_OBJ(obj)
329 ASN1_OBJECT *obj;
330         {
331         int nid;
332
333         nid=OBJ_obj2nid(obj);
334         if (nid == NID_undef) return(X509_EXT_PACK_UNKNOWN);
335         return(X509v3_pack_type_by_NID(nid));
336         }
337
338 int X509v3_pack_type_by_NID(nid)
339 int nid;
340         {
341         X509_EXTENSION_METHOD *x;
342
343         x=find_by_nid(nid);
344         if (x == NULL)
345                 return(X509_EXT_PACK_UNKNOWN);
346         else
347                 return(x->pack_type);
348         }
349
350 static X509_EXTENSION_METHOD *find_by_nid(nid)
351 int nid;
352         {
353         X509_EXTENSION_METHOD x;
354         int i;
355
356         x.nid=nid;
357         if (extensions == NULL) return(NULL);
358         i=sk_find(extensions,(char *)&x);
359         if (i < 0)
360                 return(NULL);
361         else
362                 return((X509_EXTENSION_METHOD *)sk_value(extensions,i));
363         }
364
365 static int xem_cmp(a,b)
366 X509_EXTENSION_METHOD **a,**b;
367         {
368         return((*a)->nid-(*b)->nid);
369         }
370
371 void X509v3_cleanup_extensions()
372         {
373         int i;
374
375         if (extensions != NULL)
376                 {
377                 for (i=0; i<sk_num(extensions); i++)
378                         Free(sk_value(extensions,i));
379                 sk_free(extensions);
380                 extensions=NULL;
381                 }
382         }
383
384 int X509v3_add_extension(x)
385 X509_EXTENSION_METHOD *x;
386         {
387         X509_EXTENSION_METHOD *newx;
388
389         if (extensions == NULL)
390                 {
391                 extensions=sk_new(xem_cmp);
392                 if (extensions == NULL) goto err;
393                 }
394         newx=(X509_EXTENSION_METHOD *)Malloc(sizeof(X509_EXTENSION_METHOD));
395         if (newx == NULL) goto err;
396         newx->nid=x->nid;
397         newx->data_type=x->data_type;
398         newx->pack_type=x->pack_type;
399         if (!sk_push(extensions,(char *)newx))
400                 {
401                 Free(newx);
402                 goto err;
403                 }
404         return(1);
405 err:
406         X509err(X509_F_X509V3_ADD_EXTENSION,ERR_R_MALLOC_FAILURE);
407         return(0);
408         }
409