Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl40/crypto/x509/x509name.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2026 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
114k
{
57
114k
    int ret;
58
59
114k
    if (name == NULL)
60
0
        return 0;
61
114k
    ret = sk_X509_NAME_ENTRY_num(name->entries);
62
114k
    return ret > 0 ? ret : 0;
63
114k
}
64
65
int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos)
66
536
{
67
536
    ASN1_OBJECT *obj;
68
69
536
    obj = OBJ_nid2obj(nid);
70
536
    if (obj == NULL)
71
0
        return -2;
72
536
    return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
73
536
}
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
536
{
79
536
    int n;
80
536
    X509_NAME_ENTRY *ne;
81
536
    STACK_OF(X509_NAME_ENTRY) *sk;
82
83
536
    if (name == NULL)
84
0
        return -1;
85
536
    if (lastpos < 0)
86
390
        lastpos = -1;
87
536
    sk = name->entries;
88
536
    n = sk_X509_NAME_ENTRY_num(sk);
89
751
    for (lastpos++; lastpos < n; lastpos++) {
90
377
        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
91
377
        if (OBJ_cmp(ne->object, obj) == 0)
92
162
            return lastpos;
93
377
    }
94
374
    return -1;
95
536
}
96
97
const X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
98
213k
{
99
213k
    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
100
210k
        || loc < 0)
101
2.37k
        return NULL;
102
103
210k
    return sk_X509_NAME_ENTRY_value(name->entries, loc);
104
213k
}
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
5.01k
{
179
5.01k
    X509_NAME_ENTRY *ne;
180
5.01k
    int ret;
181
5.01k
    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
182
5.01k
    if (!ne)
183
63
        return 0;
184
4.95k
    ret = X509_NAME_add_entry(name, ne, loc, set);
185
4.95k
    X509_NAME_ENTRY_free(ne);
186
4.95k
    return ret;
187
5.01k
}
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
18.1k
{
196
18.1k
    X509_NAME_ENTRY *new_name = NULL;
197
18.1k
    int n, i, inc;
198
18.1k
    STACK_OF(X509_NAME_ENTRY) *sk;
199
200
18.1k
    if (name == NULL)
201
0
        return 0;
202
18.1k
    sk = name->entries;
203
18.1k
    n = sk_X509_NAME_ENTRY_num(sk);
204
18.1k
    if (loc > n)
205
0
        loc = n;
206
18.1k
    else if (loc < 0)
207
18.1k
        loc = n;
208
18.1k
    inc = (set == 0);
209
18.1k
    name->modified = 1;
210
211
18.1k
    if (set == -1) {
212
1.69k
        if (loc == 0) {
213
255
            set = 0;
214
255
            inc = 1;
215
1.43k
        } else {
216
1.43k
            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
217
1.43k
        }
218
16.4k
    } else { /* if (set >= 0) */
219
220
16.4k
        if (loc >= n) {
221
16.4k
            if (loc != 0)
222
10.9k
                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
223
5.49k
            else
224
5.49k
                set = 0;
225
16.4k
        } else
226
0
            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
227
16.4k
    }
228
229
18.1k
    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
230
4
        goto err;
231
18.1k
    new_name->set = set;
232
18.1k
    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
18.1k
    if (inc) {
237
8.74k
        n = sk_X509_NAME_ENTRY_num(sk);
238
8.74k
        for (i = loc + 1; i < n; i++)
239
0
            sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
240
8.74k
    }
241
18.1k
    return 1;
242
4
err:
243
4
    X509_NAME_ENTRY_free(new_name);
244
4
    return 0;
245
18.1k
}
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
5.01k
{
252
5.01k
    ASN1_OBJECT *obj;
253
5.01k
    X509_NAME_ENTRY *nentry;
254
255
5.01k
    obj = OBJ_txt2obj(field, 0);
256
5.01k
    if (obj == NULL) {
257
47
        ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
258
47
            "name=%s", field);
259
47
        return NULL;
260
47
    }
261
4.97k
    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
262
4.97k
    ASN1_OBJECT_free(obj);
263
4.97k
    return nentry;
264
5.01k
}
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
4.97k
{
289
4.97k
    X509_NAME_ENTRY *ret;
290
291
4.97k
    if ((ne == NULL) || (*ne == NULL)) {
292
4.97k
        if ((ret = X509_NAME_ENTRY_new()) == NULL)
293
0
            return NULL;
294
4.97k
    } else
295
0
        ret = *ne;
296
297
4.97k
    if (!X509_NAME_ENTRY_set_object(ret, obj))
298
0
        goto err;
299
4.97k
    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
300
16
        goto err;
301
302
4.95k
    if ((ne != NULL) && (*ne == NULL))
303
0
        *ne = ret;
304
4.95k
    return ret;
305
16
err:
306
16
    if ((ne == NULL) || (ret != *ne))
307
16
        X509_NAME_ENTRY_free(ret);
308
16
    return NULL;
309
4.97k
}
310
311
int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
312
4.97k
{
313
4.97k
    if ((ne == NULL) || (obj == NULL)) {
314
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
315
0
        return 0;
316
0
    }
317
4.97k
    ASN1_OBJECT_free(ne->object);
318
4.97k
    ne->object = OBJ_dup(obj);
319
4.97k
    return ((ne->object == NULL) ? 0 : 1);
320
4.97k
}
321
322
int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
323
    const unsigned char *bytes, int len)
324
{
325
    int i;
326
327
    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
328
        return 0;
329
    if ((type > 0) && (type & MBSTRING_FLAG))
330
        return ASN1_STRING_set_by_NID(&ne->value, bytes,
331
                   len, type,
332
                   OBJ_obj2nid(ne->object))
333
            ? 1
334
            : 0;
335
    if (len < 0)
336
        len = (int)strlen((const char *)bytes);
337
    i = ASN1_STRING_set(ne->value, bytes, len);
338
    if (!i)
339
        return 0;
340
    if (type != V_ASN1_UNDEF) {
341
        if (type == V_ASN1_APP_CHOOSE)
342
            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
343
        else
344
            ne->value->type = type;
345
    }
346
    return 1;
347
}
348
349
const ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
350
210k
{
351
210k
    if (ne == NULL)
352
0
        return NULL;
353
210k
    return ne->object;
354
210k
}
355
356
const ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
357
210k
{
358
210k
    if (ne == NULL)
359
0
        return NULL;
360
210k
    return ne->value;
361
210k
}
362
363
int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
364
343k
{
365
343k
    return ne->set;
366
343k
}