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