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