1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino *
9*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
10*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
11*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
12*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in
13*86d7f5d3SJohn Marino * the documentation and/or other materials provided with the
14*86d7f5d3SJohn Marino * distribution.
15*86d7f5d3SJohn Marino *
16*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17*86d7f5d3SJohn Marino * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18*86d7f5d3SJohn Marino * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19*86d7f5d3SJohn Marino * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20*86d7f5d3SJohn Marino * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21*86d7f5d3SJohn Marino * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22*86d7f5d3SJohn Marino * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23*86d7f5d3SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24*86d7f5d3SJohn Marino * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25*86d7f5d3SJohn Marino * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26*86d7f5d3SJohn Marino * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*86d7f5d3SJohn Marino * SUCH DAMAGE.
28*86d7f5d3SJohn Marino */
29*86d7f5d3SJohn Marino #include <sys/types.h>
30*86d7f5d3SJohn Marino #include <sys/param.h>
31*86d7f5d3SJohn Marino #include <sys/ioctl.h>
32*86d7f5d3SJohn Marino #include <sys/sysctl.h>
33*86d7f5d3SJohn Marino #include <crypto/cryptodev.h>
34*86d7f5d3SJohn Marino
35*86d7f5d3SJohn Marino #include <fcntl.h>
36*86d7f5d3SJohn Marino #include <unistd.h>
37*86d7f5d3SJohn Marino #include <errno.h>
38*86d7f5d3SJohn Marino #include <string.h>
39*86d7f5d3SJohn Marino #include <stdio.h>
40*86d7f5d3SJohn Marino
41*86d7f5d3SJohn Marino #include "tcplay.h"
42*86d7f5d3SJohn Marino
43*86d7f5d3SJohn Marino static
44*86d7f5d3SJohn Marino int
getallowsoft(void)45*86d7f5d3SJohn Marino getallowsoft(void)
46*86d7f5d3SJohn Marino {
47*86d7f5d3SJohn Marino int old;
48*86d7f5d3SJohn Marino size_t olen;
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino olen = sizeof(old);
51*86d7f5d3SJohn Marino
52*86d7f5d3SJohn Marino if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, NULL, 0) < 0) {
53*86d7f5d3SJohn Marino perror("accessing sysctl kern.cryptodevallowsoft failed");
54*86d7f5d3SJohn Marino }
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino return old;
57*86d7f5d3SJohn Marino }
58*86d7f5d3SJohn Marino
59*86d7f5d3SJohn Marino static
60*86d7f5d3SJohn Marino void
setallowsoft(int new)61*86d7f5d3SJohn Marino setallowsoft(int new)
62*86d7f5d3SJohn Marino {
63*86d7f5d3SJohn Marino int old;
64*86d7f5d3SJohn Marino size_t olen, nlen;
65*86d7f5d3SJohn Marino
66*86d7f5d3SJohn Marino olen = nlen = sizeof(new);
67*86d7f5d3SJohn Marino
68*86d7f5d3SJohn Marino if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, &new, nlen) < 0) {
69*86d7f5d3SJohn Marino perror("accessing sysctl kern.cryptodevallowsoft failed");
70*86d7f5d3SJohn Marino }
71*86d7f5d3SJohn Marino }
72*86d7f5d3SJohn Marino
73*86d7f5d3SJohn Marino static
74*86d7f5d3SJohn Marino int
get_cryptodev_cipher_id(struct tc_crypto_algo * cipher)75*86d7f5d3SJohn Marino get_cryptodev_cipher_id(struct tc_crypto_algo *cipher)
76*86d7f5d3SJohn Marino {
77*86d7f5d3SJohn Marino if (strcmp(cipher->name, "AES-128-XTS") == 0)
78*86d7f5d3SJohn Marino return CRYPTO_AES_XTS;
79*86d7f5d3SJohn Marino else if (strcmp(cipher->name, "AES-256-XTS") == 0)
80*86d7f5d3SJohn Marino return CRYPTO_AES_XTS;
81*86d7f5d3SJohn Marino else if (strcmp(cipher->name, "TWOFISH-128-XTS") == 0)
82*86d7f5d3SJohn Marino return CRYPTO_TWOFISH_XTS;
83*86d7f5d3SJohn Marino else if (strcmp(cipher->name, "TWOFISH-256-XTS") == 0)
84*86d7f5d3SJohn Marino return CRYPTO_TWOFISH_XTS;
85*86d7f5d3SJohn Marino else if (strcmp(cipher->name, "SERPENT-128-XTS") == 0)
86*86d7f5d3SJohn Marino return CRYPTO_SERPENT_XTS;
87*86d7f5d3SJohn Marino else if (strcmp(cipher->name, "SERPENT-256-XTS") == 0)
88*86d7f5d3SJohn Marino return CRYPTO_SERPENT_XTS;
89*86d7f5d3SJohn Marino else
90*86d7f5d3SJohn Marino return -1;
91*86d7f5d3SJohn Marino }
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino int
syscrypt(struct tc_crypto_algo * cipher,unsigned char * key,size_t klen,unsigned char * iv,unsigned char * in,unsigned char * out,size_t len,int do_encrypt)94*86d7f5d3SJohn Marino syscrypt(struct tc_crypto_algo *cipher, unsigned char *key, size_t klen, unsigned char *iv,
95*86d7f5d3SJohn Marino unsigned char *in, unsigned char *out, size_t len, int do_encrypt)
96*86d7f5d3SJohn Marino {
97*86d7f5d3SJohn Marino struct session_op session;
98*86d7f5d3SJohn Marino struct crypt_op cryp;
99*86d7f5d3SJohn Marino int cipher_id;
100*86d7f5d3SJohn Marino int cryptodev_fd = -1, fd = -1;
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino cipher_id = get_cryptodev_cipher_id(cipher);
103*86d7f5d3SJohn Marino if (cipher_id < 0) {
104*86d7f5d3SJohn Marino tc_log(1, "Cipher %s not found\n",
105*86d7f5d3SJohn Marino cipher->name);
106*86d7f5d3SJohn Marino return ENOENT;
107*86d7f5d3SJohn Marino }
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
110*86d7f5d3SJohn Marino perror("Could not open /dev/crypto");
111*86d7f5d3SJohn Marino goto err;
112*86d7f5d3SJohn Marino }
113*86d7f5d3SJohn Marino if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
114*86d7f5d3SJohn Marino perror("CRIOGET failed");
115*86d7f5d3SJohn Marino goto err;
116*86d7f5d3SJohn Marino }
117*86d7f5d3SJohn Marino memset(&session, 0, sizeof(session));
118*86d7f5d3SJohn Marino session.cipher = cipher_id;
119*86d7f5d3SJohn Marino session.key = (caddr_t) key;
120*86d7f5d3SJohn Marino session.keylen = klen;
121*86d7f5d3SJohn Marino if (ioctl(fd, CIOCGSESSION, &session) == -1) {
122*86d7f5d3SJohn Marino perror("CIOCGSESSION failed");
123*86d7f5d3SJohn Marino goto err;
124*86d7f5d3SJohn Marino }
125*86d7f5d3SJohn Marino memset(&cryp, 0, sizeof(cryp));
126*86d7f5d3SJohn Marino cryp.ses = session.ses;
127*86d7f5d3SJohn Marino cryp.op = do_encrypt ? COP_ENCRYPT : COP_DECRYPT;
128*86d7f5d3SJohn Marino cryp.flags = 0;
129*86d7f5d3SJohn Marino cryp.len = len;
130*86d7f5d3SJohn Marino cryp.src = (caddr_t) in;
131*86d7f5d3SJohn Marino cryp.dst = (caddr_t) out;
132*86d7f5d3SJohn Marino cryp.iv = (caddr_t) iv;
133*86d7f5d3SJohn Marino cryp.mac = 0;
134*86d7f5d3SJohn Marino if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
135*86d7f5d3SJohn Marino perror("CIOCCRYPT failed");
136*86d7f5d3SJohn Marino goto err;
137*86d7f5d3SJohn Marino }
138*86d7f5d3SJohn Marino if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
139*86d7f5d3SJohn Marino perror("CIOCFSESSION failed");
140*86d7f5d3SJohn Marino goto err;
141*86d7f5d3SJohn Marino }
142*86d7f5d3SJohn Marino close(fd);
143*86d7f5d3SJohn Marino close(cryptodev_fd);
144*86d7f5d3SJohn Marino return (0);
145*86d7f5d3SJohn Marino
146*86d7f5d3SJohn Marino err:
147*86d7f5d3SJohn Marino if (fd != -1)
148*86d7f5d3SJohn Marino close(fd);
149*86d7f5d3SJohn Marino if (cryptodev_fd != -1)
150*86d7f5d3SJohn Marino close(cryptodev_fd);
151*86d7f5d3SJohn Marino return (-1);
152*86d7f5d3SJohn Marino }
153*86d7f5d3SJohn Marino
154*86d7f5d3SJohn Marino int
tc_crypto_init(void)155*86d7f5d3SJohn Marino tc_crypto_init(void)
156*86d7f5d3SJohn Marino {
157*86d7f5d3SJohn Marino int allowed;
158*86d7f5d3SJohn Marino
159*86d7f5d3SJohn Marino allowed = getallowsoft();
160*86d7f5d3SJohn Marino if (allowed == 0)
161*86d7f5d3SJohn Marino setallowsoft(1);
162*86d7f5d3SJohn Marino
163*86d7f5d3SJohn Marino return 0;
164*86d7f5d3SJohn Marino }
165*86d7f5d3SJohn Marino
166