155714Skris/* crypto/x509/x509name.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <openssl/stack.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/asn1.h>
6355714Skris#include <openssl/objects.h>
6455714Skris#include <openssl/evp.h>
6555714Skris#include <openssl/x509.h>
6655714Skris
6755714Skrisint X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
68280304Sjkim{
69280304Sjkim    ASN1_OBJECT *obj;
7055714Skris
71280304Sjkim    obj = OBJ_nid2obj(nid);
72280304Sjkim    if (obj == NULL)
73280304Sjkim        return (-1);
74280304Sjkim    return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
75280304Sjkim}
7655714Skris
7755714Skrisint X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
78280304Sjkim                              int len)
79280304Sjkim{
80280304Sjkim    int i;
81280304Sjkim    ASN1_STRING *data;
8255714Skris
83280304Sjkim    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
84280304Sjkim    if (i < 0)
85280304Sjkim        return (-1);
86280304Sjkim    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
87280304Sjkim    i = (data->length > (len - 1)) ? (len - 1) : data->length;
88280304Sjkim    if (buf == NULL)
89280304Sjkim        return (data->length);
90280304Sjkim    memcpy(buf, data->data, i);
91280304Sjkim    buf[i] = '\0';
92280304Sjkim    return (i);
93280304Sjkim}
9455714Skris
9555714Skrisint X509_NAME_entry_count(X509_NAME *name)
96280304Sjkim{
97280304Sjkim    if (name == NULL)
98280304Sjkim        return (0);
99280304Sjkim    return (sk_X509_NAME_ENTRY_num(name->entries));
100280304Sjkim}
10155714Skris
10255714Skrisint X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
103280304Sjkim{
104280304Sjkim    ASN1_OBJECT *obj;
10555714Skris
106280304Sjkim    obj = OBJ_nid2obj(nid);
107280304Sjkim    if (obj == NULL)
108280304Sjkim        return (-2);
109280304Sjkim    return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
110280304Sjkim}
11155714Skris
11255714Skris/* NOTE: you should be passsing -1, not 0 as lastpos */
113280304Sjkimint X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos)
114280304Sjkim{
115280304Sjkim    int n;
116280304Sjkim    X509_NAME_ENTRY *ne;
117280304Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
11855714Skris
119280304Sjkim    if (name == NULL)
120280304Sjkim        return (-1);
121280304Sjkim    if (lastpos < 0)
122280304Sjkim        lastpos = -1;
123280304Sjkim    sk = name->entries;
124280304Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
125280304Sjkim    for (lastpos++; lastpos < n; lastpos++) {
126280304Sjkim        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
127280304Sjkim        if (OBJ_cmp(ne->object, obj) == 0)
128280304Sjkim            return (lastpos);
129280304Sjkim    }
130280304Sjkim    return (-1);
131280304Sjkim}
13255714Skris
13355714SkrisX509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
134280304Sjkim{
135280304Sjkim    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
136280304Sjkim        || loc < 0)
137280304Sjkim        return (NULL);
138280304Sjkim    else
139280304Sjkim        return (sk_X509_NAME_ENTRY_value(name->entries, loc));
140280304Sjkim}
14155714Skris
14255714SkrisX509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
143280304Sjkim{
144280304Sjkim    X509_NAME_ENTRY *ret;
145280304Sjkim    int i, n, set_prev, set_next;
146280304Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
14755714Skris
148280304Sjkim    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
149280304Sjkim        || loc < 0)
150280304Sjkim        return (NULL);
151280304Sjkim    sk = name->entries;
152280304Sjkim    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
153280304Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
154280304Sjkim    name->modified = 1;
155280304Sjkim    if (loc == n)
156280304Sjkim        return (ret);
15755714Skris
158280304Sjkim    /* else we need to fixup the set field */
159280304Sjkim    if (loc != 0)
160280304Sjkim        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
161280304Sjkim    else
162280304Sjkim        set_prev = ret->set - 1;
163280304Sjkim    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
16455714Skris
165280304Sjkim    /*-
166280304Sjkim     * set_prev is the previous set
167280304Sjkim     * set is the current set
168280304Sjkim     * set_next is the following
169280304Sjkim     * prev  1 1    1 1     1 1     1 1
170280304Sjkim     * set   1      1       2       2
171280304Sjkim     * next  1 1    2 2     2 2     3 2
172280304Sjkim     * so basically only if prev and next differ by 2, then
173280304Sjkim     * re-number down by 1
174280304Sjkim     */
175280304Sjkim    if (set_prev + 1 < set_next)
176280304Sjkim        for (i = loc; i < n; i++)
177280304Sjkim            sk_X509_NAME_ENTRY_value(sk, i)->set--;
178280304Sjkim    return (ret);
179280304Sjkim}
18055714Skris
18159191Skrisint X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
182280304Sjkim                               unsigned char *bytes, int len, int loc,
183280304Sjkim                               int set)
18459191Skris{
185280304Sjkim    X509_NAME_ENTRY *ne;
186280304Sjkim    int ret;
187280304Sjkim    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
188280304Sjkim    if (!ne)
189280304Sjkim        return 0;
190280304Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
191280304Sjkim    X509_NAME_ENTRY_free(ne);
192280304Sjkim    return ret;
19359191Skris}
19459191Skris
19559191Skrisint X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
196280304Sjkim                               unsigned char *bytes, int len, int loc,
197280304Sjkim                               int set)
19859191Skris{
199280304Sjkim    X509_NAME_ENTRY *ne;
200280304Sjkim    int ret;
201280304Sjkim    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
202280304Sjkim    if (!ne)
203280304Sjkim        return 0;
204280304Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
205280304Sjkim    X509_NAME_ENTRY_free(ne);
206280304Sjkim    return ret;
20759191Skris}
20859191Skris
209160814Ssimonint X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
210280304Sjkim                               const unsigned char *bytes, int len, int loc,
211280304Sjkim                               int set)
21259191Skris{
213280304Sjkim    X509_NAME_ENTRY *ne;
214280304Sjkim    int ret;
215280304Sjkim    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
216280304Sjkim    if (!ne)
217280304Sjkim        return 0;
218280304Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
219280304Sjkim    X509_NAME_ENTRY_free(ne);
220280304Sjkim    return ret;
22159191Skris}
22259191Skris
223280304Sjkim/*
224280304Sjkim * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
225280304Sjkim * guy we are about to stomp on.
226280304Sjkim */
22755714Skrisint X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
228280304Sjkim                        int set)
229280304Sjkim{
230280304Sjkim    X509_NAME_ENTRY *new_name = NULL;
231280304Sjkim    int n, i, inc;
232280304Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
23355714Skris
234280304Sjkim    if (name == NULL)
235280304Sjkim        return (0);
236280304Sjkim    sk = name->entries;
237280304Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
238280304Sjkim    if (loc > n)
239280304Sjkim        loc = n;
240280304Sjkim    else if (loc < 0)
241280304Sjkim        loc = n;
24255714Skris
243280304Sjkim    name->modified = 1;
24455714Skris
245280304Sjkim    if (set == -1) {
246280304Sjkim        if (loc == 0) {
247280304Sjkim            set = 0;
248280304Sjkim            inc = 1;
249280304Sjkim        } else {
250280304Sjkim            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
251280304Sjkim            inc = 0;
252280304Sjkim        }
253280304Sjkim    } else {                    /* if (set >= 0) */
25455714Skris
255280304Sjkim        if (loc >= n) {
256280304Sjkim            if (loc != 0)
257280304Sjkim                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
258280304Sjkim            else
259280304Sjkim                set = 0;
260280304Sjkim        } else
261280304Sjkim            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
262280304Sjkim        inc = (set == 0) ? 1 : 0;
263280304Sjkim    }
26455714Skris
265280304Sjkim    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
266280304Sjkim        goto err;
267280304Sjkim    new_name->set = set;
268280304Sjkim    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
269280304Sjkim        X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
270280304Sjkim        goto err;
271280304Sjkim    }
272280304Sjkim    if (inc) {
273280304Sjkim        n = sk_X509_NAME_ENTRY_num(sk);
274280304Sjkim        for (i = loc + 1; i < n; i++)
275280304Sjkim            sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
276280304Sjkim    }
277280304Sjkim    return (1);
278280304Sjkim err:
279280304Sjkim    if (new_name != NULL)
280280304Sjkim        X509_NAME_ENTRY_free(new_name);
281280304Sjkim    return (0);
282280304Sjkim}
283280304Sjkim
28459191SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
285280304Sjkim                                               const char *field, int type,
286280304Sjkim                                               const unsigned char *bytes,
287280304Sjkim                                               int len)
288280304Sjkim{
289280304Sjkim    ASN1_OBJECT *obj;
290280304Sjkim    X509_NAME_ENTRY *nentry;
29159191Skris
292280304Sjkim    obj = OBJ_txt2obj(field, 0);
293280304Sjkim    if (obj == NULL) {
294280304Sjkim        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
295280304Sjkim                X509_R_INVALID_FIELD_NAME);
296280304Sjkim        ERR_add_error_data(2, "name=", field);
297280304Sjkim        return (NULL);
298280304Sjkim    }
299280304Sjkim    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
300280304Sjkim    ASN1_OBJECT_free(obj);
301280304Sjkim    return nentry;
302280304Sjkim}
30359191Skris
30455714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
305280304Sjkim                                               int type, unsigned char *bytes,
306280304Sjkim                                               int len)
307280304Sjkim{
308280304Sjkim    ASN1_OBJECT *obj;
309280304Sjkim    X509_NAME_ENTRY *nentry;
31055714Skris
311280304Sjkim    obj = OBJ_nid2obj(nid);
312280304Sjkim    if (obj == NULL) {
313280304Sjkim        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
314280304Sjkim        return (NULL);
315280304Sjkim    }
316280304Sjkim    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
317280304Sjkim    ASN1_OBJECT_free(obj);
318280304Sjkim    return nentry;
319280304Sjkim}
32055714Skris
32155714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
322280304Sjkim                                               ASN1_OBJECT *obj, int type,
323280304Sjkim                                               const unsigned char *bytes,
324280304Sjkim                                               int len)
325280304Sjkim{
326280304Sjkim    X509_NAME_ENTRY *ret;
32755714Skris
328280304Sjkim    if ((ne == NULL) || (*ne == NULL)) {
329280304Sjkim        if ((ret = X509_NAME_ENTRY_new()) == NULL)
330280304Sjkim            return (NULL);
331280304Sjkim    } else
332280304Sjkim        ret = *ne;
33355714Skris
334280304Sjkim    if (!X509_NAME_ENTRY_set_object(ret, obj))
335280304Sjkim        goto err;
336280304Sjkim    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
337280304Sjkim        goto err;
33859191Skris
339280304Sjkim    if ((ne != NULL) && (*ne == NULL))
340280304Sjkim        *ne = ret;
341280304Sjkim    return (ret);
342280304Sjkim err:
343280304Sjkim    if ((ne == NULL) || (ret != *ne))
344280304Sjkim        X509_NAME_ENTRY_free(ret);
345280304Sjkim    return (NULL);
346280304Sjkim}
34755714Skris
34855714Skrisint X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
349280304Sjkim{
350280304Sjkim    if ((ne == NULL) || (obj == NULL)) {
351280304Sjkim        X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
352280304Sjkim                ERR_R_PASSED_NULL_PARAMETER);
353280304Sjkim        return (0);
354280304Sjkim    }
355280304Sjkim    ASN1_OBJECT_free(ne->object);
356280304Sjkim    ne->object = OBJ_dup(obj);
357280304Sjkim    return ((ne->object == NULL) ? 0 : 1);
358280304Sjkim}
35955714Skris
36055714Skrisint X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
361280304Sjkim                             const unsigned char *bytes, int len)
362280304Sjkim{
363280304Sjkim    int i;
36455714Skris
365280304Sjkim    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
366280304Sjkim        return (0);
367280304Sjkim    if ((type > 0) && (type & MBSTRING_FLAG))
368280304Sjkim        return ASN1_STRING_set_by_NID(&ne->value, bytes,
369280304Sjkim                                      len, type,
370280304Sjkim                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
371280304Sjkim    if (len < 0)
372280304Sjkim        len = strlen((const char *)bytes);
373280304Sjkim    i = ASN1_STRING_set(ne->value, bytes, len);
374280304Sjkim    if (!i)
375280304Sjkim        return (0);
376280304Sjkim    if (type != V_ASN1_UNDEF) {
377280304Sjkim        if (type == V_ASN1_APP_CHOOSE)
378280304Sjkim            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
379280304Sjkim        else
380280304Sjkim            ne->value->type = type;
381280304Sjkim    }
382280304Sjkim    return (1);
383280304Sjkim}
38455714Skris
38555714SkrisASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
386280304Sjkim{
387280304Sjkim    if (ne == NULL)
388280304Sjkim        return (NULL);
389280304Sjkim    return (ne->object);
390280304Sjkim}
39155714Skris
39255714SkrisASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
393280304Sjkim{
394280304Sjkim    if (ne == NULL)
395280304Sjkim        return (NULL);
396280304Sjkim    return (ne->value);
397280304Sjkim}
398