xref: /src/crypto/openssl/test/safe_math_test.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 /*
14  * Uncomment this if the fallback non-builtin overflow checking is to
15  * be tested.
16  */
17 /*#define OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING*/
18 
19 #include "internal/nelem.h"
20 #include "internal/safe_math.h"
21 #include "testutil.h"
22 
23 /* Create the safe math instances we're interested in */
24 OSSL_SAFE_MATH_SIGNED(int, int)
25 OSSL_SAFE_MATH_UNSIGNED(uint, unsigned int)
26 OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
27 
28 static const struct {
29     int a, b;
30     int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
31     int neg_a_err, neg_b_err, abs_a_err, abs_b_err;
32 } test_ints[] = {
33     /*  +  -  *  /  %  /r -a -b |a||b|  */
34     { 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
35     { -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
36     { 1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
37     { -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
38     { 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
39     { -3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
40     { 2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
41     { -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
42     { INT_MAX, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
43     { INT_MAX, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
44     { INT_MAX, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
45     { INT_MAX - 3, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
46     { INT_MIN, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 },
47     { 1, INT_MIN, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 },
48     { INT_MIN, 2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
49     { 2, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
50     { INT_MIN, -1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0 },
51     { INT_MAX, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
52     { INT_MIN, INT_MAX, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
53     { 3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
54 };
55 
test_int_ops(int n)56 static int test_int_ops(int n)
57 {
58     int err, r, s;
59     const int a = test_ints[n].a, b = test_ints[n].b;
60 
61     err = 0;
62     r = safe_add_int(a, b, &err);
63     if (!TEST_int_eq(err, test_ints[n].sum_err)
64         || (!err && !TEST_int_eq(r, a + b)))
65         goto err;
66 
67     err = 0;
68     r = safe_sub_int(a, b, &err);
69     if (!TEST_int_eq(err, test_ints[n].sub_err)
70         || (!err && !TEST_int_eq(r, a - b)))
71         goto err;
72 
73     err = 0;
74     r = safe_mul_int(a, b, &err);
75     if (!TEST_int_eq(err, test_ints[n].mul_err)
76         || (!err && !TEST_int_eq(r, a * b)))
77         goto err;
78 
79     err = 0;
80     r = safe_div_int(a, b, &err);
81     if (!TEST_int_eq(err, test_ints[n].div_err)
82         || (!err && !TEST_int_eq(r, a / b)))
83         goto err;
84 
85     err = 0;
86     r = safe_mod_int(a, b, &err);
87     if (!TEST_int_eq(err, test_ints[n].mod_err)
88         || (!err && !TEST_int_eq(r, a % b)))
89         goto err;
90 
91     err = 0;
92     r = safe_div_round_up_int(a, b, &err);
93     if (!TEST_int_eq(err, test_ints[n].div_round_up_err))
94         goto err;
95     s = safe_mod_int(a, b, &err);
96     s = safe_add_int(safe_div_int(a, b, &err), s != 0, &err);
97     if (!err && !TEST_int_eq(r, s))
98         goto err;
99 
100     err = 0;
101     r = safe_neg_int(a, &err);
102     if (!TEST_int_eq(err, test_ints[n].neg_a_err)
103         || (!err && !TEST_int_eq(r, -a)))
104         goto err;
105 
106     err = 0;
107     r = safe_neg_int(b, &err);
108     if (!TEST_int_eq(err, test_ints[n].neg_b_err)
109         || (!err && !TEST_int_eq(r, -b)))
110         goto err;
111 
112     err = 0;
113     r = safe_abs_int(a, &err);
114     if (!TEST_int_eq(err, test_ints[n].abs_a_err)
115         || (!err && !TEST_int_eq(r, a < 0 ? -a : a)))
116         goto err;
117 
118     err = 0;
119     r = safe_abs_int(b, &err);
120     if (!TEST_int_eq(err, test_ints[n].abs_b_err)
121         || (!err && !TEST_int_eq(r, b < 0 ? -b : b)))
122         goto err;
123     return 1;
124 err:
125     TEST_info("a = %d  b = %d  r = %d  err = %d", a, b, r, err);
126     return 0;
127 }
128 
129 static const struct {
130     unsigned int a, b;
131     int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
132 } test_uints[] = {
133     /*  +  -  *  /  %  /r   */
134     { 3, 1, 0, 0, 0, 0, 0, 0 },
135     { 1, 3, 0, 1, 0, 0, 0, 0 },
136     { UINT_MAX, 1, 1, 0, 0, 0, 0, 0 },
137     { UINT_MAX, 2, 1, 0, 1, 0, 0, 0 },
138     { UINT_MAX, 16, 1, 0, 1, 0, 0, 0 },
139     { UINT_MAX - 13, 16, 1, 0, 1, 0, 0, 0 },
140     { 1, UINT_MAX, 1, 1, 0, 0, 0, 0 },
141     { 2, UINT_MAX, 1, 1, 1, 0, 0, 0 },
142     { UINT_MAX, 0, 0, 0, 0, 1, 1, 1 },
143 };
144 
test_uint_ops(int n)145 static int test_uint_ops(int n)
146 {
147     int err;
148     unsigned int r;
149     const unsigned int a = test_uints[n].a, b = test_uints[n].b;
150 
151     err = 0;
152     r = safe_add_uint(a, b, &err);
153     if (!TEST_int_eq(err, test_uints[n].sum_err)
154         || (!err && !TEST_uint_eq(r, a + b)))
155         goto err;
156 
157     err = 0;
158     r = safe_sub_uint(a, b, &err);
159     if (!TEST_int_eq(err, test_uints[n].sub_err)
160         || (!err && !TEST_uint_eq(r, a - b)))
161         goto err;
162 
163     err = 0;
164     r = safe_mul_uint(a, b, &err);
165     if (!TEST_int_eq(err, test_uints[n].mul_err)
166         || (!err && !TEST_uint_eq(r, a * b)))
167         goto err;
168 
169     err = 0;
170     r = safe_div_uint(a, b, &err);
171     if (!TEST_int_eq(err, test_uints[n].div_err)
172         || (!err && !TEST_uint_eq(r, a / b)))
173         goto err;
174 
175     err = 0;
176     r = safe_mod_uint(a, b, &err);
177     if (!TEST_int_eq(err, test_uints[n].mod_err)
178         || (!err && !TEST_uint_eq(r, a % b)))
179         goto err;
180 
181     err = 0;
182     r = safe_div_round_up_uint(a, b, &err);
183     if (!TEST_int_eq(err, test_uints[n].div_round_up_err)
184         || (!err && !TEST_uint_eq(r, a / b + (a % b != 0))))
185         goto err;
186 
187     err = 0;
188     r = safe_neg_uint(a, &err);
189     if (!TEST_int_eq(err, a != 0) || (!err && !TEST_uint_eq(r, 0)))
190         goto err;
191 
192     err = 0;
193     r = safe_neg_uint(b, &err);
194     if (!TEST_int_eq(err, b != 0) || (!err && !TEST_uint_eq(r, 0)))
195         goto err;
196 
197     err = 0;
198     r = safe_abs_uint(a, &err);
199     if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, a))
200         goto err;
201 
202     err = 0;
203     r = safe_abs_uint(b, &err);
204     if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, b))
205         goto err;
206     return 1;
207 err:
208     TEST_info("a = %u  b = %u  r = %u  err = %d", a, b, r, err);
209     return 0;
210 }
211 
212 static const struct {
213     size_t a, b;
214     int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
215 } test_size_ts[] = {
216     { 3, 1, 0, 0, 0, 0, 0, 0 },
217     { 1, 3, 0, 1, 0, 0, 0, 0 },
218     { 36, 8, 0, 0, 0, 0, 0, 0 },
219     { SIZE_MAX, 1, 1, 0, 0, 0, 0, 0 },
220     { SIZE_MAX, 2, 1, 0, 1, 0, 0, 0 },
221     { SIZE_MAX, 8, 1, 0, 1, 0, 0, 0 },
222     { SIZE_MAX - 3, 8, 1, 0, 1, 0, 0, 0 },
223     { 1, SIZE_MAX, 1, 1, 0, 0, 0, 0 },
224     { 2, SIZE_MAX, 1, 1, 1, 0, 0, 0 },
225     { 11, 0, 0, 0, 0, 1, 1, 1 },
226 };
227 
test_size_t_ops(int n)228 static int test_size_t_ops(int n)
229 {
230     int err;
231     size_t r;
232     const size_t a = test_size_ts[n].a, b = test_size_ts[n].b;
233 
234     err = 0;
235     r = safe_add_size_t(a, b, &err);
236     if (!TEST_int_eq(err, test_size_ts[n].sum_err)
237         || (!err && !TEST_size_t_eq(r, a + b)))
238         goto err;
239 
240     err = 0;
241     r = safe_sub_size_t(a, b, &err);
242     if (!TEST_int_eq(err, test_size_ts[n].sub_err)
243         || (!err && !TEST_size_t_eq(r, a - b)))
244         goto err;
245 
246     err = 0;
247     r = safe_mul_size_t(a, b, &err);
248     if (!TEST_int_eq(err, test_size_ts[n].mul_err)
249         || (!err && !TEST_size_t_eq(r, a * b)))
250         goto err;
251 
252     err = 0;
253     r = safe_div_size_t(a, b, &err);
254     if (!TEST_int_eq(err, test_size_ts[n].div_err)
255         || (!err && !TEST_size_t_eq(r, a / b)))
256         goto err;
257 
258     err = 0;
259     r = safe_mod_size_t(a, b, &err);
260     if (!TEST_int_eq(err, test_size_ts[n].mod_err)
261         || (!err && !TEST_size_t_eq(r, a % b)))
262         goto err;
263 
264     err = 0;
265     r = safe_div_round_up_size_t(a, b, &err);
266     if (!TEST_int_eq(err, test_size_ts[n].div_round_up_err)
267         || (!err && !TEST_size_t_eq(r, a / b + (a % b != 0))))
268         goto err;
269 
270     err = 0;
271     r = safe_neg_size_t(a, &err);
272     if (!TEST_int_eq(err, a != 0) || (!err && !TEST_size_t_eq(r, 0)))
273         goto err;
274 
275     err = 0;
276     r = safe_neg_size_t(b, &err);
277     if (!TEST_int_eq(err, b != 0) || (!err && !TEST_size_t_eq(r, 0)))
278         goto err;
279 
280     err = 0;
281     r = safe_abs_size_t(a, &err);
282     if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, a))
283         goto err;
284 
285     err = 0;
286     r = safe_abs_size_t(b, &err);
287     if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, b))
288         goto err;
289     return 1;
290 err:
291     TEST_info("a = %zu  b = %zu  r = %zu  err = %d", a, b, r, err);
292     return 0;
293 }
294 
295 static const struct {
296     int a, b, c;
297     int err;
298 } test_muldiv_ints[] = {
299     { 3, 1, 2, 0 },
300     { 1, 3, 2, 0 },
301     { -3, 1, 2, 0 },
302     { 1, 3, -2, 0 },
303     { INT_MAX, INT_MAX, INT_MAX, 0 },
304     { INT_MIN, INT_MIN, INT_MAX, 1 },
305     { INT_MIN, INT_MIN, INT_MIN, 0 },
306     { INT_MAX, 2, 4, 0 },
307     { 8, INT_MAX, 4, 1 },
308     { INT_MAX, 8, 4, 1 },
309     { INT_MIN, 2, 4, 1 },
310     { 8, INT_MIN, 4, 1 },
311     { INT_MIN, 8, 4, 1 },
312     { 3, 4, 0, 1 },
313 };
314 
test_int_muldiv(int n)315 static int test_int_muldiv(int n)
316 {
317     int err = 0;
318     int r, real = 0;
319     const int a = test_muldiv_ints[n].a;
320     const int b = test_muldiv_ints[n].b;
321     const int c = test_muldiv_ints[n].c;
322 
323     r = safe_muldiv_int(a, b, c, &err);
324     if (c != 0)
325         real = (int)((int64_t)a * (int64_t)b / (int64_t)c);
326     if (!TEST_int_eq(err, test_muldiv_ints[n].err)
327         || (!err && !TEST_int_eq(r, real))) {
328         TEST_info("%d * %d / %d  r = %d  err = %d", a, b, c, r, err);
329         return 0;
330     }
331     return 1;
332 }
333 
334 static const struct {
335     unsigned int a, b, c;
336     int err;
337 } test_muldiv_uints[] = {
338     { 3, 1, 2, 0 },
339     { 1, 3, 2, 0 },
340     { UINT_MAX, UINT_MAX, UINT_MAX, 0 },
341     { UINT_MAX, 2, 4, 0 },
342     { 8, UINT_MAX, 4, 1 },
343     { UINT_MAX, 8, 4, 1 },
344     { 3, 4, 0, 1 },
345 };
346 
test_uint_muldiv(int n)347 static int test_uint_muldiv(int n)
348 {
349     int err = 0;
350     unsigned int r, real = 0;
351     const unsigned int a = test_muldiv_uints[n].a;
352     const unsigned int b = test_muldiv_uints[n].b;
353     const unsigned int c = test_muldiv_uints[n].c;
354 
355     r = safe_muldiv_uint(a, b, c, &err);
356     if (c != 0)
357         real = (unsigned int)((uint64_t)a * (uint64_t)b / (uint64_t)c);
358     if (!TEST_int_eq(err, test_muldiv_uints[n].err)
359         || (!err && !TEST_uint_eq(r, real))) {
360         TEST_info("%u * %u / %u  r = %u  err = %d", a, b, c, r, err);
361         return 0;
362     }
363     return 1;
364 }
365 
setup_tests(void)366 int setup_tests(void)
367 {
368     ADD_ALL_TESTS(test_int_ops, OSSL_NELEM(test_ints));
369     ADD_ALL_TESTS(test_uint_ops, OSSL_NELEM(test_uints));
370     ADD_ALL_TESTS(test_size_t_ops, OSSL_NELEM(test_size_ts));
371     ADD_ALL_TESTS(test_int_muldiv, OSSL_NELEM(test_muldiv_ints));
372     ADD_ALL_TESTS(test_uint_muldiv, OSSL_NELEM(test_muldiv_uints));
373     return 1;
374 }
375