xref: /openbsd-src/regress/lib/libcrypto/bn/bn_bits.c (revision c199f4b2ed818cc4e8ea37ab132b87789ae29a21)
1 /*	$OpenBSD: bn_bits.c,v 1.2 2024/04/15 14:36:16 jsing Exp $ */
2 /*
3  * Copyright (c) 2024 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/bn.h>
22 
23 static int
test_bn_set_bit(void)24 test_bn_set_bit(void)
25 {
26 	BIGNUM *bn = NULL;
27 	char *out_str = NULL;
28 	size_t i;
29 	int failed = 1;
30 
31 	if ((bn = BN_new()) == NULL)
32 		goto failure;
33 
34 	for (i = 0; i < 128; i++) {
35 		if (i % 2 == 0) {
36 			if (!BN_set_bit(bn, i)) {
37 				fprintf(stderr, "FAIL: failed to set bit\n");
38 				goto failure;
39 			}
40 		}
41 		if (BN_is_bit_set(bn, i) != (i % 2 == 0)) {
42 			fprintf(stderr, "FAIL: BN_is_bit_set() = %d, want %d\n",
43 			    BN_is_bit_set(bn, i), (i % 2 == 0));
44 			goto failure;
45 		}
46 	}
47 
48 	if ((out_str = BN_bn2hex(bn)) == NULL)
49 		goto failure;
50 	if (strcmp(out_str, "55555555555555555555555555555555") != 0) {
51 		fprintf(stderr, "FAIL: got 0x%s, want 0x%s\n", out_str,
52 		    "55555555555555555555555555555555");
53 		goto failure;
54 	}
55 
56 	failed = 0;
57 
58  failure:
59 	BN_free(bn);
60 	free(out_str);
61 
62 	return failed;
63 }
64 
65 static int
test_bn_clear_bit(void)66 test_bn_clear_bit(void)
67 {
68 	BIGNUM *bn = NULL;
69 	char *out_str = NULL;
70 	size_t i;
71 	int failed = 1;
72 
73 	if ((bn = BN_new()) == NULL)
74 		goto failure;
75 
76 	for (i = 0; i < 128; i++) {
77 		if (!BN_set_bit(bn, i)) {
78 			fprintf(stderr, "FAIL: failed to set bit\n");
79 			goto failure;
80 		}
81 		if (i % 2 == 0) {
82 			if (!BN_clear_bit(bn, i)) {
83 				fprintf(stderr, "FAIL: failed to clear bit\n");
84 				goto failure;
85 			}
86 		}
87 		if (BN_is_bit_set(bn, i) != (i % 2 == 1)) {
88 			fprintf(stderr, "FAIL: BN_is_bit_set() = %d, want %d\n",
89 			    BN_is_bit_set(bn, i), (i % 2 == 1));
90 			goto failure;
91 		}
92 	}
93 
94 	if ((out_str = BN_bn2hex(bn)) == NULL)
95 		goto failure;
96 	if (strcmp(out_str, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") != 0) {
97 		fprintf(stderr, "FAIL: got 0x%s, want 0x%s\n", out_str,
98 		    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
99 		goto failure;
100 	}
101 
102 	/* Ensure that clearing results in non-negative zero. */
103 	if (!BN_one(bn))
104 		goto failure;
105 	BN_set_negative(bn, 1);
106 	if (!BN_clear_bit(bn, 0)) {
107 		fprintf(stderr, "FAIL: failed to clear bit\n");
108 		goto failure;
109 	}
110 	if (!BN_is_zero(bn)) {
111 		fprintf(stderr, "FAIL: clear bit did not result in zero\n");
112 		goto failure;
113 	}
114 	if (BN_is_negative(bn)) {
115 		fprintf(stderr, "FAIL: clear bit resulted in -0\n");
116 		goto failure;
117 	}
118 
119 	failed = 0;
120 
121  failure:
122 	BN_free(bn);
123 	free(out_str);
124 
125 	return failed;
126 }
127 
128 static int
test_bn_mask_bits(void)129 test_bn_mask_bits(void)
130 {
131 	BIGNUM *bn = NULL;
132 	char *out_str = NULL;
133 	size_t i;
134 	int failed = 1;
135 
136 	if ((bn = BN_new()) == NULL)
137 		goto failure;
138 
139 	if (BN_mask_bits(bn, 0)) {
140 		fprintf(stderr, "FAIL: mask bits should have failed\n");
141 		goto failure;
142 	}
143 
144 	for (i = 0; i < 128; i++) {
145 		if (!BN_set_bit(bn, i)) {
146 			fprintf(stderr, "FAIL: failed to set bit\n");
147 			goto failure;
148 		}
149 	}
150 
151 	if ((out_str = BN_bn2hex(bn)) == NULL)
152 		goto failure;
153 	if (strcmp(out_str, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") != 0) {
154 		fprintf(stderr, "FAIL: got 0x%s, want 0x%s\n", out_str,
155 		    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
156 		goto failure;
157 	}
158 
159 	if (!BN_mask_bits(bn, 127)) {
160 		fprintf(stderr, "FAIL: failed to mask bits\n");
161 		goto failure;
162 	}
163 
164 	free(out_str);
165 	if ((out_str = BN_bn2hex(bn)) == NULL)
166 		goto failure;
167 	if (strcmp(out_str, "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") != 0) {
168 		fprintf(stderr, "FAIL: got 0x%s, want 0x%s\n", out_str,
169 		    "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
170 		goto failure;
171 	}
172 
173 	if (!BN_mask_bits(bn, 65)) {
174 		fprintf(stderr, "FAIL: failed to mask bits\n");
175 		goto failure;
176 	}
177 
178 	free(out_str);
179 	if ((out_str = BN_bn2hex(bn)) == NULL)
180 		goto failure;
181 	if (strcmp(out_str, "01FFFFFFFFFFFFFFFF") != 0) {
182 		fprintf(stderr, "FAIL: got 0x%s, want 0x%s\n", out_str,
183 		    "01FFFFFFFFFFFFFFFF");
184 		goto failure;
185 	}
186 
187 	/* Ensure that masking results in non-negative zero. */
188 	if (!BN_one(bn))
189 		goto failure;
190 	BN_set_negative(bn, 1);
191 	if (!BN_mask_bits(bn, 0)) {
192 		fprintf(stderr, "FAIL: failed to mask bits\n");
193 		goto failure;
194 	}
195 	if (!BN_is_zero(bn)) {
196 		fprintf(stderr, "FAIL: mask bits did not result in zero\n");
197 		goto failure;
198 	}
199 	if (BN_is_negative(bn)) {
200 		fprintf(stderr, "FAIL: mask bits resulted in -0\n");
201 		goto failure;
202 	}
203 
204 	failed = 0;
205 
206  failure:
207 	BN_free(bn);
208 	free(out_str);
209 
210 	return failed;
211 }
212 
213 int
main(int argc,char ** argv)214 main(int argc, char **argv)
215 {
216 	int failed = 0;
217 
218 	failed |= test_bn_set_bit();
219 	failed |= test_bn_clear_bit();
220 	failed |= test_bn_mask_bits();
221 
222 	return failed;
223 }
224