Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/a_strnid.c
Line
Count
Source (jump to first uncovered line)
1
/* a_strnid.c */
2
/*
3
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4
 * 1999.
5
 */
6
/* ====================================================================
7
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    licensing@OpenSSL.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
#include <stdio.h>
61
#include <ctype.h>
62
#include "cryptlib.h"
63
#include <openssl/asn1.h>
64
#include <openssl/objects.h>
65
66
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
67
static void st_free(ASN1_STRING_TABLE *tbl);
68
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
69
                        const ASN1_STRING_TABLE *const *b);
70
71
/*
72
 * This is the global mask for the mbstring functions: this is use to mask
73
 * out certain types (such as BMPString and UTF8String) because certain
74
 * software (e.g. Netscape) has problems with them.
75
 */
76
77
static unsigned long global_mask = B_ASN1_UTF8STRING;
78
79
void ASN1_STRING_set_default_mask(unsigned long mask)
80
0
{
81
0
    global_mask = mask;
82
0
}
83
84
unsigned long ASN1_STRING_get_default_mask(void)
85
0
{
86
0
    return global_mask;
87
0
}
88
89
/*-
90
 * This function sets the default to various "flavours" of configuration.
91
 * based on an ASCII string. Currently this is:
92
 * MASK:XXXX : a numerical mask value.
93
 * nobmp : Don't use BMPStrings (just Printable, T61).
94
 * pkix : PKIX recommendation in RFC2459.
95
 * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
96
 * default:   the default value, Printable, T61, BMP.
97
 */
98
99
int ASN1_STRING_set_default_mask_asc(const char *p)
100
0
{
101
0
    unsigned long mask;
102
0
    char *end;
103
0
    if (!strncmp(p, "MASK:", 5)) {
104
0
        if (!p[5])
105
0
            return 0;
106
0
        mask = strtoul(p + 5, &end, 0);
107
0
        if (*end)
108
0
            return 0;
109
0
    } else if (!strcmp(p, "nombstr"))
110
0
        mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
111
0
    else if (!strcmp(p, "pkix"))
112
0
        mask = ~((unsigned long)B_ASN1_T61STRING);
113
0
    else if (!strcmp(p, "utf8only"))
114
0
        mask = B_ASN1_UTF8STRING;
115
0
    else if (!strcmp(p, "default"))
116
0
        mask = 0xFFFFFFFFL;
117
0
    else
118
0
        return 0;
119
0
    ASN1_STRING_set_default_mask(mask);
120
0
    return 1;
121
0
}
122
123
/*
124
 * The following function generates an ASN1_STRING based on limits in a
125
 * table. Frequently the types and length of an ASN1_STRING are restricted by
126
 * a corresponding OID. For example certificates and certificate requests.
127
 */
128
129
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
130
                                    const unsigned char *in, int inlen,
131
                                    int inform, int nid)
132
0
{
133
0
    ASN1_STRING_TABLE *tbl;
134
0
    ASN1_STRING *str = NULL;
135
0
    unsigned long mask;
136
0
    int ret;
137
0
    if (!out)
138
0
        out = &str;
139
0
    tbl = ASN1_STRING_TABLE_get(nid);
140
0
    if (tbl) {
141
0
        mask = tbl->mask;
142
0
        if (!(tbl->flags & STABLE_NO_MASK))
143
0
            mask &= global_mask;
144
0
        ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
145
0
                                  tbl->minsize, tbl->maxsize);
146
0
    } else
147
0
        ret =
148
0
            ASN1_mbstring_copy(out, in, inlen, inform,
149
0
                               DIRSTRING_TYPE & global_mask);
150
0
    if (ret <= 0)
151
0
        return NULL;
152
0
    return *out;
153
0
}
154
155
/*
156
 * Now the tables and helper functions for the string table:
157
 */
