Module Name: src Committed By: knakahara Date: Wed Jun 14 07:38:24 UTC 2017
Modified Files: src/sys/opencrypto: crypto.c Log Message: support multiple encryption drivers (port from FreeBSD). To generate a diff of this commit: cvs rdiff -u -r1.88 -r1.89 src/sys/opencrypto/crypto.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/opencrypto/crypto.c diff -u src/sys/opencrypto/crypto.c:1.88 src/sys/opencrypto/crypto.c:1.89 --- src/sys/opencrypto/crypto.c:1.88 Wed Jun 14 07:36:24 2017 +++ src/sys/opencrypto/crypto.c Wed Jun 14 07:38:24 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: crypto.c,v 1.88 2017/06/14 07:36:24 knakahara Exp $ */ +/* $NetBSD: crypto.c,v 1.89 2017/06/14 07:38:24 knakahara Exp $ */ /* $FreeBSD: src/sys/opencrypto/crypto.c,v 1.4.2.5 2003/02/26 00:14:05 sam Exp $ */ /* $OpenBSD: crypto.c,v 1.41 2002/07/17 23:52:38 art Exp $ */ @@ -53,7 +53,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.88 2017/06/14 07:36:24 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.89 2017/06/14 07:38:24 knakahara Exp $"); #include <sys/param.h> #include <sys/reboot.h> @@ -515,9 +515,14 @@ crypto_driver_suitable(struct cryptocap return true; } +#define CRYPTO_ACCEPT_HARDWARE 0x1 +#define CRYPTO_ACCEPT_SOFTWARE 0x2 /* * The algorithm we use here is pretty stupid; just use the * first driver that supports all the algorithms we need. + * If there are multiple drivers we choose the driver with + * the fewest active sessions. We prefer hardware-backed + * drivers to software ones. * * XXX We need more smarts here (in real life too, but that's * XXX another story altogether). @@ -526,9 +531,22 @@ static struct cryptocap * crypto_select_driver_lock(struct cryptoini *cri, int hard) { u_int32_t hid; + int accept; + struct cryptocap *cap, *best; + best = NULL; + /* + * hard == 0 can use both hardware and software drivers. + * We use hardware drivers prior to software drivers, so search + * hardware drivers at first time. + */ + if (hard >= 0) + accept = CRYPTO_ACCEPT_HARDWARE; + else + accept = CRYPTO_ACCEPT_SOFTWARE; +again: for (hid = 0; hid < crypto_drivers_num; hid++) { - struct cryptocap *cap = crypto_checkdriver(hid); + cap = crypto_checkdriver(hid); if (cap == NULL) continue; @@ -545,26 +563,41 @@ crypto_select_driver_lock(struct cryptoi } /* Hardware required -- ignore software drivers. */ - if (hard > 0 && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE)) { + if ((accept & CRYPTO_ACCEPT_SOFTWARE) == 0 + && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE)) { crypto_driver_unlock(cap); continue; } /* Software required -- ignore hardware drivers. */ - if (hard < 0 && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE) == 0) { + if ((accept & CRYPTO_ACCEPT_HARDWARE) == 0 + && (cap->cc_flags & CRYPTOCAP_F_SOFTWARE) == 0) { crypto_driver_unlock(cap); continue; } /* See if all the algorithms are supported. */ if (crypto_driver_suitable(cap, cri)) { - /* keep holding crypto_driver_lock(cap) */ - return cap; + if (best == NULL) { + /* keep holding crypto_driver_lock(cap) */ + best = cap; + continue; + } else if (cap->cc_sessions < best->cc_sessions) { + crypto_driver_unlock(best); + /* keep holding crypto_driver_lock(cap) */ + best = cap; + continue; + } } crypto_driver_unlock(cap); } + if (best == NULL && hard == 0 + && (accept & CRYPTO_ACCEPT_SOFTWARE) == 0) { + accept = CRYPTO_ACCEPT_SOFTWARE; + goto again; + } - return NULL; + return best; } /*