1 /* $OpenBSD: exdata_test.c,v 1.3 2024/10/02 14:12:21 jsing Exp $ */
2 /*
3 * Copyright (c) 2023 Joel Sing <jsing@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 <stdio.h>
19 #include <string.h>
20
21 #include <openssl/crypto.h>
22
23 static int ex_new_calls;
24 static int ex_free_calls;
25 static int ex_dup_calls;
26
27 static int
ex_new(void * parent,void * ptr,CRYPTO_EX_DATA * ad,int idx,long argl,void * argp)28 ex_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl,
29 void *argp)
30 {
31 long *arg = argp;
32
33 if (ptr != NULL) {
34 fprintf(stderr, "FAIL: ex_new() called with ptr != NULL\n");
35 return 0;
36 }
37 if (argl != 1234 || *arg != 1234) {
38 fprintf(stderr, "FAIL: ex_new() with bad arguments\n");
39 return 0;
40 }
41
42 ex_new_calls++;
43
44 return 1;
45 }
46
47 static int
ex_dup(CRYPTO_EX_DATA * to,CRYPTO_EX_DATA * from,void * from_d,int idx,long argl,void * argp)48 ex_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
49 int idx, long argl, void *argp)
50 {
51 long *arg = argp;
52
53 if (argl != 1234 || *arg != 1234) {
54 fprintf(stderr, "FAIL: ex_dup() with bad arguments\n");
55 return 0;
56 }
57
58 ex_dup_calls++;
59
60 return 1;
61 }
62
63 static void
ex_free(void * parent,void * ptr,CRYPTO_EX_DATA * ad,int idx,long argl,void * argp)64 ex_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
65 long argl, void *argp)
66 {
67 long *arg = argp;
68
69 if (argl != 1234 || *arg != 1234) {
70 fprintf(stderr, "FAIL: ex_free() with bad arguments\n");
71 return;
72 }
73
74 ex_free_calls++;
75 }
76
77 struct exdata {
78 CRYPTO_EX_DATA exdata;
79 int val;
80 };
81
82 static int
ex_data_test(void)83 ex_data_test(void)
84 {
85 struct exdata exdata1, exdata2, exdata3, exdata4;
86 void *argp;
87 long argl;
88 int idx1, idx2;
89 int failed = 1;
90
91 memset(&exdata1, 0, sizeof(exdata1));
92 memset(&exdata2, 0, sizeof(exdata2));
93 memset(&exdata3, 0, sizeof(exdata3));
94 memset(&exdata4, 0, sizeof(exdata4));
95
96 argl = 1234;
97 argp = &argl;
98
99 if ((idx1 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
100 ex_new, ex_dup, ex_free)) < 0) {
101 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n");
102 goto failure;
103 }
104 if (idx1 == 0) {
105 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned 0 "
106 "(reserved for internal use)\n");
107 goto failure;
108 }
109
110 if ((idx2 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, 0, NULL,
111 NULL, NULL, NULL)) < 0) {
112 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index failed\n");
113 goto failure;
114 }
115 if (idx1 == idx2) {
116 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned the "
117 "same value\n");
118 goto failure;
119 }
120 if (idx2 < idx1) {
121 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() returned "
122 "idx2 < idx1\n");
123 goto failure;
124 }
125
126 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) {
127 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n");
128 goto failure;
129 }
130
131 if (!CRYPTO_set_ex_data(&exdata1.exdata, idx2, &idx2)) {
132 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 2\n");
133 goto failure;
134 }
135 if (!CRYPTO_set_ex_data(&exdata1.exdata, idx1, &idx1)) {
136 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index 1\n");
137 goto failure;
138 }
139 if (CRYPTO_get_ex_data(&exdata1.exdata, idx1) != &idx1) {
140 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 1\n");
141 goto failure;
142 }
143 if (CRYPTO_get_ex_data(&exdata1.exdata, idx2) != &idx2) {
144 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index 2\n");
145 goto failure;
146 }
147
148 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata,
149 &exdata1.exdata)) {
150 fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() failed\n");
151 goto failure;
152 }
153 if (CRYPTO_get_ex_data(&exdata2.exdata, idx1) != &idx1) {
154 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n");
155 goto failure;
156 }
157 if (CRYPTO_get_ex_data(&exdata2.exdata, idx2) != &idx2) {
158 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed after dup\n");
159 goto failure;
160 }
161
162 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata);
163 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata);
164
165 if (ex_new_calls != 1) {
166 fprintf(stderr, "FAIL: got %d ex_new calls, want %d\n",
167 ex_new_calls, 1);
168 goto failure;
169 }
170 if (ex_dup_calls != 1) {
171 fprintf(stderr, "FAIL: got %d ex_dup calls, want %d\n",
172 ex_dup_calls, 1);
173 goto failure;
174 }
175 if (ex_free_calls != 2) {
176 fprintf(stderr, "FAIL: got %d ex_free calls, want %d\n",
177 ex_free_calls, 2);
178 goto failure;
179 }
180
181 /* The current implementation allows for data to be set without new. */
182 if (!CRYPTO_set_ex_data(&exdata3.exdata, idx1, &idx1)) {
183 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index "
184 "1 (without new)\n");
185 goto failure;
186 }
187 if (CRYPTO_get_ex_data(&exdata3.exdata, idx1) != &idx1) {
188 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index "
189 "1 (without new)\n");
190 goto failure;
191 }
192
193 /* And indexes can be used without allocation. */
194 if (!CRYPTO_set_ex_data(&exdata3.exdata, idx2 + 1, &idx2)) {
195 fprintf(stderr, "FAIL: CRYPTO_set_ex_data() failed with index "
196 "%d (unallocated)\n", idx2 + 1);
197 goto failure;
198 }
199 if (CRYPTO_get_ex_data(&exdata3.exdata, idx2 + 1) != &idx2) {
200 fprintf(stderr, "FAIL: CRYPTO_get_ex_data() failed with index "
201 "%d\n", idx2 + 1);
202 goto failure;
203 }
204
205 /* And new can be called without getting any index first. */
206 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata)) {
207 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed with "
208 "uninitialised index\n");
209 goto failure;
210 }
211
212 /* And dup can be called after new or without new... */
213 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata)) {
214 fprintf(stderr, "FAIL: CRYPTO_new_ex_data() failed\n");
215 goto failure;
216 }
217 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2.exdata,
218 &exdata1.exdata)) {
219 fprintf(stderr, "FAIL: CRYPTO_dup_ex_data() after new failed\n");
220 goto failure;
221 }
222
223 failed = 0;
224
225 failure:
226 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata1, &exdata1.exdata);
227 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata2, &exdata2.exdata);
228 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, &exdata3, &exdata3.exdata);
229 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, &exdata4, &exdata4.exdata);
230
231 return failed;
232 }
233
234 static int
ex_new_index_test(void)235 ex_new_index_test(void)
236 {
237 int failed = 1;
238 int idx;
239
240 if ((idx = CRYPTO_get_ex_new_index(-1, 0, NULL, NULL, NULL,
241 NULL)) > 0) {
242 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with "
243 "negative class\n");
244 goto failure;
245 }
246 if ((idx = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX__COUNT, 0,
247 NULL, NULL, NULL, NULL)) > 0) {
248 fprintf(stderr, "FAIL: CRYPTO_get_ex_new_index() succeeded with "
249 "class exceeding maximum\n");
250 goto failure;
251 }
252
253 failed = 0;
254
255 failure:
256 return failed;
257 }
258
259 int
main(int argc,char ** argv)260 main(int argc, char **argv)
261 {
262 int failed = 0;
263
264 failed |= ex_data_test();
265 failed |= ex_new_index_test();
266
267 /* Force a clean up. */
268 CRYPTO_cleanup_all_ex_data();
269
270 return failed;
271 }
272