158
159
/* size limits: this stuff is taken straight from RFC3280 */
160
161
#define ub_name                         32768
162
#define ub_common_name                  64
163
#define ub_locality_name                128
164
#define ub_state_name                   128
165
#define ub_organization_name            64
166
#define ub_organization_unit_name       64
167
#define ub_title                        64
168
#define ub_email_address                128
169
#define ub_serial_number                64
170
171
/* This table must be kept in NID order */
172
173
static const ASN1_STRING_TABLE tbl_standard[] = {
174
    {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
175
    {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
176
    {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
177
    {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
178
    {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
179
    {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
180
     0},
181
    {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
182
     STABLE_NO_MASK},
183
    {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
184
    {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
185
    {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
186
    {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
187
    {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
188
    {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
189
    {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
190
     STABLE_NO_MASK},
191
    {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
192
    {NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
193
    {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
194
    {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
195
    {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
196
    {NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}
197
};
198
199
static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
200
                        const ASN1_STRING_TABLE *const *b)
201
0
{
202
0
    return (*a)->nid - (*b)->nid;
203
0
}
204
205
DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
206
207
static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
208
0
{
209
0
    return a->nid - b->nid;
210
0
}
211
212
IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
213
214
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
215
0
{
216
0
    int idx;
217
0
    ASN1_STRING_TABLE *ttmp;
218
0
    ASN1_STRING_TABLE fnd;
219
0
    fnd.nid = nid;
220
0
    ttmp = OBJ_bsearch_table(&fnd, tbl_standard,
221
0
                             sizeof(tbl_standard) /
222
0
                             sizeof(ASN1_STRING_TABLE));
223
0
    if (ttmp)
224
0
        return ttmp;
225
0
    if (!stable)
226
0
        return NULL;
227
0
    idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
228
0
    if (idx < 0)
229
0
        return NULL;
230
0
    return sk_ASN1_STRING_TABLE_value(stable, idx);
231
0
}
232
233
int ASN1_STRING_TABLE_add(int nid,
234
                          long minsize, long maxsize, unsigned long mask,
235
                          unsigned long flags)
236
0
{
237
0
    ASN1_STRING_TABLE *tmp;
238
0
    char new_nid = 0;
239
0
    flags &= ~STABLE_FLAGS_MALLOC;
240
0
    if (!stable)
241
0
        stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
242
0
    if (!stable) {
243
0
        ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
244
0
        return 0;
245
0
    }
246
0
    if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
247
0
        tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
248
0
        if (!tmp) {
249
0
            ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
250
0
            return 0;
251
0
        }
252
0
        tmp->flags = flags | STABLE_FLAGS_MALLOC;
253
0
        tmp->nid = nid;
254
0
        tmp->minsize = tmp->maxsize = -1;
255
0
        new_nid = 1;
256
0
    } else
257
0
        tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
258
0
    if (minsize != -1)
259
0
        tmp->minsize = minsize;
260
0
    if (maxsize != -1)
261
0
        tmp->maxsize = maxsize;
262
0
    tmp->mask = mask;
263
0
    if (new_nid)
264
0
        sk_ASN1_STRING_TABLE_push(stable, tmp);
265
0
    return 1;
266
0
}
267
268
void ASN1_STRING_TABLE_cleanup(void)
269
0
{
270
0
    STACK_OF(ASN1_STRING_TABLE) *tmp;
271
0
    tmp = stable;
272
0
    if (!tmp)
273
0
        return;
274
0
    stable = NULL;
275
0
    sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
276
0
}
277
278
static void st_free(ASN1_STRING_TABLE *tbl)
279
0
{
280
0
    if (tbl->flags & STABLE_FLAGS_MALLOC)
281
0
        OPENSSL_free(tbl);
282
0
}
283
284
285
IMPLEMENT_STACK_OF(ASN1_STRING_TABLE)
286
287
#ifdef STRING_TABLE_TEST
288
289
main()
290
{
291
    ASN1_STRING_TABLE *tmp;
292
    int i, last_nid = -1;
293
294
    for (tmp = tbl_standard, i = 0;
295
         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
296
        if (tmp->nid < last_nid) {
297
            last_nid = 0;
298
            break;
299
        }
300
        last_nid = tmp->nid;
301
    }
302
303
    if (last_nid != 0) {
304
        printf("Table order OK\n");
305
        exit(0);
306
    }
307
308
    for (tmp = tbl_standard, i = 0;
309
         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
310
        printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
311
               OBJ_nid2ln(tmp->nid));
312
313
}
314
315
#endif