1 /*
2 * Octeon Crypto for OCF
3 *
4 * Written by David McCullough <david_mccullough@securecomputing.com>
5 * Copyright (C) 2009 David McCullough
6 *
7 * LICENSE TERMS
8 *
9 * The free distribution and use of this software in both source and binary
10 * form is allowed (with or without changes) provided that:
11 *
12 * 1. distributions of this source code include the above copyright
13 * notice, this list of conditions and the following disclaimer;
14 *
15 * 2. distributions in binary form include the above copyright
16 * notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other associated materials;
18 *
19 * 3. the copyright holder's name is not used to endorse products
20 * built using this software without specific written permission.
21 *
22 * DISCLAIMER
23 *
24 * This software is provided 'as is' with no explicit or implied warranties
25 * in respect of its properties, including, but not limited to, correctness
26 * and/or fitness for purpose.
27 * ---------------------------------------------------------------------------
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/uio.h>
41
42 #include <opencrypto/cryptodev.h>
43
44 #include <contrib/octeon-sdk/cvmx.h>
45
46 #include <mips/cavium/cryptocteon/cryptocteonvar.h>
47
48 #include "cryptodev_if.h"
49
50 struct cryptocteon_softc {
51 int32_t sc_cid; /* opencrypto id */
52 };
53
54 int cryptocteon_debug = 0;
55 TUNABLE_INT("hw.cryptocteon.debug", &cryptocteon_debug);
56
57 static void cryptocteon_identify(driver_t *, device_t);
58 static int cryptocteon_probe(device_t);
59 static int cryptocteon_attach(device_t);
60
61 static int cryptocteon_process(device_t, struct cryptop *, int);
62 static int cryptocteon_probesession(device_t,
63 const struct crypto_session_params *);
64 static int cryptocteon_newsession(device_t, crypto_session_t,
65 const struct crypto_session_params *);
66
67 static void
68 cryptocteon_identify(driver_t *drv, device_t parent)
69 {
70 if (octeon_has_feature(OCTEON_FEATURE_CRYPTO))
71 BUS_ADD_CHILD(parent, 0, "cryptocteon", 0);
72 }
73
74 static int
75 cryptocteon_probe(device_t dev)
76 {
77 device_set_desc(dev, "Octeon Secure Coprocessor");
78 return (0);
79 }
80
81 static int
82 cryptocteon_attach(device_t dev)
83 {
84 struct cryptocteon_softc *sc;
85
86 sc = device_get_softc(dev);
87
88 sc->sc_cid = crypto_get_driverid(dev, sizeof(struct octo_sess),
89 CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
90 CRYPTOCAP_F_ACCEL_SOFTWARE);
91 if (sc->sc_cid < 0) {
92 device_printf(dev, "crypto_get_driverid ret %d\n", sc->sc_cid);
93 return (ENXIO);
94 }
95
96 return (0);
97 }
98
99 static bool
100 cryptocteon_auth_supported(const struct crypto_session_params *csp)
101 {
102 u_int hash_len;
103
104 switch (csp->csp_auth_alg) {
105 case CRYPTO_SHA1_HMAC:
106 hash_len = SHA1_HASH_LEN;
107 break;
108 default:
109 return (false);
110 }
111
112 if (csp->csp_auth_klen > hash_len)
113 return (false);
114 return (true);
115 }
116
117 static bool
118 cryptocteon_cipher_supported(const struct crypto_session_params *csp)
119 {
120
121 switch (csp->csp_cipher_alg) {
122 case CRYPTO_AES_CBC:
123 if (csp->csp_ivlen != 16)
124 return (false);
125 if (csp->csp_cipher_klen != 16 &&
126 csp->csp_cipher_klen != 24 &&
127 csp->csp_cipher_klen != 32)
128 return (false);
129 break;
130 default:
131 return (false);
132 }
133
134 return (true);
135 }
136
137 static int
138 cryptocteon_probesession(device_t dev, const struct crypto_session_params *csp)
139 {
140
141 if (csp->csp_flags != 0)
142 return (EINVAL);
143 switch (csp->csp_mode) {
144 case CSP_MODE_DIGEST:
145 if (!cryptocteon_auth_supported(csp))
146 return (EINVAL);
147 break;
148 case CSP_MODE_CIPHER:
149 if (!cryptocteon_cipher_supported(csp))
150 return (EINVAL);
151 break;
152 case CSP_MODE_ETA:
153 if (!cryptocteon_auth_supported(csp) ||
154 !cryptocteon_cipher_supported(csp))
155 return (EINVAL);
156 break;
157 default:
158 return (EINVAL);
159 }
160 return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
161 }
162
163 static void
164 cryptocteon_calc_hash(const struct crypto_session_params *csp, const char *key,
165 struct octo_sess *ocd)
166 {
167 char hash_key[SHA1_HASH_LEN];
168
169 memset(hash_key, 0, sizeof(hash_key));
170 memcpy(hash_key, key, csp->csp_auth_klen);
171 octo_calc_hash(csp->csp_auth_alg == CRYPTO_SHA1_HMAC, hash_key,
172 ocd->octo_hminner, ocd->octo_hmouter);
173 }
174
175 /* Generate a new octo session. */
176 static int
177 cryptocteon_newsession(device_t dev, crypto_session_t cses,
178 const struct crypto_session_params *csp)
179 {
180 struct cryptocteon_softc *sc;
181 struct octo_sess *ocd;
182
183 sc = device_get_softc(dev);
184
185 ocd = crypto_get_driver_session(cses);
186
187 ocd->octo_encklen = csp->csp_cipher_klen;
188 if (csp->csp_cipher_key != NULL)
189 memcpy(ocd->octo_enckey, csp->csp_cipher_key,
190 ocd->octo_encklen);
191
192 if (csp->csp_auth_key != NULL)
193 cryptocteon_calc_hash(csp, csp->csp_auth_key, ocd);
194
195 ocd->octo_mlen = csp->csp_auth_mlen;
196 if (csp->csp_auth_mlen == 0) {
197 switch (csp->csp_auth_alg) {
198 case CRYPTO_SHA1_HMAC:
199 ocd->octo_mlen = SHA1_HASH_LEN;
200 break;
201 }
202 }
203
204 switch (csp->csp_mode) {
205 case CSP_MODE_DIGEST:
206 switch (csp->csp_auth_alg) {
207 case CRYPTO_SHA1_HMAC:
208 ocd->octo_encrypt = octo_null_sha1_encrypt;
209 ocd->octo_decrypt = octo_null_sha1_encrypt;
210 break;
211 }
212 break;
213 case CSP_MODE_CIPHER:
214 switch (csp->csp_cipher_alg) {
215 case CRYPTO_AES_CBC:
216 ocd->octo_encrypt = octo_aes_cbc_encrypt;
217 ocd->octo_decrypt = octo_aes_cbc_decrypt;
218 break;
219 }
220 break;
221 case CSP_MODE_ETA:
222 switch (csp->csp_cipher_alg) {
223 case CRYPTO_AES_CBC:
224 switch (csp->csp_auth_alg) {
225 case CRYPTO_SHA1_HMAC:
226 ocd->octo_encrypt = octo_aes_cbc_sha1_encrypt;
227 ocd->octo_decrypt = octo_aes_cbc_sha1_decrypt;
228 break;
229 }
230 break;
231 }
232 break;
233 }
234
235 KASSERT(ocd->octo_encrypt != NULL && ocd->octo_decrypt != NULL,
236 ("%s: missing function pointers", __func__));
237
238 return (0);
239 }
240
241 /*
242 * Process a request.
243 */
244 static int
245 cryptocteon_process(device_t dev, struct cryptop *crp, int hint)
246 {
247 const struct crypto_session_params *csp;
248 struct octo_sess *od;
249 size_t iovcnt, iovlen;
250 struct mbuf *m = NULL;
251 struct uio *uiop = NULL;
252 unsigned char *ivp = NULL;
253 unsigned char iv_data[16];
254 unsigned char icv[SHA1_HASH_LEN], icv2[SHA1_HASH_LEN];
255 int auth_off, auth_len, crypt_off, crypt_len;
256 struct cryptocteon_softc *sc;
257
258 sc = device_get_softc(dev);
259
260 crp->crp_etype = 0;
261
262 od = crypto_get_driver_session(crp->crp_session);
263 csp = crypto_get_params(crp->crp_session);
264
265 /*
266 * The crypto routines assume that the regions to auth and
267 * cipher are exactly 8 byte multiples and aligned on 8
268 * byte logical boundaries within the iovecs.
269 */
270 if (crp->crp_aad_length % 8 != 0 || crp->crp_payload_length % 8 != 0) {
271 crp->crp_etype = EFBIG;
272 goto done;
273 }
274
275 /*
276 * As currently written, the crypto routines assume the AAD and
277 * payload are adjacent.
278 */
279 if (crp->crp_aad_length != 0 && crp->crp_payload_start !=
280 crp->crp_aad_start + crp->crp_aad_length) {
281 crp->crp_etype = EFBIG;
282 goto done;
283 }
284
285 crypt_off = crp->crp_payload_start;
286 crypt_len = crp->crp_payload_length;
287 if (crp->crp_aad_length != 0) {
288 auth_off = crp->crp_aad_start;
289 auth_len = crp->crp_aad_length + crp->crp_payload_length;
290 } else {
291 auth_off = crypt_off;
292 auth_len = crypt_len;
293 }
294
295 /*
296 * do some error checking outside of the loop for m and IOV processing
297 * this leaves us with valid m or uiop pointers for later
298 */
299 switch (crp->crp_buf.cb_type) {
300 case CRYPTO_BUF_MBUF:
301 {
302 unsigned frags;
303
304 m = crp->crp_buf.cb_mbuf;
305 for (frags = 0; m != NULL; frags++)
306 m = m->m_next;
307
308 if (frags >= UIO_MAXIOV) {
309 printf("%s,%d: %d frags > UIO_MAXIOV", __FILE__, __LINE__, frags);
310 crp->crp_etype = EFBIG;
311 goto done;
312 }
313
314 m = crp->crp_buf.cb_mbuf;
315 break;
316 }
317 case CRYPTO_BUF_UIO:
318 uiop = crp->crp_buf.cb_uio;
319 if (uiop->uio_iovcnt > UIO_MAXIOV) {
320 printf("%s,%d: %d uio_iovcnt > UIO_MAXIOV", __FILE__, __LINE__,
321 uiop->uio_iovcnt);
322 crp->crp_etype = EFBIG;
323 goto done;
324 }
325 break;
326 default:
327 break;
328 }
329
330 if (csp->csp_cipher_alg != 0) {
331 if (crp->crp_flags & CRYPTO_F_IV_SEPARATE)
332 ivp = crp->crp_iv;
333 else {
334 crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen,
335 iv_data);
336 ivp = iv_data;
337 }
338 }
339
340 /*
341 * setup the I/O vector to cover the buffer
342 */
343 switch (crp->crp_buf.cb_type) {
344 case CRYPTO_BUF_MBUF:
345 iovcnt = 0;
346 iovlen = 0;
347
348 while (m != NULL) {
349 od->octo_iov[iovcnt].iov_base = mtod(m, void *);
350 od->octo_iov[iovcnt].iov_len = m->m_len;
351
352 m = m->m_next;
353 iovlen += od->octo_iov[iovcnt++].iov_len;
354 }
355 break;
356 case CRYPTO_BUF_UIO:
357 iovlen = 0;
358 for (iovcnt = 0; iovcnt < uiop->uio_iovcnt; iovcnt++) {
359 od->octo_iov[iovcnt].iov_base = uiop->uio_iov[iovcnt].iov_base;
360 od->octo_iov[iovcnt].iov_len = uiop->uio_iov[iovcnt].iov_len;
361
362 iovlen += od->octo_iov[iovcnt].iov_len;
363 }
364 break;
365 case CRYPTO_BUF_CONTIG:
366 iovlen = crp->crp_buf.cb_buf_len;
367 od->octo_iov[0].iov_base = crp->crp_buf.cb_buf;
368 od->octo_iov[0].iov_len = crp->crp_buf.cb_buf_len;
369 iovcnt = 1;
370 break;
371 default:
372 panic("can't happen");
373 }
374
375 /*
376 * setup a new explicit key
377 */
378 if (crp->crp_cipher_key != NULL)
379 memcpy(od->octo_enckey, crp->crp_cipher_key, od->octo_encklen);
380 if (crp->crp_auth_key != NULL)
381 cryptocteon_calc_hash(csp, crp->crp_auth_key, od);
382
383 if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
384 (*od->octo_encrypt)(od, od->octo_iov, iovcnt, iovlen,
385 auth_off, auth_len, crypt_off, crypt_len, icv, ivp);
386 else
387 (*od->octo_decrypt)(od, od->octo_iov, iovcnt, iovlen,
388 auth_off, auth_len, crypt_off, crypt_len, icv, ivp);
389
390 if (csp->csp_auth_alg != 0) {
391 if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
392 crypto_copydata(crp, crp->crp_digest_start,
393 od->octo_mlen, icv2);
394 if (timingsafe_bcmp(icv, icv2, od->octo_mlen) != 0)
395 crp->crp_etype = EBADMSG;
396 } else
397 crypto_copyback(crp, crp->crp_digest_start,
398 od->octo_mlen, icv);
399 }
400 done:
401 crypto_done(crp);
402 return (0);
403 }
404
405 static device_method_t cryptocteon_methods[] = {
406 /* device methods */
407 DEVMETHOD(device_identify, cryptocteon_identify),
408 DEVMETHOD(device_probe, cryptocteon_probe),
409 DEVMETHOD(device_attach, cryptocteon_attach),
410
411 /* crypto device methods */
412 DEVMETHOD(cryptodev_probesession, cryptocteon_probesession),
413 DEVMETHOD(cryptodev_newsession, cryptocteon_newsession),
414 DEVMETHOD(cryptodev_process, cryptocteon_process),
415 { 0, 0 }
416 };
417
418 static driver_t cryptocteon_driver = {
419 "cryptocteon",
420 cryptocteon_methods,
421 sizeof (struct cryptocteon_softc),
422 };
423 static devclass_t cryptocteon_devclass;
424 DRIVER_MODULE(cryptocteon, nexus, cryptocteon_driver, cryptocteon_devclass, 0, 0);
Cache object: e74acacd0d29fac1edb77dfe488f7dd4
|