Coverage Report

Created: 2026-02-22 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/x509/x509name.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
#include "internal/deprecated.h"
10
11
#include <stdio.h>
12
#include "internal/cryptlib.h"
13
#include <openssl/safestack.h>
14
#include <openssl/asn1.h>
15
#include <openssl/objects.h>
16
#include <openssl/evp.h>
17
#include <openssl/x509.h>
18
#include "crypto/x509.h"
19
20
OSSL_BEGIN_ALLOW_DEPRECATED
21
#if !defined(OPENSSL_NO_DEPRECATED_4_0)
22
int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid,
23
    char *buf, int len)
24
0
{
25
0
    ASN1_OBJECT *obj;
26
27
0
    obj = OBJ_nid2obj(nid);
28
0
    if (obj == NULL)
29
0
        return -1;
30
0
    return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
31
0
}
32
33
int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
34
    char *buf, int len)
35
0
{
36
0
    int i;
37
0
    const ASN1_STRING *data;
38
39
0
    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
40
0
    if (i < 0)
41
0
        return -1;
42
0
    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
43
0
    if (buf == NULL)
44
0
        return data->length;
45
0
    if (len <= 0)
46
0
        return 0;
47
0
    i = (data->length > (len - 1)) ? (len - 1) : data->length;
48
0
    memcpy(buf, data->data, i);
49
0
    buf[i] = '\0';
50
0
    return i;
51
0
}
52
#endif /* !defined(OPENSSL_NO_DEPRECATED_4_0) */
53
OSSL_END_ALLOW_DEPRECATED
54
55
int X509_NAME_entry_count(const X509_NAME *name)
56
0
{
57
0
    int ret;
58
59
0
    if (name == NULL)
60
0
        return 0;
61
0
    ret = sk_X509_NAME_ENTRY_num(name->entries);
62
0
    return ret > 0 ? ret : 0;
63
0
}
64
65
int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos)
66
0
{
67
0
    ASN1_OBJECT *obj;
68
69
0
    obj = OBJ_nid2obj(nid);
70
0
    if (obj == NULL)
71
0
        return -2;
72
0
    return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
73
0
}
74
75
/* NOTE: you should be passing -1, not 0 as lastpos */
76
int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
77
    int lastpos)
78
0
{
79
0
    int n;
80
0
    X509_NAME_ENTRY *ne;
81
0
    STACK_OF(X509_NAME_ENTRY) *sk;
82
83
0
    if (name == NULL)
84
0
        return -1;
85
0
    if (lastpos < 0)
86
0
        lastpos = -1;
87
0
    sk = name->entries;
88
0
    n = sk_X509_NAME_ENTRY_num(sk);
89
0
    for (lastpos++; lastpos < n; lastpos++) {
90
0
        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
91
0
        if (OBJ_cmp(ne->object, obj) == 0)
92
0
            return lastpos;
93
0
    }
94
0
    return -1;
95
0
}
96
97
X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
98
0
{
99
0
    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
100
0
        || loc < 0)
101
0
        return NULL;
102
103
0
    return sk_X509_NAME_ENTRY_value(name->entries, loc);
104
0
}
105
106
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
107
0
{
108
0
    X509_NAME_ENTRY *ret;
109
0
    int i, n, set_prev, set_next;
110
0
    STACK_OF(X509_NAME_ENTRY) *sk;
111
112
0
    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
113
0
        || loc < 0)
114
0
        return NULL;
115
116
0
    sk = name->entries;
117
0
    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
118
0
    n = sk_X509_NAME_ENTRY_num(sk);
119
0
    name->modified = 1;
120
0
    if (loc == n)
121
0
        return ret;
122
123
    /* else we need to fixup the set field */
124
0
    if (loc != 0)
125
0
        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
126
0
    else
127
0
        set_prev = ret->set - 1;
128
0
    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
129
130
    /*-
131
     * set_prev is the previous set
132
     * set is the current set
133
     * set_next is the following
134
     * prev  1 1    1 1     1 1     1 1
135
     * set   1      1       2       2
136
     * next  1 1    2 2     2 2     3 2
137
     * so basically only if prev and next differ by 2, then
138
     * re-number down by 1
139
     */
140
0
    if (set_prev + 1 < set_next)
141
0
        for (i = loc; i < n; i++)
142
0
            sk_X509_NAME_ENTRY_value(sk, i)->set--;
143
0
    return ret;
144
0
}
145
146
int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
147
    const unsigned char *bytes, int len, int loc,
148
    int set)
149
0
{
150
0
    X509_NAME_ENTRY *ne;
151
0
    int ret;
152
153
0
    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
154
0
    if (!ne)
155
0
        return 0;
156
0
    ret = X509_NAME_add_entry(name, ne, loc, set);
157
0
    X509_NAME_ENTRY_free(ne);
158
0
    return ret;
159
0
}
160
161
int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
162
    const unsigned char *bytes, int len, int loc,
163
    int set)
164
0
{
165
0
    X509_NAME_ENTRY *ne;
166
0
    int ret;
167
0
    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
168
0
    if (!ne)
169
0
        return 0;
170
0
    ret = X509_NAME_add_entry(name, ne, loc, set);
171
0
    X509_NAME_ENTRY_free(ne);
172
0
    return ret;
173
0
}
174
175
int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
176
    const unsigned char *bytes, int len, int loc,
177
    int set)
