Use OPENSSL_hexchar2int
[openssl.git] / crypto / x509v3 / v3_genn.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2008 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 #include <stdio.h>
60 #include "internal/cryptlib.h"
61 #include <openssl/asn1t.h>
62 #include <openssl/conf.h>
63 #include <openssl/x509v3.h>
64
65 ASN1_SEQUENCE(OTHERNAME) = {
66         ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
67         /* Maybe have a true ANY DEFINED BY later */
68         ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
69 } ASN1_SEQUENCE_END(OTHERNAME)
70
71 IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
72
73 ASN1_SEQUENCE(EDIPARTYNAME) = {
74         ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
75         ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
76 } ASN1_SEQUENCE_END(EDIPARTYNAME)
77
78 IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
79
80 ASN1_CHOICE(GENERAL_NAME) = {
81         ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
82         ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
83         ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
84         /* Don't decode this */
85         ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
86         /* X509_NAME is a CHOICE type so use EXPLICIT */
87         ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
88         ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
89         ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
90         ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
91         ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
92 } ASN1_CHOICE_END(GENERAL_NAME)
93
94 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
95
96 ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
97         ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
98 ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
99
100 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
101
102 GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
103 {
104     return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
105                                     (d2i_of_void *)d2i_GENERAL_NAME,
106                                     (char *)a);
107 }
108
109 /* Returns 0 if they are equal, != 0 otherwise. */
110 int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
111 {
112     int result = -1;
113
114     if (!a || !b || a->type != b->type)
115         return -1;
116     switch (a->type) {
117     case GEN_X400:
118     case GEN_EDIPARTY:
119         result = ASN1_TYPE_cmp(a->d.other, b->d.other);
120         break;
121
122     case GEN_OTHERNAME:
123         result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
124         break;
125
126     case GEN_EMAIL:
127     case GEN_DNS:
128     case GEN_URI:
129         result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
130         break;
131
132     case GEN_DIRNAME:
133         result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
134         break;
135
136     case GEN_IPADD:
137         result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
138         break;
139
140     case GEN_RID:
141         result = OBJ_cmp(a->d.rid, b->d.rid);
142         break;
143     }
144     return result;
145 }
146
147 /* Returns 0 if they are equal, != 0 otherwise. */
148 int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
149 {
150     int result = -1;
151
152     if (!a || !b)
153         return -1;
154     /* Check their type first. */
155     if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
156         return result;
157     /* Check the value. */
158     result = ASN1_TYPE_cmp(a->value, b->value);
159     return result;
160 }
161
162 void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
163 {
164     switch (type) {
165     case GEN_X400:
166     case GEN_EDIPARTY:
167         a->d.other = value;
168         break;
169
170     case GEN_OTHERNAME:
171         a->d.otherName = value;
172         break;
173
174     case GEN_EMAIL:
175     case GEN_DNS:
176     case GEN_URI:
177         a->d.ia5 = value;
178         break;
179
180     case GEN_DIRNAME:
181         a->d.dirn = value;
182         break;
183
184     case GEN_IPADD:
185         a->d.ip = value;
186         break;
187
188     case GEN_RID:
189         a->d.rid = value;
190         break;
191     }
192     a->type = type;
193 }
194
195 void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
196 {
197     if (ptype)
198         *ptype = a->type;
199     switch (a->type) {
200     case GEN_X400:
201     case GEN_EDIPARTY:
202         return a->d.other;
203
204     case GEN_OTHERNAME:
205         return a->d.otherName;
206
207     case GEN_EMAIL:
208     case GEN_DNS:
209     case GEN_URI:
210         return a->d.ia5;
211
212     case GEN_DIRNAME:
213         return a->d.dirn;
214
215     case GEN_IPADD:
216         return a->d.ip;
217
218     case GEN_RID:
219         return a->d.rid;
220
221     default:
222         return NULL;
223     }
224 }
225
226 int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
227                                 ASN1_OBJECT *oid, ASN1_TYPE *value)
228 {
229     OTHERNAME *oth;
230     oth = OTHERNAME_new();
231     if (oth == NULL)
232         return 0;
233     oth->type_id = oid;
234     oth->value = value;
235     GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
236     return 1;
237 }
238
239 int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
240                                 ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
241 {
242     if (gen->type != GEN_OTHERNAME)
243         return 0;
244     if (poid)
245         *poid = gen->d.otherName->type_id;
246     if (pvalue)
247         *pvalue = gen->d.otherName->value;
248     return 1;
249 }