diff options
| author | schwarze <> | 2021-12-11 22:58:48 +0000 |
|---|---|---|
| committer | schwarze <> | 2021-12-11 22:58:48 +0000 |
| commit | f88e6b60ffe39799ab846173f185ba13ac7dd1f9 (patch) | |
| tree | 532c5bb73c4be67f02e0555a36f578b690062300 /src | |
| parent | e60659e7b74a1e7d2072dbfb90b218a488525589 (diff) | |
| download | openbsd-f88e6b60ffe39799ab846173f185ba13ac7dd1f9.tar.gz openbsd-f88e6b60ffe39799ab846173f185ba13ac7dd1f9.tar.bz2 openbsd-f88e6b60ffe39799ab846173f185ba13ac7dd1f9.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.c | 92 | ||||
| -rw-r--r-- | src/regress/lib/libcrypto/asn1/Makefile | 5 | ||||
| -rw-r--r-- | src/regress/lib/libcrypto/asn1/string_table.c | 128 |
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 | ||
| 66 | static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; | 66 | static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; |
| 67 | |||
| 68 | static ASN1_STRING_TABLE *stable_get(int nid); | ||
| 67 | static void st_free(ASN1_STRING_TABLE *tbl); | 69 | static void st_free(ASN1_STRING_TABLE *tbl); |
| 68 | static int sk_table_cmp(const ASN1_STRING_TABLE * const *a, | 70 | static 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 * | |||
| 235 | ASN1_STRING_TABLE_get(int nid) | 237 | ASN1_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 | |||
| 257 | static ASN1_STRING_TABLE * | ||
| 258 | stable_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 | ||
| 254 | int | 295 | int |
| @@ -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 | ||
| 3 | TESTS = \ | 3 | TESTS = \ |
| 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 | ||
| 12 | PROGS = ${TESTS} | 13 | PROGS = ${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 | |||
| 23 | static int errcount; | ||
| 24 | |||
| 25 | static void | ||
| 26 | report(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 | |||
| 37 | static void | ||
| 38 | stable_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 | |||
| 62 | int | ||
| 63 | main(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 | } | ||
