summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-03-26 19:14:11 +0000
committertb <>2023-03-26 19:14:11 +0000
commit346c49c75dd5682ad10632f41eb38f4aad9df83d (patch)
tree1a394d219c8c10791ecdfd6aff3b3fa92b35ea09
parent9b31f9948a949769a2079f7e09b17226e584993d (diff)
downloadopenbsd-346c49c75dd5682ad10632f41eb38f4aad9df83d.tar.gz
openbsd-346c49c75dd5682ad10632f41eb38f4aad9df83d.tar.bz2
openbsd-346c49c75dd5682ad10632f41eb38f4aad9df83d.zip
Add regress coverage for some BIO_f_asn1() bugs fixed before release
-rw-r--r--src/regress/lib/libcrypto/bio/Makefile3
-rw-r--r--src/regress/lib/libcrypto/bio/bio_asn1.c174
2 files changed, 176 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/bio/Makefile b/src/regress/lib/libcrypto/bio/Makefile
index ee10a60812..11d10bda30 100644
--- a/src/regress/lib/libcrypto/bio/Makefile
+++ b/src/regress/lib/libcrypto/bio/Makefile
@@ -1,5 +1,6 @@
1# $OpenBSD: Makefile,v 1.4 2022/12/08 17:49:02 tb Exp $ 1# $OpenBSD: Makefile,v 1.5 2023/03/26 19:14:11 tb Exp $
2 2
3PROGS += bio_asn1
3PROGS += bio_chain 4PROGS += bio_chain
4PROGS += bio_host 5PROGS += bio_host
5PROGS += bio_mem 6PROGS += bio_mem
diff --git a/src/regress/lib/libcrypto/bio/bio_asn1.c b/src/regress/lib/libcrypto/bio/bio_asn1.c
new file mode 100644
index 0000000000..9ee2bb5341
--- /dev/null
+++ b/src/regress/lib/libcrypto/bio/bio_asn1.c
@@ -0,0 +1,174 @@
1/* $OpenBSD: bio_asn1.c,v 1.1 2023/03/26 19:14:11 tb Exp $ */
2
3/*
4 * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <err.h>
20#include <stdio.h>
21#include <stdlib.h>
22
23#include <openssl/asn1.h>
24#include <openssl/bio.h>
25#include <openssl/pkcs7.h>
26#include <openssl/objects.h>
27
28/*
29 * test_prefix_leak() leaks before asn/bio_asn1.c r1.19.
30 */
31
32static long
33read_leak_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret)
34{
35 int read_return = BIO_CB_READ | BIO_CB_RETURN;
36 char *set_me;
37
38 if ((cmd & read_return) != read_return)
39 return ret;
40
41 set_me = BIO_get_callback_arg(bio);
42 *set_me = 1;
43
44 return 0;
45}
46
47static int
48test_prefix_leak(void)
49{
50 const char *data = "some data\n";
51 BIO *bio_in = NULL, *bio_out = NULL;
52 PKCS7 *pkcs7 = NULL;
53 char set_me = 0;
54 int failed = 1;
55
56 if ((bio_in = BIO_new_mem_buf(data, -1)) == NULL)
57 goto err;
58
59 BIO_set_callback(bio_in, read_leak_cb);
60 BIO_set_callback_arg(bio_in, &set_me);
61
62 if ((pkcs7 = PKCS7_new()) == NULL)
63 goto err;
64 if (!PKCS7_set_type(pkcs7, NID_pkcs7_data))
65 goto err;
66
67 if ((bio_out = BIO_new(BIO_s_mem())) == NULL)
68 goto err;
69
70 if (!i2d_ASN1_bio_stream(bio_out, (ASN1_VALUE *)pkcs7, bio_in,
71 SMIME_STREAM | SMIME_BINARY, &PKCS7_it))
72 goto err;
73
74 if (set_me != 1) {
75 fprintf(stderr, "%s: read_leak_cb didn't set set_me", __func__);
76 goto err;
77 }
78
79 failed = 0;
80
81 err:
82 BIO_free(bio_in);
83 BIO_free(bio_out);
84 PKCS7_free(pkcs7);
85
86 return failed;
87}
88
89/*
90 * test_infinite_loop() would hang before asn/bio_asn1.c r1.18.
91 */
92
93#define SENTINEL (-57)
94
95static long
96inf_loop_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret)
97{
98 int write_return = BIO_CB_WRITE | BIO_CB_RETURN;
99 char *set_me;
100
101 if ((cmd & write_return) != write_return)
102 return ret;
103
104 set_me = BIO_get_callback_arg(bio);
105
106 /* First time around: ASN1_STATE_HEADER_COPY - succeed. */
107 if (*set_me == 0) {
108 *set_me = 1;
109 return ret;
110 }
111
112 /* Second time around: ASN1_STATE_DATA_COPY - return sentinel value. */
113 if (*set_me == 1) {
114 *set_me = 2;
115 return SENTINEL;
116 }
117
118 /* Everything else is unexpected: return EOF. */
119 *set_me = 3;
120
121 return 0;
122
123}
124
125static int
126test_infinite_loop(void)
127{
128 BIO *asn_bio = NULL, *bio = NULL;
129 char set_me = 0;
130 int failed = 1;
131 int write_ret;
132
133 if ((asn_bio = BIO_new(BIO_f_asn1())) == NULL)
134 goto err;
135
136 if ((bio = BIO_new(BIO_s_mem())) == NULL)
137 goto err;
138
139 BIO_set_callback(bio, inf_loop_cb);
140 BIO_set_callback_arg(bio, &set_me);
141
142 if (BIO_push(asn_bio, bio) == NULL) {
143 BIO_free(bio);
144 goto err;
145 }
146
147 if ((write_ret = BIO_write(asn_bio, "foo", 3)) != SENTINEL) {
148 fprintf(stderr, "%s: BIO_write: want %d, got %d", __func__,
149 SENTINEL, write_ret);
150 goto err;
151 }
152
153 if (set_me != 2) {
154 fprintf(stderr, "%s: set_me: %d != 2", __func__, set_me);
155 goto err;
156 }
157
158 failed = 0;
159 err:
160 BIO_free_all(asn_bio);
161
162 return failed;
163}
164
165int
166main(void)
167{
168 int failed = 0;
169
170 failed |= test_prefix_leak();
171 failed |= test_infinite_loop();
172
173 return failed;
174}