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