178
0
{
179
0
    X509_NAME_ENTRY *ne;
180
0
    int ret;
181
0
    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
182
0
    if (!ne)
183
0
        return 0;
184
0
    ret = X509_NAME_add_entry(name, ne, loc, set);
185
0
    X509_NAME_ENTRY_free(ne);
186
0
    return ret;
187
0
}
188
189
/*
190
 * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
191
 * guy we are about to stomp on.
192
 */
193
int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc,
194
    int set)
195
0
{
196
0
    X509_NAME_ENTRY *new_name = NULL;
197
0
    int n, i, inc;
198
0
    STACK_OF(X509_NAME_ENTRY) *sk;
199
200
0
    if (name == NULL)
201
0
        return 0;
202
0
    sk = name->entries;
203
0
    n = sk_X509_NAME_ENTRY_num(sk);
204
0
    if (loc > n)
205
0
        loc = n;
206
0
    else if (loc < 0)
207
0
        loc = n;
208
0
    inc = (set == 0);
209
0
    name->modified = 1;
210
211
0
    if (set == -1) {
212
0
        if (loc == 0) {
213
0
            set = 0;
214
0
            inc = 1;
215
0
        } else {
216
0
            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
217
0
        }
218
0
    } else { /* if (set >= 0) */
219
220
0
        if (loc >= n) {
221
0
            if (loc != 0)
222
0
                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
223
0
            else
224
0
                set = 0;
225
0
        } else
226
0
            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
227
0
    }
228
229
0
    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
230
0
        goto err;
231
0
    new_name->set = set;
232
0
    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
233
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
234
0
        goto err;
235
0
    }
236
0
    if (inc) {
237
0
        n = sk_X509_NAME_ENTRY_num(sk);
238
0
        for (i = loc + 1; i < n; i++)
239
0
            sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
240
0
    }
241
0
    return 1;
242
0
err:
243
0
    X509_NAME_ENTRY_free(new_name);
244
0
    return 0;
245
0
}
246
247
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
248
    const char *field, int type,
249
    const unsigned char *bytes,
250
    int len)
251
0
{
252
0
    ASN1_OBJECT *obj;
253
0
    X509_NAME_ENTRY *nentry;
254
255
0
    obj = OBJ_txt2obj(field, 0);
256
0
    if (obj == NULL) {
257
0
        ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
258
0
            "name=%s", field);
259
0
        return NULL;
260
0
    }
261
0
    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
262
0
    ASN1_OBJECT_free(obj);
263
0
    return nentry;
264
0
}
265
266
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
267
    int type,
268
    const unsigned char *bytes,
269
    int len)
270
0
{
271
0
    ASN1_OBJECT *obj;
272
0
    X509_NAME_ENTRY *nentry;
273
274
0
    obj = OBJ_nid2obj(nid);
275
0
    if (obj == NULL) {
276
0
        ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
277
0
        return NULL;
278
0
    }
279
0
    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
280
0
    ASN1_OBJECT_free(obj);
281
0
    return nentry;
282
0
}
283
284
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
285
    const ASN1_OBJECT *obj, int type,
286
    const unsigned char *bytes,
287
    int len)
288
0
{
289
0
    X509_NAME_ENTRY *ret;
290
291
0
    if ((ne == NULL) || (*ne == NULL)) {
292
0
        if ((ret = X509_NAME_ENTRY_new()) == NULL)
293
0
            return NULL;
294
0
    } else
295
0
        ret = *ne;
296
297
0
    if (!X509_NAME_ENTRY_set_object(ret, obj))
298
0
        goto err;
299
0
    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
300
0
        goto err;
301
302
0
    if ((ne != NULL) && (*ne == NULL))
303
0
        *ne = ret;
304
0
    return ret;
305
0
err:
306
0
    if ((ne == NULL) || (ret != *ne))
307
0
        X509_NAME_ENTRY_free(ret);
308
0
    return NULL;
309
0
}
310
311
int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
312
0
{
313
0
    if ((ne == NULL) || (obj == NULL)) {
314
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
315
0
        return 0;
316
0
    }
317
0
    ASN1_OBJECT_free(ne->object);
318
0
    ne->object = OBJ_dup(obj);
319
0
    return ((ne->object == NULL) ? 0 : 1);
320
0
}
321
322
int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
323
    const unsigned char *bytes, int len)
324
0
{
325
0
    int i;
326
327
0
    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
328
0
        return 0;
329
0
    if ((type > 0) && (type & MBSTRING_FLAG))
330
0
        return ASN1_STRING_set_by_NID(&ne->value, bytes,
331
0
                   len, type,
332
0
                   OBJ_obj2nid(ne->object))
333
0
            ? 1
334
0
            : 0;
335
0
    if (len < 0)
336
0
        len = (int)strlen((const char *)bytes);
337
0
    i = ASN1_STRING_set(ne->value, bytes, len);
338
0
    if (!i)
339
0
        return 0;
340
0
    if (type != V_ASN1_UNDEF) {
341
0
        if (type == V_ASN1_APP_CHOOSE)
342
0
            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
343
0
        else
344
0
            ne->value->type = type;
345
0
    }
346
0
    return 1;
347
0
}
348
349
ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
350
0
{
351
0
    if (ne == NULL)
352
0
        return NULL;
353
0
    return ne->object;
354
0
}
355
356
ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
357
0
{
358
0
    if (ne == NULL)
359
0
        return NULL;
360
0
    return ne->value;
361
0
}
362
363
int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
364
0
{
365
0
    return ne->set;
366
0
}