Seek out and destroy another evil cast.
[openssl.git] / crypto / x509v3 / v3_genn.c
1 /* v3_genn.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59
60 #include <stdio.h>
61 #include "cryptlib.h"
62 #include <openssl/asn1.h>
63 #include <openssl/asn1_mac.h>
64 #include <openssl/conf.h>
65 #include <openssl/x509v3.h>
66
67 int i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **pp)
68 {
69         unsigned char *p;
70         int ret;
71
72         ret = 0;
73
74         /* Save the location of initial TAG */
75         if(pp) p = *pp;
76         else p = NULL;
77
78         /* GEN_DNAME needs special treatment because of EXPLICIT tag */
79
80         if(a->type == GEN_DIRNAME) {
81                 int v = 0;
82                 M_ASN1_I2D_len_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v);
83                 if(!p) return ret;
84                 M_ASN1_I2D_put_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v);
85                 *pp = p;
86                 return ret;
87         }
88
89         switch(a->type) {
90
91                 case GEN_X400:
92                 case GEN_EDIPARTY:
93                 ret = i2d_ASN1_TYPE(a->d.other, pp);
94                 break;
95
96                 case GEN_OTHERNAME:
97                 ret = i2d_OTHERNAME(a->d.otherName, pp);
98                 break;
99
100                 case GEN_EMAIL:
101                 case GEN_DNS:
102                 case GEN_URI:
103                 ret = i2d_ASN1_IA5STRING(a->d.ia5, pp);
104                 break;
105
106                 case GEN_IPADD:
107                 ret = i2d_ASN1_OCTET_STRING(a->d.ip, pp);
108                 break;
109         
110                 case GEN_RID:
111                 ret = i2d_ASN1_OBJECT(a->d.rid, pp);
112                 break;
113         }
114         /* Replace TAG with IMPLICIT value */
115         if(p) *p = (*p & V_ASN1_CONSTRUCTED) | a->type;
116         return ret;
117 }
118
119 GENERAL_NAME *GENERAL_NAME_new()
120 {
121         GENERAL_NAME *ret=NULL;
122         ASN1_CTX c;
123         M_ASN1_New_Malloc(ret, GENERAL_NAME);
124         ret->type = -1;
125         ret->d.ptr = NULL;
126         return (ret);
127         M_ASN1_New_Error(ASN1_F_GENERAL_NAME_NEW);
128 }
129
130 GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **a, unsigned char **pp,
131                                                                  long length)
132 {
133         unsigned char _tmp;
134         M_ASN1_D2I_vars(a,GENERAL_NAME *,GENERAL_NAME_new);
135         M_ASN1_D2I_Init();
136         c.slen = length;
137
138         _tmp = M_ASN1_next;
139         ret->type = _tmp & ~V_ASN1_CONSTRUCTED;
140
141         switch(ret->type) {
142                 /* Just put these in a "blob" for now */
143                 case GEN_X400:
144                 case GEN_EDIPARTY:
145                 M_ASN1_D2I_get_imp(ret->d.other, d2i_ASN1_TYPE,V_ASN1_SEQUENCE);
146                 break;
147
148                 case GEN_OTHERNAME:
149                 M_ASN1_D2I_get_imp(ret->d.otherName, d2i_OTHERNAME,V_ASN1_SEQUENCE);
150                 break;
151
152                 case GEN_EMAIL:
153                 case GEN_DNS:
154                 case GEN_URI:
155                 M_ASN1_D2I_get_imp(ret->d.ia5, d2i_ASN1_IA5STRING,
156                                                         V_ASN1_IA5STRING);
157                 break;
158
159                 case GEN_DIRNAME:
160                 M_ASN1_D2I_get_EXP_opt(ret->d.dirn, d2i_X509_NAME, 4);
161                 break;
162
163                 case GEN_IPADD:
164                 M_ASN1_D2I_get_imp(ret->d.ip, d2i_ASN1_OCTET_STRING,
165                                                         V_ASN1_OCTET_STRING);
166                 break;
167         
168                 case GEN_RID:
169                 M_ASN1_D2I_get_imp(ret->d.rid, d2i_ASN1_OBJECT,V_ASN1_OBJECT);
170                 break;
171
172                 default:
173                 c.error = ASN1_R_BAD_TAG;
174                 goto err;
175         }
176
177         c.slen = 0;
178         M_ASN1_D2I_Finish(a, GENERAL_NAME_free, ASN1_F_D2I_GENERAL_NAME);
179 }
180
181 void GENERAL_NAME_free(GENERAL_NAME *a)
182 {
183         if (a == NULL) return;
184         switch(a->type) {
185                 case GEN_X400:
186                 case GEN_EDIPARTY:
187                 ASN1_TYPE_free(a->d.other);
188                 break;
189
190                 case GEN_OTHERNAME:
191                 OTHERNAME_free(a->d.otherName);
192                 break;
193
194                 case GEN_EMAIL:
195                 case GEN_DNS:
196                 case GEN_URI:
197
198                 M_ASN1_IA5STRING_free(a->d.ia5);
199                 break;
200
201                 case GEN_DIRNAME:
202                 X509_NAME_free(a->d.dirn);
203                 break;
204
205                 case GEN_IPADD:
206                 M_ASN1_OCTET_STRING_free(a->d.ip);
207                 break;
208         
209                 case GEN_RID:
210                 ASN1_OBJECT_free(a->d.rid);
211                 break;
212
213         }
214         Free (a);
215 }
216
217 /* Now the GeneralNames versions: a SEQUENCE OF GeneralName. These are needed as
218  * explicit functions.
219  */
220
221 STACK_OF(GENERAL_NAME) *GENERAL_NAMES_new()
222 {
223         return sk_GENERAL_NAME_new(NULL);
224 }
225
226 void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *a)
227 {
228         sk_GENERAL_NAME_pop_free(a, GENERAL_NAME_free);
229 }
230
231 STACK_OF(GENERAL_NAME) *d2i_GENERAL_NAMES(STACK_OF(GENERAL_NAME) **a,
232                                          unsigned char **pp, long length)
233 {
234 return d2i_ASN1_SET_OF_GENERAL_NAME(a, pp, length, d2i_GENERAL_NAME,
235                          GENERAL_NAME_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
236 }
237
238 int i2d_GENERAL_NAMES(STACK_OF(GENERAL_NAME) *a, unsigned char **pp)
239 {
240 return i2d_ASN1_SET_OF_GENERAL_NAME(a, pp, i2d_GENERAL_NAME, V_ASN1_SEQUENCE,
241                                                  V_ASN1_UNIVERSAL, IS_SEQUENCE);
242 }
243
244 IMPLEMENT_STACK_OF(GENERAL_NAME)
245 IMPLEMENT_ASN1_SET_OF(GENERAL_NAME)
246
247 int i2d_OTHERNAME(OTHERNAME *a, unsigned char **pp)
248 {
249         int v = 0;
250         M_ASN1_I2D_vars(a);
251
252         M_ASN1_I2D_len(a->type_id, i2d_ASN1_OBJECT);
253         M_ASN1_I2D_len_EXP_opt(a->value, i2d_ASN1_TYPE, 0, v);
254
255         M_ASN1_I2D_seq_total();
256
257         M_ASN1_I2D_put(a->type_id, i2d_ASN1_OBJECT);
258         M_ASN1_I2D_put_EXP_opt(a->value, i2d_ASN1_TYPE, 0, v);
259
260         M_ASN1_I2D_finish();
261 }
262
263 OTHERNAME *OTHERNAME_new(void)
264 {
265         OTHERNAME *ret=NULL;
266         ASN1_CTX c;
267         M_ASN1_New_Malloc(ret, OTHERNAME);
268         ret->type_id = OBJ_nid2obj(NID_undef);
269         M_ASN1_New(ret->value, ASN1_TYPE_new);
270         return (ret);
271         M_ASN1_New_Error(ASN1_F_OTHERNAME_NEW);
272 }
273
274 OTHERNAME *d2i_OTHERNAME(OTHERNAME **a, unsigned char **pp, long length)
275 {
276         M_ASN1_D2I_vars(a,OTHERNAME *,OTHERNAME_new);
277         M_ASN1_D2I_Init();
278         M_ASN1_D2I_start_sequence();
279         M_ASN1_D2I_get(ret->type_id, d2i_ASN1_OBJECT);
280         M_ASN1_D2I_get_EXP_opt(ret->value, d2i_ASN1_TYPE, 0);
281         M_ASN1_D2I_Finish(a, OTHERNAME_free, ASN1_F_D2I_OTHERNAME);
282 }
283
284 void OTHERNAME_free(OTHERNAME *a)
285 {
286         if (a == NULL) return;
287         ASN1_OBJECT_free(a->type_id);
288         ASN1_TYPE_free(a->value);
289         Free (a);
290 }
291