1 /* $FreeBSD: src/tools/tools/crypto/cryptokeytest.c,v 1.1.2.1 2003/02/24 22:52:36 sam Exp $ */
2 /* $DragonFly: src/tools/tools/crypto/cryptokeytest.c,v 1.2 2003/06/17 04:29:11 dillon Exp $ */
3 /*
4  * The big num stuff is a bit broken at the moment and I've not yet fixed it.
5  * The symtom is that odd size big nums will fail.  Test code below (it only
6  * uses modexp currently).
7  *
8  * --Jason L. Wright
9  */
10 #include <sys/types.h>
11 #include <sys/ioctl.h>
12 #include <machine/endian.h>
13 #include <sys/time.h>
14 #include <crypto/cryptodev.h>
15 #include <openssl/bn.h>
16 #include <fcntl.h>
17 #include <err.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 
22 static int crypto_fd = -1;
23 
24 /*
25  * Convert a little endian byte string in 'p' that
26  * is 'plen' bytes long to a BIGNUM. If 'dst' is NULL,
27  * a new BIGNUM is allocated.  Returns NULL on failure.
28  *
29  * XXX there has got to be a more efficient way to do
30  * this, but I haven't figured out enough of the OpenSSL
31  * magic.
32  */
33 BIGNUM *
34 le_to_bignum(BIGNUM *dst, u_int8_t *p, int plen)
35 {
36 	u_int8_t *pd;
37 	int i;
38 
39 	if (plen == 0)
40 		return (NULL);
41 
42 	if ((pd = (u_int8_t *)malloc(plen)) == NULL)
43 		return (NULL);
44 
45 	for (i = 0; i < plen; i++)
46 		pd[i] = p[plen - i - 1];
47 
48 	dst = BN_bin2bn(pd, plen, dst);
49 	free(pd);
50 	return (dst);
51 }
52 
53 /*
54  * Convert a BIGNUM to a little endian byte string.
55  * If 'rd' is NULL, allocate space for it, otherwise
56  * 'rd' is assumed to have room for BN_num_bytes(n)
57  * bytes.  Returns NULL on failure.
58  */
59 u_int8_t *
60 bignum_to_le(BIGNUM *n, u_int8_t *rd)
61 {
62 	int i, j, k;
63 	int blen = BN_num_bytes(n);
64 
65 	if (blen == 0)
66 		return (NULL);
67 	if (rd == NULL)
68 		rd = (u_int8_t *)malloc(blen);
69 	if (rd == NULL)
70 		return (NULL);
71 
72 	for (i = 0, j = 0; i < n->top; i++) {
73 		for (k = 0; k < BN_BITS2 / 8; k++) {
74 			if ((j + k) >= blen)
75 				goto out;
76 			rd[j + k] = n->d[i] >> (k * 8);
77 		}
78 		j += BN_BITS2 / 8;
79 	}
80 out:
81 	return (rd);
82 }
83 
84 int
85 UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
86 {
87 	struct crypt_kop kop;
88 	u_int8_t *ale, *ble, *cle;
89 
90 	if (crypto_fd == -1) {
91 		int fd, fdc = open("/dev/crypto", O_RDONLY);
92 
93 		if (fdc == -1)
94 			err(1, "/dev/crypto");
95 		if (ioctl(fdc, CRIOGET, &fd) == -1)
96 			err(1, "CRIOGET");
97 		close(fdc);
98 		crypto_fd = fd;
99 	}
100 
101 	if ((ale = bignum_to_le(a, NULL)) == NULL)
102 		err(1, "bignum_to_le, a");
103 	if ((ble = bignum_to_le(b, NULL)) == NULL)
104 		err(1, "bignum_to_le, b");
105 	if ((cle = bignum_to_le(c, NULL)) == NULL)
106 		err(1, "bignum_to_le, c");
107 
108 	bzero(&kop, sizeof(kop));
109 	kop.crk_op = CRK_MOD_EXP;
110 	kop.crk_iparams = 3;
111 	kop.crk_oparams = 1;
112 	kop.crk_param[0].crp_p = ale;
113 	kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8;
114 	kop.crk_param[1].crp_p = ble;
115 	kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8;
116 	kop.crk_param[2].crp_p = cle;
117 	kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8;
118 	kop.crk_param[3].crp_p = cle;
119 	kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8;
120 
121 	if (ioctl(crypto_fd, CIOCKEY, &kop) == -1)
122 		err(1, "CIOCKEY");
123 
124 	bzero(ale, BN_num_bytes(a));
125 	free(ale);
126 	bzero(ble, BN_num_bytes(b));
127 	free(ble);
128 
129 	if (kop.crk_status != 0) {
130 		printf("error %d\n", kop.crk_status);
131 		bzero(cle, BN_num_bytes(c));
132 		free(cle);
133 		return (-1);
134 	} else {
135 		res = le_to_bignum(res, cle, BN_num_bytes(c));
136 		bzero(cle, BN_num_bytes(c));
137 		free(cle);
138 		if (res == NULL)
139 			err(1, "le_to_bignum");
140 		return (0);
141 	}
142 	return (0);
143 }
144 
145 void
146 show_result(a, b, c, sw, hw)
147 BIGNUM *a, *b, *c, *sw, *hw;
148 {
149 	printf("\n");
150 
151 	printf("A = ");
152 	BN_print_fp(stdout, a);
153 	printf("\n");
154 
155 	printf("B = ");
156 	BN_print_fp(stdout, b);
157 	printf("\n");
158 
159 	printf("C = ");
160 	BN_print_fp(stdout, c);
161 	printf("\n");
162 
163 	printf("sw= ");
164 	BN_print_fp(stdout, sw);
165 	printf("\n");
166 
167 	printf("hw= ");
168 	BN_print_fp(stdout, hw);
169 	printf("\n");
170 
171 	printf("\n");
172 }
173 
174 void
175 testit(void)
176 {
177 	BIGNUM *a, *b, *c, *r1, *r2;
178 	BN_CTX *ctx;
179 
180 	ctx = BN_CTX_new();
181 
182 	a = BN_new();
183 	b = BN_new();
184 	c = BN_new();
185 	r1 = BN_new();
186 	r2 = BN_new();
187 
188 	BN_pseudo_rand(a, 1023, 0, 0);
189 	BN_pseudo_rand(b, 1023, 0, 0);
190 	BN_pseudo_rand(c, 1024, 0, 0);
191 
192 	if (BN_cmp(a, c) > 0) {
193 		BIGNUM *rem = BN_new();
194 
195 		BN_mod(rem, a, c, ctx);
196 		UB_mod_exp(r2, rem, b, c, ctx);
197 		BN_free(rem);
198 	} else {
199 		UB_mod_exp(r2, a, b, c, ctx);
200 	}
201 	BN_mod_exp(r1, a, b, c, ctx);
202 
203 	if (BN_cmp(r1, r2) != 0) {
204 		show_result(a, b, c, r1, r2);
205 	}
206 
207 	BN_free(r2);
208 	BN_free(r1);
209 	BN_free(c);
210 	BN_free(b);
211 	BN_free(a);
212 	BN_CTX_free(ctx);
213 }
214 
215 int
216 main()
217 {
218 	int i;
219 
220 	for (i = 0; i < 1000; i++) {
221 		fprintf(stderr, "test %d\n", i);
222 		testit();
223 	}
224 	return (0);
225 }
226