summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorschwarze <>2021-12-11 22:58:48 +0000
committerschwarze <>2021-12-11 22:58:48 +0000
commit693b9af2c868379acbde502b0fdd91708ee6da6e (patch)
tree532c5bb73c4be67f02e0555a36f578b690062300 /src
parentba300c78ab7a7a24256b3e243db2e3f84ada4c14 (diff)
downloadopenbsd-693b9af2c868379acbde502b0fdd91708ee6da6e.tar.gz
openbsd-693b9af2c868379acbde502b0fdd91708ee6da6e.tar.bz2
openbsd-693b9af2c868379acbde502b0fdd91708ee6da6e.zip
Merge two bugfixes in ASN1_STRING_TABLE_add(3) and ASN1_STRING_TABLE_get(3)
from the OpenSSL 1.1.1 branch, which is still under a free license, mostly this commit: commit d35c0ff30b31be9fd5dcf3d552a16feb8de464bc Author: Dr. Stephen Henson <steve@openssl.org> Date: Fri Oct 19 15:06:31 2012 +0000 fix ASN1_STRING_TABLE_add so it can override existing string table values This fixes a segfault in ASN1_STRING_TABLE_add(3), which tried to change a static const entry when called with an nid already in the default table, and it switches the precedence of the two tables in ASN1_STRING_TABLE_get(3). In addition, it changes behaviour in the following minor ways: * Ignore negative minsize and maxsize arguments, not just -1. * Ignore a zero mask and zero flags. It's unclear whether these additional changes make the API absolutely better, but we want compatibility with OpenSSL in these functions. Tweaks & OK tb@.
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/asn1/a_strnid.c92
-rw-r--r--src/regress/lib/libcrypto/asn1/Makefile5
-rw-r--r--src/regress/lib/libcrypto/asn1/string_table.c128
3 files changed, 189 insertions, 36 deletions
diff --git a/src/lib/libcrypto/asn1/a_strnid.c b/src/lib/libcrypto/asn1/a_strnid.c
index 0cc8dc8428..08043f723b 100644
--- a/src/lib/libcrypto/asn1/a_strnid.c
+++ b/src/lib/libcrypto/asn1/a_strnid.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_strnid.c,v 1.22 2021/12/11 22:34:36 schwarze Exp $ */ 1/* $OpenBSD: a_strnid.c,v 1.23 2021/12/11 22:58:48 schwarze Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 1999. 3 * project 1999.
4 */ 4 */
@@ -64,6 +64,8 @@
64#include <openssl/objects.h> 64#include <openssl/objects.h>
65 65
66static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; 66static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
67
68static ASN1_STRING_TABLE *stable_get(int nid);
67static void st_free(ASN1_STRING_TABLE *tbl); 69static void st_free(ASN1_STRING_TABLE *tbl);
68static int sk_table_cmp(const ASN1_STRING_TABLE * const *a, 70static int sk_table_cmp(const ASN1_STRING_TABLE * const *a,
69 const ASN1_STRING_TABLE * const *b); 71 const ASN1_STRING_TABLE * const *b);
@@ -235,20 +237,59 @@ ASN1_STRING_TABLE *
235ASN1_STRING_TABLE_get(int nid) 237ASN1_STRING_TABLE_get(int nid)
236{ 238{
237 int idx; 239 int idx;
238 ASN1_STRING_TABLE *ttmp;
239 ASN1_STRING_TABLE fnd; 240 ASN1_STRING_TABLE fnd;
240 241
241 fnd.nid = nid; 242 fnd.nid = nid;
242 ttmp = OBJ_bsearch_table(&fnd, tbl_standard, 243 if (stable != NULL) {
244 idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
245 if (idx >= 0)
246 return sk_ASN1_STRING_TABLE_value(stable, idx);
247 }
248 return OBJ_bsearch_table(&fnd, tbl_standard,
243 sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE)); 249 sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE));
244 if (ttmp) 250}
245 return ttmp; 251
246 if (!stable) 252/*
253 * Return a string table pointer which can be modified: either directly
254 * from table or a copy of an internal value added to the table.
255 */
256
257static ASN1_STRING_TABLE *
258stable_get(int nid)
259{
260 ASN1_STRING_TABLE *tmp, *rv;
261
262 /* Always need a string table so allocate one if NULL */
263 if (stable == NULL) {
264 stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
265 if (stable == NULL)
266 return NULL;
267 }
268 tmp = ASN1_STRING_TABLE_get(nid);
269 if (tmp != NULL && (tmp->flags & STABLE_FLAGS_MALLOC) != 0)
270 return tmp;
271
272 if ((rv = calloc(1, sizeof(*rv))) == NULL) {
273 ASN1error(ERR_R_MALLOC_FAILURE);
247 return NULL; 274 return NULL;
248 idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); 275 }
249 if (idx < 0) 276 if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
277 free(rv);
250 return NULL; 278 return NULL;
251 return sk_ASN1_STRING_TABLE_value(stable, idx); 279 }
280 if (tmp != NULL) {
281 rv->nid = tmp->nid;
282 rv->minsize = tmp->minsize;
283 rv->maxsize = tmp->maxsize;
284 rv->mask = tmp->mask;
285 rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
286 } else {
287 rv->nid = nid;
288 rv->minsize = -1;
289 rv->maxsize = -1;
290 rv->flags = STABLE_FLAGS_MALLOC;
291 }
292 return rv;
252} 293}
253 294
254int 295int
@@ -256,37 +297,20 @@ ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask,
256 unsigned long flags) 297 unsigned long flags)
257{ 298{
258 ASN1_STRING_TABLE *tmp; 299 ASN1_STRING_TABLE *tmp;
259 char new_nid = 0;
260 300
261 flags &= ~STABLE_FLAGS_MALLOC; 301 if ((tmp = stable_get(nid)) == NULL) {
262 if (!stable)
263 stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
264 if (!stable) {
265 ASN1error(ERR_R_MALLOC_FAILURE); 302 ASN1error(ERR_R_MALLOC_FAILURE);
266 return 0; 303 return 0;
267 } 304 }
268 if (!(tmp = ASN1_STRING_TABLE_get(nid))) { 305 if (minsize >= 0)
269 tmp = malloc(sizeof(ASN1_STRING_TABLE));
270 if (!tmp) {
271 ASN1error(ERR_R_MALLOC_FAILURE);
272 return 0;
273 }
274 tmp->flags = flags | STABLE_FLAGS_MALLOC;
275 tmp->nid = nid;
276 new_nid = 1;
277 } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
278 if (minsize != -1)
279 tmp->minsize = minsize; 306 tmp->minsize = minsize;
280 if (maxsize != -1) 307 if (maxsize >= 0)
281 tmp->maxsize = maxsize; 308 tmp->maxsize = maxsize;
282 tmp->mask = mask; 309 if (mask != 0)
283 if (new_nid) { 310 tmp->mask = mask;
284 if (sk_ASN1_STRING_TABLE_push(stable, tmp) == 0) { 311 if (flags != 0)
285 free(tmp); 312 tmp->flags = flags | STABLE_FLAGS_MALLOC;
286 ASN1error(ERR_R_MALLOC_FAILURE); 313
287 return 0;
288 }
289 }
290 return 1; 314 return 1;
291} 315}
292 316
diff --git a/src/regress/lib/libcrypto/asn1/Makefile b/src/regress/lib/libcrypto/asn1/Makefile
index 1c4a42b80b..90eca92f8e 100644
--- a/src/regress/lib/libcrypto/asn1/Makefile
+++ b/src/regress/lib/libcrypto/asn1/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.9 2021/12/09 16:30:57 jsing Exp $ 1# $OpenBSD: Makefile,v 1.10 2021/12/11 22:58:48 schwarze Exp $
2 2
3TESTS = \ 3TESTS = \
4 asn1basic \ 4 asn1basic \
@@ -7,7 +7,8 @@ TESTS = \
7 asn1string_copy \ 7 asn1string_copy \
8 asn1time \ 8 asn1time \
9 asn1x509 \ 9 asn1x509 \
10 rfc5280time 10 rfc5280time \
11 string_table
11 12
12PROGS = ${TESTS} 13PROGS = ${TESTS}
13 14
diff --git a/src/regress/lib/libcrypto/asn1/string_table.c b/src/regress/lib/libcrypto/asn1/string_table.c
new file mode 100644
index 0000000000..e80cf0f206
--- /dev/null
+++ b/src/regress/lib/libcrypto/asn1/string_table.c
@@ -0,0 +1,128 @@
1/* $OpenBSD: string_table.c,v 1.1 2021/12/11 22:58:48 schwarze Exp $ */
2/*
3 * Copyright (c) 2021 Ingo Schwarze <schwarze@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <err.h>
19#include <stdarg.h>
20#include <openssl/asn1.h>
21#include <openssl/objects.h>
22
23static int errcount;
24
25static void
26report(const char *fmt, ...)
27{
28 va_list ap;
29
30 va_start(ap, fmt);
31 vwarnx(fmt, ap);
32 va_end(ap);
33
34 errcount++;
35}
36
37static void
38stable_check(const char *testname, ASN1_STRING_TABLE *have,
39 ASN1_STRING_TABLE *want, unsigned long want_flags)
40{
41 if (have == NULL) {
42 report("%s returned NULL", testname);
43 return;
44 }
45 if (have->nid != want->nid)
46 report("%s nid %d, expected %d", testname,
47 have->nid, want->nid);
48 if (have->minsize != want->minsize)
49 report("%s minsize %ld, expected %ld", testname,
50 have->minsize, want->minsize);
51 if (have->maxsize != want->maxsize)
52 report("%s maxsize %ld, expected %ld", testname,
53 have->maxsize, want->maxsize);
54 if (have->mask != want->mask)
55 report("%s mask %lu, expected %lu", testname,
56 have->mask, want->mask);
57 if (have->flags != want_flags)
58 report("%s flags %lu, expected %lu", testname,
59 have->flags, want_flags);
60}
61
62int
63main(void)
64{
65 ASN1_STRING_TABLE orig, mine, *have;
66 int irc;
67
68 orig.nid = NID_name;
69 orig.minsize = 1;
70 orig.maxsize = ub_name;
71 orig.mask = DIRSTRING_TYPE;
72 orig.flags = 0;
73
74 mine.nid = NID_name;
75 mine.minsize = 4;
76 mine.maxsize = 64;
77 mine.mask = B_ASN1_PRINTABLESTRING;
78 mine.flags = STABLE_NO_MASK;
79
80 /* Original entry. */
81
82 have = ASN1_STRING_TABLE_get(orig.nid);
83 stable_check("orig", have, &orig, 0);
84
85 /* Copy, but don't really change. */
86
87 irc = ASN1_STRING_TABLE_add(orig.nid, -1, -1, 0, 0);
88 if (irc != 1)
89 report("set noop returned %d, expected 1", irc);
90 have = ASN1_STRING_TABLE_get(orig.nid);
91 stable_check("noop", have, &orig, STABLE_FLAGS_MALLOC);
92
93 /* Change entry. */
94
95 irc = ASN1_STRING_TABLE_add(mine.nid, mine.minsize, mine.maxsize,
96 mine.mask, mine.flags);
97 if (irc != 1)
98 report("set returned %d, expected 1", irc);
99 have = ASN1_STRING_TABLE_get(mine.nid);
100 stable_check("set", have, &mine, STABLE_FLAGS_MALLOC | STABLE_NO_MASK);
101
102 /* New entry. */
103
104 mine.nid = NID_title;
105 irc = ASN1_STRING_TABLE_add(mine.nid, mine.minsize, mine.maxsize,
106 mine.mask, mine.flags);
107 if (irc != 1)
108 report("new returned %d, expected 1", irc);
109 have = ASN1_STRING_TABLE_get(mine.nid);
110 stable_check("new", have, &mine, STABLE_FLAGS_MALLOC | STABLE_NO_MASK);
111
112 /* Back to the initial state. */
113
114 ASN1_STRING_TABLE_cleanup();
115 have = ASN1_STRING_TABLE_get(orig.nid);
116 stable_check("back", have, &orig, 0);
117 if (ASN1_STRING_TABLE_get(mine.nid) != NULL)
118 report("deleted entry is not NULL");
119
120 switch (errcount) {
121 case 0:
122 return 0;
123 case 1:
124 errx(1, "one error");
125 default:
126 errx(1, "%d errors", errcount);
127 }
128}