1*1dcdf01fSchristos /*
2*1dcdf01fSchristos  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
360662d10Schristos  *
4*1dcdf01fSchristos  * Licensed under the OpenSSL license (the "License").  You may not use
5*1dcdf01fSchristos  * this file except in compliance with the License.  You can obtain a copy
6*1dcdf01fSchristos  * in the file LICENSE in the source distribution or at
7*1dcdf01fSchristos  * https://www.openssl.org/source/license.html
860662d10Schristos  */
960662d10Schristos 
1060662d10Schristos #include <stdio.h>
11*1dcdf01fSchristos #include "internal/cryptlib.h"
12*1dcdf01fSchristos #include <openssl/safestack.h>
1360662d10Schristos #include <openssl/asn1.h>
1460662d10Schristos #include <openssl/objects.h>
1560662d10Schristos #include <openssl/evp.h>
1660662d10Schristos #include <openssl/x509.h>
17*1dcdf01fSchristos #include "crypto/x509.h"
1860662d10Schristos 
X509_NAME_get_text_by_NID(X509_NAME * name,int nid,char * buf,int len)1960662d10Schristos int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
2060662d10Schristos {
2160662d10Schristos     ASN1_OBJECT *obj;
2260662d10Schristos 
2360662d10Schristos     obj = OBJ_nid2obj(nid);
2460662d10Schristos     if (obj == NULL)
25*1dcdf01fSchristos         return -1;
26*1dcdf01fSchristos     return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
2760662d10Schristos }
2860662d10Schristos 
X509_NAME_get_text_by_OBJ(X509_NAME * name,const ASN1_OBJECT * obj,char * buf,int len)29*1dcdf01fSchristos int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
30*1dcdf01fSchristos                               char *buf, int len)
3160662d10Schristos {
3260662d10Schristos     int i;
33*1dcdf01fSchristos     const ASN1_STRING *data;
3460662d10Schristos 
3560662d10Schristos     i = X509_NAME_get_index_by_OBJ(name, obj, -1);
3660662d10Schristos     if (i < 0)
37*1dcdf01fSchristos         return -1;
3860662d10Schristos     data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
3960662d10Schristos     if (buf == NULL)
40*1dcdf01fSchristos         return data->length;
41*1dcdf01fSchristos     if (len <= 0)
42*1dcdf01fSchristos         return 0;
43*1dcdf01fSchristos     i = (data->length > (len - 1)) ? (len - 1) : data->length;
4460662d10Schristos     memcpy(buf, data->data, i);
4560662d10Schristos     buf[i] = '\0';
46*1dcdf01fSchristos     return i;
4760662d10Schristos }
4860662d10Schristos 
X509_NAME_entry_count(const X509_NAME * name)49*1dcdf01fSchristos int X509_NAME_entry_count(const X509_NAME *name)
5060662d10Schristos {
5160662d10Schristos     if (name == NULL)
52*1dcdf01fSchristos         return 0;
53*1dcdf01fSchristos     return sk_X509_NAME_ENTRY_num(name->entries);
5460662d10Schristos }
5560662d10Schristos 
X509_NAME_get_index_by_NID(X509_NAME * name,int nid,int lastpos)5660662d10Schristos int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
5760662d10Schristos {
5860662d10Schristos     ASN1_OBJECT *obj;
5960662d10Schristos 
6060662d10Schristos     obj = OBJ_nid2obj(nid);
6160662d10Schristos     if (obj == NULL)
62*1dcdf01fSchristos         return -2;
63*1dcdf01fSchristos     return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
6460662d10Schristos }
6560662d10Schristos 
66*1dcdf01fSchristos /* NOTE: you should be passing -1, not 0 as lastpos */
X509_NAME_get_index_by_OBJ(X509_NAME * name,const ASN1_OBJECT * obj,int lastpos)67*1dcdf01fSchristos int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos)
6860662d10Schristos {
6960662d10Schristos     int n;
7060662d10Schristos     X509_NAME_ENTRY *ne;
7160662d10Schristos     STACK_OF(X509_NAME_ENTRY) *sk;
7260662d10Schristos 
7360662d10Schristos     if (name == NULL)
74*1dcdf01fSchristos         return -1;
7560662d10Schristos     if (lastpos < 0)
7660662d10Schristos         lastpos = -1;
7760662d10Schristos     sk = name->entries;
7860662d10Schristos     n = sk_X509_NAME_ENTRY_num(sk);
7960662d10Schristos     for (lastpos++; lastpos < n; lastpos++) {
8060662d10Schristos         ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
8160662d10Schristos         if (OBJ_cmp(ne->object, obj) == 0)
82*1dcdf01fSchristos             return lastpos;
8360662d10Schristos     }
84*1dcdf01fSchristos     return -1;
8560662d10Schristos }
8660662d10Schristos 
X509_NAME_get_entry(const X509_NAME * name,int loc)87*1dcdf01fSchristos X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
8860662d10Schristos {
8960662d10Schristos     if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
9060662d10Schristos         || loc < 0)
91*1dcdf01fSchristos         return NULL;
92*1dcdf01fSchristos 
93*1dcdf01fSchristos     return sk_X509_NAME_ENTRY_value(name->entries, loc);
9460662d10Schristos }
9560662d10Schristos 
X509_NAME_delete_entry(X509_NAME * name,int loc)9660662d10Schristos X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
9760662d10Schristos {
9860662d10Schristos     X509_NAME_ENTRY *ret;
9960662d10Schristos     int i, n, set_prev, set_next;
10060662d10Schristos     STACK_OF(X509_NAME_ENTRY) *sk;
10160662d10Schristos 
10260662d10Schristos     if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
10360662d10Schristos         || loc < 0)
104*1dcdf01fSchristos         return NULL;
105*1dcdf01fSchristos 
10660662d10Schristos     sk = name->entries;
10760662d10Schristos     ret = sk_X509_NAME_ENTRY_delete(sk, loc);
10860662d10Schristos     n = sk_X509_NAME_ENTRY_num(sk);
10960662d10Schristos     name->modified = 1;
11060662d10Schristos     if (loc == n)
111*1dcdf01fSchristos         return ret;
11260662d10Schristos 
11360662d10Schristos     /* else we need to fixup the set field */
11460662d10Schristos     if (loc != 0)
11560662d10Schristos         set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
11660662d10Schristos     else
11760662d10Schristos         set_prev = ret->set - 1;
11860662d10Schristos     set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
11960662d10Schristos 
12060662d10Schristos     /*-
12160662d10Schristos      * set_prev is the previous set
12260662d10Schristos      * set is the current set
12360662d10Schristos      * set_next is the following
12460662d10Schristos      * prev  1 1    1 1     1 1     1 1
12560662d10Schristos      * set   1      1       2       2
12660662d10Schristos      * next  1 1    2 2     2 2     3 2
12760662d10Schristos      * so basically only if prev and next differ by 2, then
12860662d10Schristos      * re-number down by 1
12960662d10Schristos      */
13060662d10Schristos     if (set_prev + 1 < set_next)
13160662d10Schristos         for (i = loc; i < n; i++)
13260662d10Schristos             sk_X509_NAME_ENTRY_value(sk, i)->set--;
133*1dcdf01fSchristos     return ret;
13460662d10Schristos }
13560662d10Schristos 
X509_NAME_add_entry_by_OBJ(X509_NAME * name,const ASN1_OBJECT * obj,int type,const unsigned char * bytes,int len,int loc,int set)136*1dcdf01fSchristos int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
137*1dcdf01fSchristos                                const unsigned char *bytes, int len, int loc,
13860662d10Schristos                                int set)
13960662d10Schristos {
14060662d10Schristos     X509_NAME_ENTRY *ne;
14160662d10Schristos     int ret;
142*1dcdf01fSchristos 
14360662d10Schristos     ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
14460662d10Schristos     if (!ne)
14560662d10Schristos         return 0;
14660662d10Schristos     ret = X509_NAME_add_entry(name, ne, loc, set);
14760662d10Schristos     X509_NAME_ENTRY_free(ne);
14860662d10Schristos     return ret;
14960662d10Schristos }
15060662d10Schristos 
X509_NAME_add_entry_by_NID(X509_NAME * name,int nid,int type,const unsigned char * bytes,int len,int loc,int set)15160662d10Schristos int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
152*1dcdf01fSchristos                                const unsigned char *bytes, int len, int loc,
15360662d10Schristos                                int set)
15460662d10Schristos {
15560662d10Schristos     X509_NAME_ENTRY *ne;
15660662d10Schristos     int ret;
15760662d10Schristos     ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
15860662d10Schristos     if (!ne)
15960662d10Schristos         return 0;
16060662d10Schristos     ret = X509_NAME_add_entry(name, ne, loc, set);
16160662d10Schristos     X509_NAME_ENTRY_free(ne);
16260662d10Schristos     return ret;
16360662d10Schristos }
16460662d10Schristos 
X509_NAME_add_entry_by_txt(X509_NAME * name,const char * field,int type,const unsigned char * bytes,int len,int loc,int set)16560662d10Schristos int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
16660662d10Schristos                                const unsigned char *bytes, int len, int loc,
16760662d10Schristos                                int set)
16860662d10Schristos {
16960662d10Schristos     X509_NAME_ENTRY *ne;
17060662d10Schristos     int ret;
17160662d10Schristos     ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
17260662d10Schristos     if (!ne)
17360662d10Schristos         return 0;
17460662d10Schristos     ret = X509_NAME_add_entry(name, ne, loc, set);
17560662d10Schristos     X509_NAME_ENTRY_free(ne);
17660662d10Schristos     return ret;
17760662d10Schristos }
17860662d10Schristos 
17960662d10Schristos /*
18060662d10Schristos  * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
18160662d10Schristos  * guy we are about to stomp on.
18260662d10Schristos  */
X509_NAME_add_entry(X509_NAME * name,const X509_NAME_ENTRY * ne,int loc,int set)183*1dcdf01fSchristos int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc,
18460662d10Schristos                         int set)
18560662d10Schristos {
18660662d10Schristos     X509_NAME_ENTRY *new_name = NULL;
18760662d10Schristos     int n, i, inc;
18860662d10Schristos     STACK_OF(X509_NAME_ENTRY) *sk;
18960662d10Schristos 
19060662d10Schristos     if (name == NULL)
191*1dcdf01fSchristos         return 0;
19260662d10Schristos     sk = name->entries;
19360662d10Schristos     n = sk_X509_NAME_ENTRY_num(sk);
19460662d10Schristos     if (loc > n)
19560662d10Schristos         loc = n;
19660662d10Schristos     else if (loc < 0)
19760662d10Schristos         loc = n;
198*1dcdf01fSchristos     inc = (set == 0);
19960662d10Schristos     name->modified = 1;
20060662d10Schristos 
20160662d10Schristos     if (set == -1) {
20260662d10Schristos         if (loc == 0) {
20360662d10Schristos             set = 0;
20460662d10Schristos             inc = 1;
20560662d10Schristos         } else {
20660662d10Schristos             set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
20760662d10Schristos         }
20860662d10Schristos     } else {                    /* if (set >= 0) */
20960662d10Schristos 
21060662d10Schristos         if (loc >= n) {
21160662d10Schristos             if (loc != 0)
21260662d10Schristos                 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
21360662d10Schristos             else
21460662d10Schristos                 set = 0;
21560662d10Schristos         } else
21660662d10Schristos             set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
21760662d10Schristos     }
21860662d10Schristos 
219*1dcdf01fSchristos     /*
220*1dcdf01fSchristos      * X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily
221*1dcdf01fSchristos      * const'ified; harmless cast since dup() don't modify its input.
222*1dcdf01fSchristos      */
223*1dcdf01fSchristos     if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL)
22460662d10Schristos         goto err;
22560662d10Schristos     new_name->set = set;
22660662d10Schristos     if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
22760662d10Schristos         X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
22860662d10Schristos         goto err;
22960662d10Schristos     }
23060662d10Schristos     if (inc) {
23160662d10Schristos         n = sk_X509_NAME_ENTRY_num(sk);
23260662d10Schristos         for (i = loc + 1; i < n; i++)
233*1dcdf01fSchristos             sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
23460662d10Schristos     }
235*1dcdf01fSchristos     return 1;
23660662d10Schristos  err:
23760662d10Schristos     X509_NAME_ENTRY_free(new_name);
238*1dcdf01fSchristos     return 0;
23960662d10Schristos }
24060662d10Schristos 
X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY ** ne,const char * field,int type,const unsigned char * bytes,int len)24160662d10Schristos X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
24260662d10Schristos                                                const char *field, int type,
24360662d10Schristos                                                const unsigned char *bytes,
24460662d10Schristos                                                int len)
24560662d10Schristos {
24660662d10Schristos     ASN1_OBJECT *obj;
24760662d10Schristos     X509_NAME_ENTRY *nentry;
24860662d10Schristos 
24960662d10Schristos     obj = OBJ_txt2obj(field, 0);
25060662d10Schristos     if (obj == NULL) {
25160662d10Schristos         X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
25260662d10Schristos                 X509_R_INVALID_FIELD_NAME);
25360662d10Schristos         ERR_add_error_data(2, "name=", field);
254*1dcdf01fSchristos         return NULL;
25560662d10Schristos     }
25660662d10Schristos     nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
25760662d10Schristos     ASN1_OBJECT_free(obj);
25860662d10Schristos     return nentry;
25960662d10Schristos }
26060662d10Schristos 
X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY ** ne,int nid,int type,const unsigned char * bytes,int len)26160662d10Schristos X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
262*1dcdf01fSchristos                                                int type,
263*1dcdf01fSchristos                                                const unsigned char *bytes,
26460662d10Schristos                                                int len)
26560662d10Schristos {
26660662d10Schristos     ASN1_OBJECT *obj;
26760662d10Schristos     X509_NAME_ENTRY *nentry;
26860662d10Schristos 
26960662d10Schristos     obj = OBJ_nid2obj(nid);
27060662d10Schristos     if (obj == NULL) {
27160662d10Schristos         X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
272*1dcdf01fSchristos         return NULL;
27360662d10Schristos     }
27460662d10Schristos     nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
27560662d10Schristos     ASN1_OBJECT_free(obj);
27660662d10Schristos     return nentry;
27760662d10Schristos }
27860662d10Schristos 
X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY ** ne,const ASN1_OBJECT * obj,int type,const unsigned char * bytes,int len)27960662d10Schristos X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
280*1dcdf01fSchristos                                                const ASN1_OBJECT *obj, int type,
28160662d10Schristos                                                const unsigned char *bytes,
28260662d10Schristos                                                int len)
28360662d10Schristos {
28460662d10Schristos     X509_NAME_ENTRY *ret;
28560662d10Schristos 
28660662d10Schristos     if ((ne == NULL) || (*ne == NULL)) {
28760662d10Schristos         if ((ret = X509_NAME_ENTRY_new()) == NULL)
288*1dcdf01fSchristos             return NULL;
28960662d10Schristos     } else
29060662d10Schristos         ret = *ne;
29160662d10Schristos 
29260662d10Schristos     if (!X509_NAME_ENTRY_set_object(ret, obj))
29360662d10Schristos         goto err;
29460662d10Schristos     if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
29560662d10Schristos         goto err;
29660662d10Schristos 
29760662d10Schristos     if ((ne != NULL) && (*ne == NULL))
29860662d10Schristos         *ne = ret;
299*1dcdf01fSchristos     return ret;
30060662d10Schristos  err:
30160662d10Schristos     if ((ne == NULL) || (ret != *ne))
30260662d10Schristos         X509_NAME_ENTRY_free(ret);
303*1dcdf01fSchristos     return NULL;
30460662d10Schristos }
30560662d10Schristos 
X509_NAME_ENTRY_set_object(X509_NAME_ENTRY * ne,const ASN1_OBJECT * obj)306*1dcdf01fSchristos int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
30760662d10Schristos {
30860662d10Schristos     if ((ne == NULL) || (obj == NULL)) {
30960662d10Schristos         X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
31060662d10Schristos                 ERR_R_PASSED_NULL_PARAMETER);
311*1dcdf01fSchristos         return 0;
31260662d10Schristos     }
31360662d10Schristos     ASN1_OBJECT_free(ne->object);
31460662d10Schristos     ne->object = OBJ_dup(obj);
31560662d10Schristos     return ((ne->object == NULL) ? 0 : 1);
31660662d10Schristos }
31760662d10Schristos 
X509_NAME_ENTRY_set_data(X509_NAME_ENTRY * ne,int type,const unsigned char * bytes,int len)31860662d10Schristos int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
31960662d10Schristos                              const unsigned char *bytes, int len)
32060662d10Schristos {
32160662d10Schristos     int i;
32260662d10Schristos 
32360662d10Schristos     if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
324*1dcdf01fSchristos         return 0;
32560662d10Schristos     if ((type > 0) && (type & MBSTRING_FLAG))
32660662d10Schristos         return ASN1_STRING_set_by_NID(&ne->value, bytes,
32760662d10Schristos                                       len, type,
32860662d10Schristos                                       OBJ_obj2nid(ne->object)) ? 1 : 0;
32960662d10Schristos     if (len < 0)
33060662d10Schristos         len = strlen((const char *)bytes);
33160662d10Schristos     i = ASN1_STRING_set(ne->value, bytes, len);
33260662d10Schristos     if (!i)
333*1dcdf01fSchristos         return 0;
33460662d10Schristos     if (type != V_ASN1_UNDEF) {
33560662d10Schristos         if (type == V_ASN1_APP_CHOOSE)
33660662d10Schristos             ne->value->type = ASN1_PRINTABLE_type(bytes, len);
33760662d10Schristos         else
33860662d10Schristos             ne->value->type = type;
33960662d10Schristos     }
340*1dcdf01fSchristos     return 1;
34160662d10Schristos }
34260662d10Schristos 
X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY * ne)343*1dcdf01fSchristos ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
34460662d10Schristos {
34560662d10Schristos     if (ne == NULL)
346*1dcdf01fSchristos         return NULL;
347*1dcdf01fSchristos     return ne->object;
34860662d10Schristos }
34960662d10Schristos 
X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY * ne)350*1dcdf01fSchristos ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
35160662d10Schristos {
35260662d10Schristos     if (ne == NULL)
353*1dcdf01fSchristos         return NULL;
354*1dcdf01fSchristos     return ne->value;
355*1dcdf01fSchristos }
356*1dcdf01fSchristos 
X509_NAME_ENTRY_set(const X509_NAME_ENTRY * ne)357*1dcdf01fSchristos int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
358*1dcdf01fSchristos {
359*1dcdf01fSchristos     return ne->set;
36060662d10Schristos }
361