diff options
author | Tom Caputi <[email protected]> | 2016-05-12 10:51:24 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-07-20 10:43:30 -0700 |
commit | 0b04990a5de594659d2cf20458965277dd6efeb1 (patch) | |
tree | 74369a3236e03359f7276cb9b19687e28c7f6d59 /lib/libzpool/kernel.c | |
parent | be88e733a634ad0d7f20350e1a17ede51922d3ff (diff) |
Illumos Crypto Port module added to enable native encryption in zfs
A port of the Illumos Crypto Framework to a Linux kernel module (found
in module/icp). This is needed to do the actual encryption work. We cannot
use the Linux kernel's built in crypto api because it is only exported to
GPL-licensed modules. Having the ICP also means the crypto code can run on
any of the other kernels under OpenZFS. I ended up porting over most of the
internals of the framework, which means that porting over other API calls (if
we need them) should be fairly easy. Specifically, I have ported over the API
functions related to encryption, digests, macs, and crypto templates. The ICP
is able to use assembly-accelerated encryption on amd64 machines and AES-NI
instructions on Intel chips that support it. There are place-holder
directories for similar assembly optimizations for other architectures
(although they have not been written).
Signed-off-by: Tom Caputi <[email protected]>
Signed-off-by: Tony Hutter <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Issue #4329
Diffstat (limited to 'lib/libzpool/kernel.c')
-rw-r--r-- | lib/libzpool/kernel.c | 100 |
1 files changed, 93 insertions, 7 deletions
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 93bfb0403..a68911451 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -41,6 +41,7 @@ #include <sys/time.h> #include <sys/systeminfo.h> #include <zfs_fletcher.h> +#include <sys/crypto/icp.h> /* * Emulation of kernel services in userland. @@ -1113,9 +1114,96 @@ lowbit64(uint64_t i) return (h); } +/* + * Find highest one bit set. + * Returns bit number + 1 of highest bit that is set, otherwise returns 0. + * High order bit is 31 (or 63 in _LP64 kernel). + */ +int +highbit(ulong_t i) +{ +register int h = 1; + + if (i == 0) + return (0); +#ifdef _LP64 + if (i & 0xffffffff00000000ul) { + h += 32; i >>= 32; + } +#endif + if (i & 0xffff0000) { + h += 16; i >>= 16; + } + if (i & 0xff00) { + h += 8; i >>= 8; + } + if (i & 0xf0) { + h += 4; i >>= 4; + } + if (i & 0xc) { + h += 2; i >>= 2; + } + if (i & 0x2) { + h += 1; + } + return (h); +} + +/* + * Find lowest one bit set. + * Returns bit number + 1 of lowest bit that is set, otherwise returns 0. + * Low order bit is 0. + */ +int +lowbit(ulong_t i) +{ + register int h = 1; + + if (i == 0) + return (0); + +#ifdef _LP64 + if (!(i & 0xffffffff)) { + h += 32; i >>= 32; + } +#endif + if (!(i & 0xffff)) { + h += 16; i >>= 16; + } + if (!(i & 0xff)) { + h += 8; i >>= 8; + } + if (!(i & 0xf)) { + h += 4; i >>= 4; + } + if (!(i & 0x3)) { + h += 2; i >>= 2; + } + if (!(i & 0x1)) { + h += 1; + } + return (h); +} static int random_fd = -1, urandom_fd = -1; +void +random_init(void) +{ + VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); + VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); +} + +void +random_fini(void) +{ + close(random_fd); + close(urandom_fd); + + random_fd = -1; + urandom_fd = -1; +} + static int random_get_bytes_common(uint8_t *ptr, size_t len, int fd) { @@ -1228,12 +1316,13 @@ kernel_init(int mode) (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", (mode & FWRITE) ? get_system_hostid() : 0); - VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); - VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); + random_init(); + VERIFY0(uname(&hw_utsname)); thread_init(); system_taskq_init(); + icp_init(); spa_init(mode); @@ -1248,14 +1337,11 @@ kernel_fini(void) fletcher_4_fini(); spa_fini(); + icp_fini(); system_taskq_fini(); thread_fini(); - close(random_fd); - close(urandom_fd); - - random_fd = -1; - urandom_fd = -1; + random_fini(); } uid_t |