xref: /openbsd/regress/sys/crypto/enc/des3.c (revision 38fc82d7)
1*38fc82d7Smarkus /*      $OpenBSD: des3.c,v 1.1 2002/03/21 15:08:53 markus Exp $  */
2*38fc82d7Smarkus 
3*38fc82d7Smarkus /*
4*38fc82d7Smarkus  * Copyright (c) 2002 Markus Friedl.  All rights reserverd.
5*38fc82d7Smarkus  *
6*38fc82d7Smarkus  * Redistribution and use in source and binary forms, with or without
7*38fc82d7Smarkus  * modification, are permitted provided that the following conditions
8*38fc82d7Smarkus  * are met:
9*38fc82d7Smarkus  * 1. Redistributions of source code must retain the above copyright
10*38fc82d7Smarkus  *    notice, this list of conditions and the following disclaimer.
11*38fc82d7Smarkus  * 2. Redistributions in binary form must reproduce the above copyright
12*38fc82d7Smarkus  *    notice, this list of conditions and the following disclaimer in the
13*38fc82d7Smarkus  *    documentation and/or other materials provided with the distribution.
14*38fc82d7Smarkus  *
15*38fc82d7Smarkus  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*38fc82d7Smarkus  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*38fc82d7Smarkus  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*38fc82d7Smarkus  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*38fc82d7Smarkus  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*38fc82d7Smarkus  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*38fc82d7Smarkus  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*38fc82d7Smarkus  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*38fc82d7Smarkus  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*38fc82d7Smarkus  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*38fc82d7Smarkus  */
26*38fc82d7Smarkus 
27*38fc82d7Smarkus #include <sys/types.h>
28*38fc82d7Smarkus #include <sys/param.h>
29*38fc82d7Smarkus #include <sys/ioctl.h>
30*38fc82d7Smarkus #include <sys/sysctl.h>
31*38fc82d7Smarkus #include <crypto/cryptodev.h>
32*38fc82d7Smarkus #include <stdio.h>
33*38fc82d7Smarkus #include <fcntl.h>
34*38fc82d7Smarkus #include <unistd.h>
35*38fc82d7Smarkus #include <err.h>
36*38fc82d7Smarkus #include <des.h>
37*38fc82d7Smarkus 
38*38fc82d7Smarkus int
39*38fc82d7Smarkus syscrypt(const unsigned char *key, size_t klen, const unsigned char *iv,
40*38fc82d7Smarkus     const unsigned char *in, unsigned char *out, size_t len, int encrypt)
41*38fc82d7Smarkus {
42*38fc82d7Smarkus 	struct session_op session;
43*38fc82d7Smarkus 	struct crypt_op cryp;
44*38fc82d7Smarkus 	int cryptodev_fd = -1, fd = -1, i;
45*38fc82d7Smarkus 
46*38fc82d7Smarkus 	if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
47*38fc82d7Smarkus 		warn("/dev/crypto");
48*38fc82d7Smarkus 		goto err;
49*38fc82d7Smarkus 	}
50*38fc82d7Smarkus 	if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
51*38fc82d7Smarkus 		warn("CRIOGET failed");
52*38fc82d7Smarkus 		goto err;
53*38fc82d7Smarkus 	}
54*38fc82d7Smarkus 	memset(&session, 0, sizeof(session));
55*38fc82d7Smarkus 	session.cipher = CRYPTO_3DES_CBC;
56*38fc82d7Smarkus 	session.key = (caddr_t) key;
57*38fc82d7Smarkus 	session.keylen = klen;
58*38fc82d7Smarkus 	if (ioctl(fd, CIOCGSESSION, &session) == -1) {
59*38fc82d7Smarkus 		warn("CIOCGSESSION");
60*38fc82d7Smarkus 		goto err;
61*38fc82d7Smarkus 	}
62*38fc82d7Smarkus 	memset(&cryp, 0, sizeof(cryp));
63*38fc82d7Smarkus 	cryp.ses = session.ses;
64*38fc82d7Smarkus 	cryp.op = encrypt ? COP_ENCRYPT : COP_DECRYPT;
65*38fc82d7Smarkus 	cryp.flags = 0;
66*38fc82d7Smarkus 	cryp.len = len;
67*38fc82d7Smarkus 	cryp.src = (caddr_t) in;
68*38fc82d7Smarkus 	cryp.dst = (caddr_t) out;
69*38fc82d7Smarkus 	cryp.iv = (caddr_t) iv;
70*38fc82d7Smarkus 	cryp.mac = 0;
71*38fc82d7Smarkus 	if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
72*38fc82d7Smarkus 		warn("CIOCCRYPT");
73*38fc82d7Smarkus 		goto err;
74*38fc82d7Smarkus 	}
75*38fc82d7Smarkus 	if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
76*38fc82d7Smarkus 		warn("CIOCFSESSION");
77*38fc82d7Smarkus 		goto err;
78*38fc82d7Smarkus 	}
79*38fc82d7Smarkus 	close(fd);
80*38fc82d7Smarkus 	close(cryptodev_fd);
81*38fc82d7Smarkus 	return (0);
82*38fc82d7Smarkus 
83*38fc82d7Smarkus err:
84*38fc82d7Smarkus 	if (fd != -1)
85*38fc82d7Smarkus 		close(fd);
86*38fc82d7Smarkus 	if (cryptodev_fd != -1)
87*38fc82d7Smarkus 		close(cryptodev_fd);
88*38fc82d7Smarkus 	return (-1);
89*38fc82d7Smarkus }
90*38fc82d7Smarkus 
91*38fc82d7Smarkus int
92*38fc82d7Smarkus getallowsoft(void)
93*38fc82d7Smarkus {
94*38fc82d7Smarkus 	int mib[2], old;
95*38fc82d7Smarkus 	size_t olen;
96*38fc82d7Smarkus 
97*38fc82d7Smarkus 	olen = sizeof(old);
98*38fc82d7Smarkus 
99*38fc82d7Smarkus 	mib[0] = CTL_KERN;
100*38fc82d7Smarkus 	mib[1] = KERN_CRYPTODEVALLOWSOFT;
101*38fc82d7Smarkus 	if (sysctl(mib, 2, &old, &olen, NULL, 0) < 0)
102*38fc82d7Smarkus 		err(1, "sysctl failed");
103*38fc82d7Smarkus 
104*38fc82d7Smarkus 	return old;
105*38fc82d7Smarkus }
106*38fc82d7Smarkus 
107*38fc82d7Smarkus void
108*38fc82d7Smarkus setallowsoft(int new)
109*38fc82d7Smarkus {
110*38fc82d7Smarkus 	int mib[2], old;
111*38fc82d7Smarkus 	size_t olen, nlen;
112*38fc82d7Smarkus 
113*38fc82d7Smarkus 	olen = nlen = sizeof(new);
114*38fc82d7Smarkus 
115*38fc82d7Smarkus 	mib[0] = CTL_KERN;
116*38fc82d7Smarkus 	mib[1] = KERN_CRYPTODEVALLOWSOFT;
117*38fc82d7Smarkus 
118*38fc82d7Smarkus 	if (sysctl(mib, 2, &old, &olen, &new, nlen) < 0)
119*38fc82d7Smarkus 		err(1, "sysctl failed");
120*38fc82d7Smarkus }
121*38fc82d7Smarkus 
122*38fc82d7Smarkus int
123*38fc82d7Smarkus match(unsigned char *a, unsigned char *b, size_t len)
124*38fc82d7Smarkus {
125*38fc82d7Smarkus 	int i;
126*38fc82d7Smarkus 
127*38fc82d7Smarkus 	if (memcmp(a, b, len) == 0)
128*38fc82d7Smarkus 		return (1);
129*38fc82d7Smarkus 
130*38fc82d7Smarkus 	warnx("decrypt/plaintext mismatch");
131*38fc82d7Smarkus 
132*38fc82d7Smarkus 	for (i = 0; i < len; i++)
133*38fc82d7Smarkus 		printf("%2.2x", a[i]);
134*38fc82d7Smarkus 	printf("\n");
135*38fc82d7Smarkus 	for (i = 0; i < len; i++)
136*38fc82d7Smarkus 		printf("%2.2x", b[i]);
137*38fc82d7Smarkus 	printf("\n");
138*38fc82d7Smarkus 
139*38fc82d7Smarkus 	return (0);
140*38fc82d7Smarkus }
141*38fc82d7Smarkus 
142*38fc82d7Smarkus #define SZ 16
143*38fc82d7Smarkus 
144*38fc82d7Smarkus int
145*38fc82d7Smarkus main(int argc, char **argv)
146*38fc82d7Smarkus {
147*38fc82d7Smarkus 	des_key_schedule ks1, ks2, ks3;
148*38fc82d7Smarkus 	unsigned char iv0[8], iv[8], key[24] = "012345670123456701234567";
149*38fc82d7Smarkus 	unsigned char b1[SZ], b2[SZ];
150*38fc82d7Smarkus 	int allowed, i, fail = 0;
151*38fc82d7Smarkus 
152*38fc82d7Smarkus 	if (geteuid() == 0) {
153*38fc82d7Smarkus 		allowed = getallowsoft();
154*38fc82d7Smarkus 		if (allowed == 0)
155*38fc82d7Smarkus 			setallowsoft(1);
156*38fc82d7Smarkus 	}
157*38fc82d7Smarkus 
158*38fc82d7Smarkus 	/* setup data and iv */
159*38fc82d7Smarkus 	for (i = 0; i < sizeof(b1);  i+= sizeof(u_int32_t))
160*38fc82d7Smarkus 		*(u_int32_t *)(b1 + i) = arc4random();
161*38fc82d7Smarkus 	for (i = 0; i < sizeof(iv0); i+= sizeof(u_int32_t))
162*38fc82d7Smarkus 		*(u_int32_t *)(iv0 + 1) = arc4random();
163*38fc82d7Smarkus 	memset(b2, 0, sizeof(b2));
164*38fc82d7Smarkus 
165*38fc82d7Smarkus 	/* keysetup for software */
166*38fc82d7Smarkus         des_set_key((void *) key, ks1);
167*38fc82d7Smarkus         des_set_key((void *) (key+8), ks2);
168*38fc82d7Smarkus         des_set_key((void *) (key+16), ks3);
169*38fc82d7Smarkus 
170*38fc82d7Smarkus 	/* encrypt with software, decrypt with /dev/crypto */
171*38fc82d7Smarkus 	memcpy(iv, iv0, sizeof(iv0));
172*38fc82d7Smarkus         des_ede3_cbc_encrypt((void *)b1, (void*)b2, sizeof(b1), ks1, ks2, ks3,
173*38fc82d7Smarkus 	    (void*)iv, DES_ENCRYPT);
174*38fc82d7Smarkus 	memcpy(iv, iv0, sizeof(iv0));
175*38fc82d7Smarkus 	if (syscrypt(key, sizeof(key), iv, b2, b2, sizeof(b1), 0) < 0) {
176*38fc82d7Smarkus 		warnx("decrypt with /dev/crypto failed");
177*38fc82d7Smarkus 		fail++;
178*38fc82d7Smarkus 	}
179*38fc82d7Smarkus 	if (!match(b1, b2, sizeof(b1)))
180*38fc82d7Smarkus 		fail++;
181*38fc82d7Smarkus 	else
182*38fc82d7Smarkus 		printf("ok, encrypt with software, decrypt with /dev/crypto\n");
183*38fc82d7Smarkus 
184*38fc82d7Smarkus 	/* encrypt with /dev/crypto, decrypt with software */
185*38fc82d7Smarkus 	memcpy(iv, iv0, sizeof(iv0));
186*38fc82d7Smarkus 	if (syscrypt(key, sizeof(key), iv, b1, b2, sizeof(b1), 1) < 0) {
187*38fc82d7Smarkus 		warnx("encrypt with /dev/crypto failed");
188*38fc82d7Smarkus 		fail++;
189*38fc82d7Smarkus 	}
190*38fc82d7Smarkus 	memcpy(iv, iv0, sizeof(iv0));
191*38fc82d7Smarkus         des_ede3_cbc_encrypt((void *)b2, (void*)b2, sizeof(b1), ks1, ks2, ks3,
192*38fc82d7Smarkus 	    (void*)iv, DES_DECRYPT);
193*38fc82d7Smarkus 	if (!match(b1, b2, sizeof(b1)))
194*38fc82d7Smarkus 		fail++;
195*38fc82d7Smarkus 	else
196*38fc82d7Smarkus 		printf("ok, encrypt with /dev/crypto, decrypt with software\n");
197*38fc82d7Smarkus 
198*38fc82d7Smarkus 	if (geteuid() == 0 && allowed == 0)
199*38fc82d7Smarkus 		setallowsoft(0);
200*38fc82d7Smarkus 	exit((fail > 0) ? 1 : 0);
201*38fc82d7Smarkus }
202