This commit was manufactured by cvs2svn to create branch 'RELENG_6'.
This commit is contained in:
parent
d8ee659609
commit
ec43e58941
18
sbin/geom/class/eli/Makefile
Normal file
18
sbin/geom/class/eli/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../misc ${.CURDIR}/../../../../sys/geom/eli ${.CURDIR}/../../../../sys/crypto/sha2
|
||||
|
||||
CLASS= eli
|
||||
SRCS= g_eli_crypto.c
|
||||
SRCS+= g_eli_key.c
|
||||
SRCS+= pkcs5v2.c
|
||||
SRCS+= sha2.c
|
||||
|
||||
DPADD= ${LIBMD} ${LIBCRYPTO}
|
||||
LDADD= -lmd -lcrypto
|
||||
|
||||
WARNS?= 3
|
||||
|
||||
CFLAGS+=-I${.CURDIR}/../../../../sys
|
||||
|
||||
.include <bsd.lib.mk>
|
1246
sbin/geom/class/eli/geom_eli.c
Normal file
1246
sbin/geom/class/eli/geom_eli.c
Normal file
File diff suppressed because it is too large
Load Diff
1170
sys/geom/eli/g_eli.c
Normal file
1170
sys/geom/eli/g_eli.c
Normal file
File diff suppressed because it is too large
Load Diff
366
sys/geom/eli/g_eli.h
Normal file
366
sys/geom/eli/g_eli.h
Normal file
@ -0,0 +1,366 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _G_ELI_H_
|
||||
#define _G_ELI_H_
|
||||
|
||||
#include <sys/endian.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <crypto/sha2/sha2.h>
|
||||
#include <opencrypto/cryptodev.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/bio.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <geom/geom.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifndef _OpenSSL_
|
||||
#include <sys/md5.h>
|
||||
#endif
|
||||
|
||||
#define G_ELI_CLASS_NAME "ELI"
|
||||
#define G_ELI_MAGIC "GEOM::ELI"
|
||||
#define G_ELI_SUFFIX ".eli"
|
||||
|
||||
/*
|
||||
* Version history:
|
||||
* 0 - Initial version number.
|
||||
*/
|
||||
#define G_ELI_VERSION 0
|
||||
|
||||
/* Use random, onetime keys. */
|
||||
#define G_ELI_FLAG_ONETIME 0x00000001
|
||||
/* Ask for the passphrase from the kernel, before mounting root. */
|
||||
#define G_ELI_FLAG_BOOT 0x00000002
|
||||
/* Detach on last close, if we were open for writing. */
|
||||
#define G_ELI_FLAG_WO_DETACH 0x00000004
|
||||
/* Detach on last close. */
|
||||
#define G_ELI_FLAG_RW_DETACH 0x00000008
|
||||
/* Provider was open for writing. */
|
||||
#define G_ELI_FLAG_WOPEN 0x00010000
|
||||
/* Destroy device. */
|
||||
#define G_ELI_FLAG_DESTROY 0x00020000
|
||||
|
||||
#define SHA512_MDLEN 64
|
||||
|
||||
#define G_ELI_MAXMKEYS 2
|
||||
#define G_ELI_MAXKEYLEN 64
|
||||
#define G_ELI_USERKEYLEN G_ELI_MAXKEYLEN
|
||||
#define G_ELI_DATAKEYLEN G_ELI_MAXKEYLEN
|
||||
#define G_ELI_IVKEYLEN G_ELI_MAXKEYLEN
|
||||
#define G_ELI_SALTLEN 64
|
||||
#define G_ELI_DATAIVKEYLEN (G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN)
|
||||
/* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */
|
||||
#define G_ELI_MKEYLEN (G_ELI_DATAIVKEYLEN + SHA512_MDLEN)
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern u_int g_eli_debug;
|
||||
extern u_int g_eli_overwrites;
|
||||
|
||||
#define G_ELI_CRYPTO_HW 1
|
||||
#define G_ELI_CRYPTO_SW 2
|
||||
|
||||
#define G_ELI_DEBUG(lvl, ...) do { \
|
||||
if (g_eli_debug >= (lvl)) { \
|
||||
printf("GEOM_ELI"); \
|
||||
if (g_eli_debug > 0) \
|
||||
printf("[%u]", lvl); \
|
||||
printf(": "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
#define G_ELI_LOGREQ(lvl, bp, ...) do { \
|
||||
if (g_eli_debug >= (lvl)) { \
|
||||
printf("GEOM_ELI"); \
|
||||
if (g_eli_debug > 0) \
|
||||
printf("[%u]", lvl); \
|
||||
printf(": "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf(" "); \
|
||||
g_print_bio(bp); \
|
||||
printf("\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct g_eli_worker {
|
||||
struct g_eli_softc *w_softc;
|
||||
struct proc *w_proc;
|
||||
u_int w_number;
|
||||
uint64_t w_sid;
|
||||
LIST_ENTRY(g_eli_worker) w_next;
|
||||
};
|
||||
|
||||
struct g_eli_softc {
|
||||
struct g_geom *sc_geom;
|
||||
u_int sc_crypto;
|
||||
uint8_t sc_datakey[G_ELI_DATAKEYLEN];
|
||||
uint8_t sc_ivkey[G_ELI_IVKEYLEN];
|
||||
SHA256_CTX sc_ivctx;
|
||||
u_int sc_algo;
|
||||
u_int sc_keylen;
|
||||
int sc_nkey;
|
||||
uint32_t sc_flags;
|
||||
|
||||
/* Only for software cryptography. */
|
||||
struct bio_queue_head sc_queue;
|
||||
struct mtx sc_queue_mtx;
|
||||
LIST_HEAD(, g_eli_worker) sc_workers;
|
||||
};
|
||||
#define sc_name sc_geom->name
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct g_eli_metadata {
|
||||
char md_magic[16]; /* Magic value. */
|
||||
uint32_t md_version; /* Version number. */
|
||||
uint32_t md_flags; /* Additional flags. */
|
||||
uint16_t md_algo; /* Encryption algorithm. */
|
||||
uint16_t md_keylen; /* Key length. */
|
||||
uint64_t md_provsize; /* Provider's size. */
|
||||
uint32_t md_sectorsize; /* Sector size. */
|
||||
uint8_t md_keys; /* Available keys. */
|
||||
int32_t md_iterations; /* Number of iterations for PKCS#5v2 */
|
||||
uint8_t md_salt[G_ELI_SALTLEN]; /* Salt. */
|
||||
/* Encrypted master key (IV-key, Data-key, HMAC). */
|
||||
uint8_t md_mkeys[G_ELI_MAXMKEYS * G_ELI_MKEYLEN];
|
||||
u_char md_hash[16]; /* MD5 hash. */
|
||||
};
|
||||
#ifndef _OpenSSL_
|
||||
static __inline void
|
||||
eli_metadata_encode(struct g_eli_metadata *md, u_char *data)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
u_char *p;
|
||||
|
||||
p = data;
|
||||
bcopy(md->md_magic, p, sizeof(md->md_magic)); p += sizeof(md->md_magic);
|
||||
le32enc(p, md->md_version); p += sizeof(md->md_version);
|
||||
le32enc(p, md->md_flags); p += sizeof(md->md_flags);
|
||||
le16enc(p, md->md_algo); p += sizeof(md->md_algo);
|
||||
le16enc(p, md->md_keylen); p += sizeof(md->md_keylen);
|
||||
le64enc(p, md->md_provsize); p += sizeof(md->md_provsize);
|
||||
le32enc(p, md->md_sectorsize); p += sizeof(md->md_sectorsize);
|
||||
*p = md->md_keys; p += sizeof(md->md_keys);
|
||||
le32enc(p, md->md_iterations); p += sizeof(md->md_iterations);
|
||||
bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
|
||||
bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, data, p - data);
|
||||
MD5Final(md->md_hash, &ctx);
|
||||
bcopy(md->md_hash, p, sizeof(md->md_hash));
|
||||
}
|
||||
static __inline int
|
||||
eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
const u_char *p;
|
||||
|
||||
p = data + sizeof(md->md_magic) + sizeof(md->md_version);
|
||||
md->md_flags = le32dec(p); p += sizeof(md->md_flags);
|
||||
md->md_algo = le16dec(p); p += sizeof(md->md_algo);
|
||||
md->md_keylen = le16dec(p); p += sizeof(md->md_keylen);
|
||||
md->md_provsize = le64dec(p); p += sizeof(md->md_provsize);
|
||||
md->md_sectorsize = le32dec(p); p += sizeof(md->md_sectorsize);
|
||||
md->md_keys = *p; p += sizeof(md->md_keys);
|
||||
md->md_iterations = le32dec(p); p += sizeof(md->md_iterations);
|
||||
bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
|
||||
bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, data, p - data);
|
||||
MD5Final(md->md_hash, &ctx);
|
||||
if (bcmp(md->md_hash, p, 16) != 0)
|
||||
return (EINVAL);
|
||||
return (0);
|
||||
}
|
||||
static __inline int
|
||||
eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
|
||||
{
|
||||
int error;
|
||||
|
||||
bcopy(data, md->md_magic, sizeof(md->md_magic));
|
||||
md->md_version = le32dec(data + sizeof(md->md_magic));
|
||||
switch (md->md_version) {
|
||||
case 0:
|
||||
error = eli_metadata_decode_v0(data, md);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
#endif /* !_OpenSSL */
|
||||
|
||||
static __inline u_int
|
||||
g_eli_str2algo(const char *name)
|
||||
{
|
||||
|
||||
if (strcmp("null", name) == 0)
|
||||
return (CRYPTO_NULL_CBC);
|
||||
if (strcmp("aes", name) == 0)
|
||||
return (CRYPTO_AES_CBC);
|
||||
else if (strcmp("blowfish", name) == 0)
|
||||
return (CRYPTO_BLF_CBC);
|
||||
else if (strcmp("3des", name) == 0)
|
||||
return (CRYPTO_3DES_CBC);
|
||||
return (CRYPTO_ALGORITHM_MIN - 1);
|
||||
}
|
||||
|
||||
static __inline const char *
|
||||
g_eli_algo2str(u_int algo)
|
||||
{
|
||||
|
||||
switch (algo) {
|
||||
case CRYPTO_NULL_CBC:
|
||||
return ("NULL");
|
||||
case CRYPTO_AES_CBC:
|
||||
return ("AES");
|
||||
case CRYPTO_BLF_CBC:
|
||||
return ("Blowfish");
|
||||
case CRYPTO_3DES_CBC:
|
||||
return ("3DES");
|
||||
}
|
||||
return ("unknown");
|
||||
}
|
||||
|
||||
static __inline void
|
||||
eli_metadata_dump(const struct g_eli_metadata *md)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
char str[sizeof(md->md_mkeys) * 2 + 1];
|
||||
u_int i;
|
||||
|
||||
printf(" magic: %s\n", md->md_magic);
|
||||
printf(" version: %u\n", (u_int)md->md_version);
|
||||
printf(" flags: 0x%x\n", (u_int)md->md_flags);
|
||||
printf(" algo: %s\n", g_eli_algo2str(md->md_algo));
|
||||
printf(" keylen: %u\n", (u_int)md->md_keylen);
|
||||
printf(" provsize: %ju\n", (uintmax_t)md->md_provsize);
|
||||
printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
|
||||
printf(" keys: 0x%02x\n", (u_int)md->md_keys);
|
||||
printf("iterations: %u\n", (u_int)md->md_iterations);
|
||||
bzero(str, sizeof(str));
|
||||
for (i = 0; i < sizeof(md->md_salt); i++) {
|
||||
str[i * 2] = hex[md->md_salt[i] >> 4];
|
||||
str[i * 2 + 1] = hex[md->md_salt[i] & 0x0f];
|
||||
}
|
||||
printf(" Salt: %s\n", str);
|
||||
bzero(str, sizeof(str));
|
||||
for (i = 0; i < sizeof(md->md_mkeys); i++) {
|
||||
str[i * 2] = hex[md->md_mkeys[i] >> 4];
|
||||
str[i * 2 + 1] = hex[md->md_mkeys[i] & 0x0f];
|
||||
}
|
||||
printf("Master Key: %s\n", str);
|
||||
bzero(str, sizeof(str));
|
||||
for (i = 0; i < 16; i++) {
|
||||
str[i * 2] = hex[md->md_hash[i] >> 4];
|
||||
str[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
|
||||
}
|
||||
printf(" MD5 hash: %s\n", str);
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
g_eli_keylen(u_int algo, u_int keylen)
|
||||
{
|
||||
|
||||
switch (algo) {
|
||||
case CRYPTO_NULL_CBC:
|
||||
if (keylen == 0)
|
||||
keylen = 64 * 8;
|
||||
else {
|
||||
if (keylen > 64 * 8)
|
||||
keylen = 0;
|
||||
}
|
||||
return (keylen);
|
||||
case CRYPTO_AES_CBC:
|
||||
switch (keylen) {
|
||||
case 0:
|
||||
return (128);
|
||||
case 128:
|
||||
case 192:
|
||||
case 256:
|
||||
return (keylen);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
case CRYPTO_BLF_CBC:
|
||||
if (keylen == 0)
|
||||
return (128);
|
||||
if (keylen < 128 || keylen > 448)
|
||||
return (0);
|
||||
if ((keylen % 32) != 0)
|
||||
return (0);
|
||||
return (keylen);
|
||||
case CRYPTO_3DES_CBC:
|
||||
if (keylen == 0 || keylen == 192)
|
||||
return (192);
|
||||
return (0);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
int g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
|
||||
struct g_eli_metadata *md);
|
||||
struct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp,
|
||||
struct g_provider *bpp, const struct g_eli_metadata *md,
|
||||
const u_char *mkey, int nkey);
|
||||
int g_eli_destroy(struct g_eli_softc *sc, boolean_t force);
|
||||
|
||||
int g_eli_access(struct g_provider *pp, int dr, int dw, int de);
|
||||
void g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb);
|
||||
#endif
|
||||
|
||||
void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
|
||||
int g_eli_mkey_decrypt(const struct g_eli_metadata *md,
|
||||
const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
|
||||
int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
|
||||
unsigned char *mkey);
|
||||
|
||||
int g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize);
|
||||
int g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize);
|
||||
|
||||
struct hmac_ctx {
|
||||
SHA512_CTX shactx;
|
||||
u_char k_opad[128];
|
||||
};
|
||||
|
||||
void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
|
||||
size_t hkeylen);
|
||||
void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
|
||||
size_t datasize);
|
||||
void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize);
|
||||
void g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize,
|
||||
const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize);
|
||||
#endif /* !_G_ELI_H_ */
|
276
sys/geom/eli/g_eli_crypto.c
Normal file
276
sys/geom/eli/g_eli_crypto.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/evp.h>
|
||||
#define _OpenSSL_
|
||||
#endif
|
||||
#include <geom/eli/g_eli.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
MALLOC_DECLARE(M_ELI);
|
||||
|
||||
static int
|
||||
g_eli_crypto_done(struct cryptop *crp)
|
||||
{
|
||||
|
||||
crp->crp_opaque = (void *)crp;
|
||||
wakeup(crp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize)
|
||||
{
|
||||
struct cryptoini cri;
|
||||
struct cryptop *crp;
|
||||
struct cryptodesc *crd;
|
||||
struct uio *uio;
|
||||
struct iovec *iov;
|
||||
uint64_t sid;
|
||||
u_char *p;
|
||||
int error;
|
||||
|
||||
bzero(&cri, sizeof(cri));
|
||||
cri.cri_alg = algo;
|
||||
cri.cri_key = __DECONST(void *, key);
|
||||
cri.cri_klen = keysize;
|
||||
error = crypto_newsession(&sid, &cri, 0);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
p = malloc(sizeof(*crp) + sizeof(*crd) + sizeof(*uio) + sizeof(*iov),
|
||||
M_ELI, M_NOWAIT | M_ZERO);
|
||||
if (p == NULL) {
|
||||
crypto_freesession(sid);
|
||||
return (ENOMEM);
|
||||
}
|
||||
crp = (struct cryptop *)p; p += sizeof(*crp);
|
||||
crd = (struct cryptodesc *)p; p += sizeof(*crd);
|
||||
uio = (struct uio *)p; p += sizeof(*uio);
|
||||
iov = (struct iovec *)p; p += sizeof(*iov);
|
||||
|
||||
iov->iov_len = datasize;
|
||||
iov->iov_base = data;
|
||||
|
||||
uio->uio_iov = iov;
|
||||
uio->uio_iovcnt = 1;
|
||||
uio->uio_segflg = UIO_SYSSPACE;
|
||||
uio->uio_resid = datasize;
|
||||
|
||||
crd->crd_skip = 0;
|
||||
crd->crd_len = datasize;
|
||||
crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT | CRD_F_KEY_EXPLICIT;
|
||||
if (enc)
|
||||
crd->crd_flags |= CRD_F_ENCRYPT;
|
||||
crd->crd_alg = algo;
|
||||
crd->crd_key = __DECONST(void *, key);
|
||||
crd->crd_klen = keysize;
|
||||
bzero(crd->crd_iv, sizeof(crd->crd_iv));
|
||||
crd->crd_next = NULL;
|
||||
|
||||
crp->crp_sid = sid;
|
||||
crp->crp_ilen = datasize;
|
||||
crp->crp_olen = datasize;
|
||||
crp->crp_opaque = NULL;
|
||||
crp->crp_callback = g_eli_crypto_done;
|
||||
crp->crp_buf = (void *)uio;
|
||||
crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
|
||||
crp->crp_desc = crd;
|
||||
|
||||
error = crypto_dispatch(crp);
|
||||
if (error == 0) {
|
||||
while (crp->crp_opaque == NULL)
|
||||
tsleep(crp, PRIBIO, "geli", hz / 5);
|
||||
error = crp->crp_etype;
|
||||
}
|
||||
|
||||
free(crp, M_ELI);
|
||||
crypto_freesession(sid);
|
||||
return (error);
|
||||
}
|
||||
#else /* !_KERNEL */
|
||||
static int
|
||||
g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx;
|
||||
const EVP_CIPHER *type;
|
||||
u_char iv[keysize];
|
||||
int outsize;
|
||||
|
||||
switch (algo) {
|
||||
case CRYPTO_NULL_CBC:
|
||||
type = EVP_enc_null();
|
||||
break;
|
||||
case CRYPTO_AES_CBC:
|
||||
switch (keysize) {
|
||||
case 128:
|
||||
type = EVP_aes_128_cbc();
|
||||
break;
|
||||
case 192:
|
||||
type = EVP_aes_192_cbc();
|
||||
break;
|
||||
case 256:
|
||||
type = EVP_aes_256_cbc();
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
break;
|
||||
case CRYPTO_BLF_CBC:
|
||||
type = EVP_bf_cbc();
|
||||
break;
|
||||
case CRYPTO_3DES_CBC:
|
||||
type = EVP_des_ede3_cbc();
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
|
||||
EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc);
|
||||
EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
bzero(iv, sizeof(iv));
|
||||
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
|
||||
|
||||
if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return (EINVAL);
|
||||
}
|
||||
assert(outsize == (int)datasize);
|
||||
|
||||
if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return (EINVAL);
|
||||
}
|
||||
assert(outsize == 0);
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return (0);
|
||||
}
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
int
|
||||
g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize)
|
||||
{
|
||||
|
||||
return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
|
||||
}
|
||||
|
||||
int
|
||||
g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
|
||||
const u_char *key, size_t keysize)
|
||||
{
|
||||
|
||||
return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize));
|
||||
}
|
||||
|
||||
void
|
||||
g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
|
||||
size_t hkeylen)
|
||||
{
|
||||
u_char k_ipad[128], key[128];
|
||||
SHA512_CTX lctx;
|
||||
u_int i;
|
||||
|
||||
bzero(key, sizeof(key));
|
||||
if (hkeylen == 0)
|
||||
; /* do nothing */
|
||||
else if (hkeylen <= 128)
|
||||
bcopy(hkey, key, hkeylen);
|
||||
else {
|
||||
/* If key is longer than 128 bytes reset it to key = SHA512(key). */
|
||||
SHA512_Init(&lctx);
|
||||
SHA512_Update(&lctx, hkey, hkeylen);
|
||||
SHA512_Final(key, &lctx);
|
||||
}
|
||||
|
||||
/* XOR key with ipad and opad values. */
|
||||
for (i = 0; i < sizeof(key); i++) {
|
||||
k_ipad[i] = key[i] ^ 0x36;
|
||||
ctx->k_opad[i] = key[i] ^ 0x5c;
|
||||
}
|
||||
bzero(key, sizeof(key));
|
||||
/* Perform inner SHA512. */
|
||||
SHA512_Init(&ctx->shactx);
|
||||
SHA512_Update(&ctx->shactx, k_ipad, sizeof(k_ipad));
|
||||
}
|
||||
|
||||
void
|
||||
g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
|
||||
size_t datasize)
|
||||
{
|
||||
|
||||
SHA512_Update(&ctx->shactx, data, datasize);
|
||||
}
|
||||
|
||||
void
|
||||
g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
|
||||
{
|
||||
u_char digest[SHA512_MDLEN];
|
||||
SHA512_CTX lctx;
|
||||
|
||||
SHA512_Final(digest, &ctx->shactx);
|
||||
/* Perform outer SHA512. */
|
||||
SHA512_Init(&lctx);
|
||||
SHA512_Update(&lctx, ctx->k_opad, sizeof(ctx->k_opad));
|
||||
bzero(ctx, sizeof(*ctx));
|
||||
SHA512_Update(&lctx, digest, sizeof(digest));
|
||||
SHA512_Final(digest, &lctx);
|
||||
/* mdsize == 0 means "Give me the whole hash!" */
|
||||
if (mdsize == 0)
|
||||
mdsize = SHA512_MDLEN;
|
||||
bcopy(digest, md, mdsize);
|
||||
}
|
||||
|
||||
void
|
||||
g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize, const uint8_t *data,
|
||||
size_t datasize, uint8_t *md, size_t mdsize)
|
||||
{
|
||||
struct hmac_ctx ctx;
|
||||
|
||||
g_eli_crypto_hmac_init(&ctx, hkey, hkeysize);
|
||||
g_eli_crypto_hmac_update(&ctx, data, datasize);
|
||||
g_eli_crypto_hmac_final(&ctx, md, mdsize);
|
||||
}
|
639
sys/geom/eli/g_eli_ctl.c
Normal file
639
sys/geom/eli/g_eli_ctl.c
Normal file
@ -0,0 +1,639 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <vm/uma.h>
|
||||
|
||||
#include <geom/geom.h>
|
||||
#include <geom/eli/g_eli.h>
|
||||
|
||||
|
||||
MALLOC_DECLARE(M_ELI);
|
||||
|
||||
|
||||
static void
|
||||
g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_eli_metadata md;
|
||||
struct g_provider *pp;
|
||||
const char *name;
|
||||
u_char *key, mkey[G_ELI_DATAIVKEYLEN];
|
||||
int *nargs, *detach;
|
||||
int keysize, error;
|
||||
u_int nkey;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
|
||||
if (nargs == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "nargs");
|
||||
return;
|
||||
}
|
||||
if (*nargs != 1) {
|
||||
gctl_error(req, "Invalid number of arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
detach = gctl_get_paraml(req, "detach", sizeof(*detach));
|
||||
if (detach == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "detach");
|
||||
return;
|
||||
}
|
||||
|
||||
name = gctl_get_asciiparam(req, "arg0");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||
return;
|
||||
}
|
||||
if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
|
||||
name += strlen("/dev/");
|
||||
pp = g_provider_by_name(name);
|
||||
if (pp == NULL) {
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
error = g_eli_read_metadata(mp, pp, &md);
|
||||
if (error != 0) {
|
||||
gctl_error(req, "Cannot read metadata from %s (error=%d).",
|
||||
name, error);
|
||||
return;
|
||||
}
|
||||
if (md.md_keys == 0x00) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "No valid keys on %s.", pp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
key = gctl_get_param(req, "key", &keysize);
|
||||
if (key == NULL || keysize != G_ELI_USERKEYLEN) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "No '%s' argument.", "key");
|
||||
return;
|
||||
}
|
||||
|
||||
error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
|
||||
bzero(key, keysize);
|
||||
if (error == -1) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "Wrong key for %s.", pp->name);
|
||||
return;
|
||||
} else if (error > 0) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
|
||||
pp->name, error);
|
||||
return;
|
||||
}
|
||||
G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
|
||||
|
||||
if (*detach)
|
||||
md.md_flags |= G_ELI_FLAG_WO_DETACH;
|
||||
g_eli_create(req, mp, pp, &md, mkey, nkey);
|
||||
bzero(mkey, sizeof(mkey));
|
||||
bzero(&md, sizeof(md));
|
||||
}
|
||||
|
||||
static struct g_eli_softc *
|
||||
g_eli_find_device(struct g_class *mp, const char *prov)
|
||||
{
|
||||
struct g_eli_softc *sc;
|
||||
struct g_geom *gp;
|
||||
struct g_provider *pp;
|
||||
struct g_consumer *cp;
|
||||
|
||||
if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
|
||||
prov += strlen("/dev/");
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
sc = gp->softc;
|
||||
if (sc == NULL)
|
||||
continue;
|
||||
pp = LIST_FIRST(&gp->provider);
|
||||
if (pp != NULL && strcmp(pp->name, prov) == 0)
|
||||
return (sc);
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
if (cp != NULL && cp->provider != NULL &&
|
||||
strcmp(cp->provider->name, prov) == 0) {
|
||||
return (sc);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_eli_softc *sc;
|
||||
int *force, *last, *nargs, error;
|
||||
const char *prov;
|
||||
char param[16];
|
||||
u_int i;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
|
||||
if (nargs == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "nargs");
|
||||
return;
|
||||
}
|
||||
if (*nargs <= 0) {
|
||||
gctl_error(req, "Missing device(s).");
|
||||
return;
|
||||
}
|
||||
force = gctl_get_paraml(req, "force", sizeof(*force));
|
||||
if (force == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "force");
|
||||
return;
|
||||
}
|
||||
last = gctl_get_paraml(req, "last", sizeof(*last));
|
||||
if (last == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "last");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < (u_int)*nargs; i++) {
|
||||
snprintf(param, sizeof(param), "arg%u", i);
|
||||
prov = gctl_get_asciiparam(req, param);
|
||||
if (prov == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", i);
|
||||
return;
|
||||
}
|
||||
sc = g_eli_find_device(mp, prov);
|
||||
if (sc == NULL) {
|
||||
gctl_error(req, "No such device: %s.", prov);
|
||||
return;
|
||||
}
|
||||
if (*last) {
|
||||
sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
|
||||
sc->sc_geom->access = g_eli_access;
|
||||
} else {
|
||||
error = g_eli_destroy(sc, *force);
|
||||
if (error != 0) {
|
||||
gctl_error(req,
|
||||
"Cannot destroy device %s (error=%d).",
|
||||
sc->sc_name, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_eli_metadata md;
|
||||
struct g_provider *pp;
|
||||
const char *name;
|
||||
intmax_t *keylen, *sectorsize;
|
||||
u_char mkey[G_ELI_DATAIVKEYLEN];
|
||||
int *nargs, *detach;
|
||||
|
||||
g_topology_assert();
|
||||
bzero(&md, sizeof(md));
|
||||
|
||||
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
|
||||
if (nargs == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "nargs");
|
||||
return;
|
||||
}
|
||||
if (*nargs != 1) {
|
||||
gctl_error(req, "Invalid number of arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
detach = gctl_get_paraml(req, "detach", sizeof(*detach));
|
||||
if (detach == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "detach");
|
||||
return;
|
||||
}
|
||||
|
||||
strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
|
||||
md.md_version = G_ELI_VERSION;
|
||||
md.md_flags |= G_ELI_FLAG_ONETIME;
|
||||
if (*detach)
|
||||
md.md_flags |= G_ELI_FLAG_WO_DETACH;
|
||||
|
||||
name = gctl_get_asciiparam(req, "algo");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "algo");
|
||||
return;
|
||||
}
|
||||
md.md_algo = g_eli_str2algo(name);
|
||||
if (md.md_algo < CRYPTO_ALGORITHM_MIN ||
|
||||
md.md_algo > CRYPTO_ALGORITHM_MAX) {
|
||||
gctl_error(req, "Invalid '%s' argument.", "algo");
|
||||
return;
|
||||
}
|
||||
|
||||
keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
|
||||
if (keylen == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "keylen");
|
||||
return;
|
||||
}
|
||||
md.md_keylen = g_eli_keylen(md.md_algo, *keylen);
|
||||
if (md.md_keylen == 0) {
|
||||
gctl_error(req, "Invalid '%s' argument.", "keylen");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not important here. */
|
||||
md.md_provsize = 0;
|
||||
/* Not important here. */
|
||||
bzero(md.md_salt, sizeof(md.md_salt));
|
||||
|
||||
md.md_keys = 0x01;
|
||||
arc4rand(mkey, sizeof(mkey), 0);
|
||||
|
||||
/* Not important here. */
|
||||
bzero(md.md_hash, sizeof(md.md_hash));
|
||||
|
||||
name = gctl_get_asciiparam(req, "arg0");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||
return;
|
||||
}
|
||||
if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
|
||||
name += strlen("/dev/");
|
||||
pp = g_provider_by_name(name);
|
||||
if (pp == NULL) {
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
|
||||
sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
|
||||
if (sectorsize == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "sectorsize");
|
||||
return;
|
||||
}
|
||||
if (*sectorsize == 0)
|
||||
md.md_sectorsize = pp->sectorsize;
|
||||
else {
|
||||
if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
|
||||
gctl_error(req, "Invalid sector size.");
|
||||
return;
|
||||
}
|
||||
md.md_sectorsize = *sectorsize;
|
||||
}
|
||||
|
||||
g_eli_create(req, mp, pp, &md, mkey, -1);
|
||||
bzero(mkey, sizeof(mkey));
|
||||
bzero(&md, sizeof(md));
|
||||
}
|
||||
|
||||
static void
|
||||
g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_eli_softc *sc;
|
||||
struct g_eli_metadata md;
|
||||
struct g_provider *pp;
|
||||
struct g_consumer *cp;
|
||||
const char *name;
|
||||
u_char *key, *mkeydst, *sector;
|
||||
intmax_t *valp;
|
||||
int nkey;
|
||||
int keysize, error;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
name = gctl_get_asciiparam(req, "arg0");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||
return;
|
||||
}
|
||||
sc = g_eli_find_device(mp, name);
|
||||
if (sc == NULL) {
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
error = g_eli_read_metadata(mp, pp, &md);
|
||||
if (error != 0) {
|
||||
gctl_error(req, "Cannot read metadata from %s (error=%d).",
|
||||
name, error);
|
||||
return;
|
||||
}
|
||||
|
||||
valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
|
||||
if (valp == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "keyno");
|
||||
return;
|
||||
}
|
||||
if (*valp != -1)
|
||||
nkey = *valp;
|
||||
else
|
||||
nkey = sc->sc_nkey;
|
||||
if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
|
||||
gctl_error(req, "Invalid '%s' argument.", "keyno");
|
||||
return;
|
||||
}
|
||||
|
||||
key = gctl_get_param(req, "key", &keysize);
|
||||
if (key == NULL || keysize != G_ELI_USERKEYLEN) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "No '%s' argument.", "key");
|
||||
return;
|
||||
}
|
||||
|
||||
mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
|
||||
md.md_keys |= (1 << nkey);
|
||||
|
||||
bcopy(sc->sc_ivkey, mkeydst, sizeof(sc->sc_ivkey));
|
||||
bcopy(sc->sc_datakey, mkeydst + sizeof(sc->sc_ivkey),
|
||||
sizeof(sc->sc_datakey));
|
||||
|
||||
/* Encrypt Master Key with the new key. */
|
||||
error = g_eli_mkey_encrypt(md.md_algo, key, md.md_keylen, mkeydst);
|
||||
bzero(key, sizeof(key));
|
||||
if (error != 0) {
|
||||
bzero(&md, sizeof(md));
|
||||
gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
|
||||
return;
|
||||
}
|
||||
|
||||
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
|
||||
/* Store metadata with fresh key. */
|
||||
eli_metadata_encode(&md, sector);
|
||||
bzero(&md, sizeof(md));
|
||||
error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
|
||||
pp->sectorsize);
|
||||
bzero(sector, sizeof(sector));
|
||||
free(sector, M_ELI);
|
||||
if (error != 0) {
|
||||
gctl_error(req, "Cannot store metadata on %s (error=%d).",
|
||||
pp->name, error);
|
||||
return;
|
||||
}
|
||||
G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
|
||||
}
|
||||
|
||||
static void
|
||||
g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_eli_softc *sc;
|
||||
struct g_eli_metadata md;
|
||||
struct g_provider *pp;
|
||||
struct g_consumer *cp;
|
||||
const char *name;
|
||||
u_char *mkeydst, *sector;
|
||||
intmax_t *valp;
|
||||
size_t keysize;
|
||||
int error, nkey, *all, *force;
|
||||
u_int i;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
nkey = 0; /* fixes causeless gcc warning */
|
||||
|
||||
name = gctl_get_asciiparam(req, "arg0");
|
||||
if (name == NULL) {
|
||||
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||
return;
|
||||
}
|
||||
sc = g_eli_find_device(mp, name);
|
||||
if (sc == NULL) {
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
error = g_eli_read_metadata(mp, pp, &md);
|
||||
if (error != 0) {
|
||||
gctl_error(req, "Cannot read metadata from %s (error=%d).",
|
||||
name, error);
|
||||
return;
|
||||
}
|
||||
|
||||
all = gctl_get_paraml(req, "all", sizeof(*all));
|
||||
if (all == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "all");
|
||||
return;
|
||||
}
|
||||
|
||||
if (*all) {
|
||||
mkeydst = md.md_mkeys;
|
||||
keysize = sizeof(md.md_mkeys);
|
||||
} else {
|
||||
force = gctl_get_paraml(req, "force", sizeof(*force));
|
||||
if (force == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "force");
|
||||
return;
|
||||
}
|
||||
|
||||
valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
|
||||
if (valp == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "keyno");
|
||||
return;
|
||||
}
|
||||
if (*valp != -1)
|
||||
nkey = *valp;
|
||||
else
|
||||
nkey = sc->sc_nkey;
|
||||
if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
|
||||
gctl_error(req, "Invalid '%s' argument.", "keyno");
|
||||
return;
|
||||
}
|
||||
if (!(md.md_keys & (1 << nkey)) && !*force) {
|
||||
gctl_error(req, "Master Key %u is not set.", nkey);
|
||||
return;
|
||||
}
|
||||
md.md_keys &= ~(1 << nkey);
|
||||
if (md.md_keys == 0 && !*force) {
|
||||
gctl_error(req, "This is the last Master Key. Use '-f' "
|
||||
"flag if you really want to remove it.");
|
||||
return;
|
||||
}
|
||||
mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
|
||||
keysize = G_ELI_MKEYLEN;
|
||||
}
|
||||
|
||||
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
|
||||
for (i = 0; i <= g_eli_overwrites; i++) {
|
||||
if (i == g_eli_overwrites)
|
||||
bzero(mkeydst, keysize);
|
||||
else
|
||||
arc4rand(mkeydst, keysize, 0);
|
||||
/* Store metadata with destroyed key. */
|
||||
eli_metadata_encode(&md, sector);
|
||||
error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
|
||||
pp->sectorsize);
|
||||
if (error != 0) {
|
||||
G_ELI_DEBUG(0, "Cannot store metadata on %s "
|
||||
"(error=%d).", pp->name, error);
|
||||
}
|
||||
}
|
||||
bzero(&md, sizeof(md));
|
||||
bzero(sector, sizeof(sector));
|
||||
free(sector, M_ELI);
|
||||
if (*all)
|
||||
G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
|
||||
else
|
||||
G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
|
||||
}
|
||||
|
||||
static int
|
||||
g_eli_kill_one(struct g_eli_softc *sc)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
struct g_consumer *cp;
|
||||
u_char *sector;
|
||||
int err, error = 0;
|
||||
u_int i;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
if (sc == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
pp = LIST_FIRST(&sc->sc_geom->provider);
|
||||
g_error_provider(pp, ENXIO);
|
||||
|
||||
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
||||
pp = cp->provider;
|
||||
|
||||
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
|
||||
for (i = 0; i <= g_eli_overwrites; i++) {
|
||||
if (i == g_eli_overwrites)
|
||||
bzero(sector, pp->sectorsize);
|
||||
else
|
||||
arc4rand(sector, pp->sectorsize, 0);
|
||||
err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
|
||||
pp->sectorsize);
|
||||
if (err != 0) {
|
||||
G_ELI_DEBUG(0, "Cannot erase metadata on %s "
|
||||
"(error=%d).", pp->name, err);
|
||||
if (error == 0)
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
free(sector, M_ELI);
|
||||
if (error == 0)
|
||||
G_ELI_DEBUG(0, "%s has been killed.", pp->name);
|
||||
g_eli_destroy(sc, 1);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
int *all, *nargs;
|
||||
int error;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
|
||||
if (nargs == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "nargs");
|
||||
return;
|
||||
}
|
||||
all = gctl_get_paraml(req, "all", sizeof(*all));
|
||||
if (all == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "all");
|
||||
return;
|
||||
}
|
||||
if (!*all && *nargs == 0) {
|
||||
gctl_error(req, "Too few arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (*all) {
|
||||
struct g_geom *gp, *gp2;
|
||||
|
||||
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
|
||||
error = g_eli_kill_one(gp->softc);
|
||||
if (error != 0)
|
||||
gctl_error(req, "Not fully done.");
|
||||
}
|
||||
} else {
|
||||
struct g_eli_softc *sc;
|
||||
const char *prov;
|
||||
char param[16];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < *nargs; i++) {
|
||||
snprintf(param, sizeof(param), "arg%u", i);
|
||||
prov = gctl_get_asciiparam(req, param);
|
||||
|
||||
sc = g_eli_find_device(mp, prov);
|
||||
if (sc == NULL) {
|
||||
G_ELI_DEBUG(1, "No such provider: %s.", prov);
|
||||
continue;
|
||||
}
|
||||
error = g_eli_kill_one(sc);
|
||||
if (error != 0)
|
||||
gctl_error(req, "Not fully done.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
|
||||
{
|
||||
uint32_t *version;
|
||||
|
||||
g_topology_assert();
|
||||
|
||||
version = gctl_get_paraml(req, "version", sizeof(*version));
|
||||
if (version == NULL) {
|
||||
gctl_error(req, "No '%s' argument.", "version");
|
||||
return;
|
||||
}
|
||||
if (*version != G_ELI_VERSION) {
|
||||
gctl_error(req, "Userland and kernel parts are out of sync.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(verb, "attach") == 0)
|
||||
g_eli_ctl_attach(req, mp);
|
||||
else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
|
||||
g_eli_ctl_detach(req, mp);
|
||||
else if (strcmp(verb, "onetime") == 0)
|
||||
g_eli_ctl_onetime(req, mp);
|
||||
else if (strcmp(verb, "setkey") == 0)
|
||||
g_eli_ctl_setkey(req, mp);
|
||||
else if (strcmp(verb, "delkey") == 0)
|
||||
g_eli_ctl_delkey(req, mp);
|
||||
else if (strcmp(verb, "kill") == 0)
|
||||
g_eli_ctl_kill(req, mp);
|
||||
else
|
||||
gctl_error(req, "Unknown verb.");
|
||||
}
|
179
sys/geom/eli/g_eli_key.c
Normal file
179
sys/geom/eli/g_eli_key.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <geom/geom.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <geom/eli/g_eli.h>
|
||||
|
||||
|
||||
/*
|
||||
* Verify if the given 'key' is correct.
|
||||
* Return 1 if it is correct and 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
g_eli_mkey_verify(const unsigned char *mkey, const unsigned char *key)
|
||||
{
|
||||
const unsigned char *odhmac; /* On-disk HMAC. */
|
||||
unsigned char chmac[SHA512_MDLEN]; /* Calculated HMAC. */
|
||||
unsigned char hmkey[SHA512_MDLEN]; /* Key for HMAC. */
|
||||
|
||||
/*
|
||||
* The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
|
||||
*/
|
||||
g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
|
||||
|
||||
odhmac = mkey + G_ELI_DATAIVKEYLEN;
|
||||
|
||||
/* Calculate HMAC from Data-Key and IV-Key. */
|
||||
g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
|
||||
chmac, 0);
|
||||
|
||||
bzero(hmkey, sizeof(hmkey));
|
||||
|
||||
/*
|
||||
* Compare calculated HMAC with HMAC from metadata.
|
||||
* If two HMACs are equal, 'key' is correct.
|
||||
*/
|
||||
return (!bcmp(odhmac, chmac, SHA512_MDLEN));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate HMAC from Data-Key and IV-Key.
|
||||
*/
|
||||
void
|
||||
g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key)
|
||||
{
|
||||
unsigned char hmkey[SHA512_MDLEN]; /* Key for HMAC. */
|
||||
unsigned char *odhmac; /* On-disk HMAC. */
|
||||
|
||||
/*
|
||||
* The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
|
||||
*/
|
||||
g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
|
||||
|
||||
odhmac = mkey + G_ELI_DATAIVKEYLEN;
|
||||
/* Calculate HMAC from Data-Key and IV-Key. */
|
||||
g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
|
||||
odhmac, 0);
|
||||
|
||||
bzero(hmkey, sizeof(hmkey));
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and decrypt Master Key encrypted with 'key'.
|
||||
* Return decrypted Master Key number in 'nkeyp' if not NULL.
|
||||
* Return 0 on success, > 0 on failure, -1 on bad key.
|
||||
*/
|
||||
int
|
||||
g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
|
||||
unsigned char *mkey, unsigned *nkeyp)
|
||||
{
|
||||
unsigned char tmpmkey[G_ELI_MKEYLEN];
|
||||
unsigned char enckey[SHA512_MDLEN]; /* Key for encryption. */
|
||||
const unsigned char *mmkey;
|
||||
int bit, error, nkey;
|
||||
|
||||
if (nkeyp != NULL)
|
||||
*nkeyp = -1;
|
||||
|
||||
/*
|
||||
* The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
|
||||
*/
|
||||
g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
|
||||
|
||||
mmkey = md->md_mkeys;
|
||||
nkey = 0;
|
||||
for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
|
||||
bit = (1 << nkey);
|
||||
if ((md->md_keys & bit) == 0)
|
||||
continue;
|
||||
bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
|
||||
error = g_eli_crypto_decrypt(md->md_algo, tmpmkey,
|
||||
G_ELI_MKEYLEN, enckey, md->md_keylen);
|
||||
if (error != 0) {
|
||||
bzero(tmpmkey, sizeof(tmpmkey));
|
||||
bzero(enckey, sizeof(enckey));
|
||||
return (error);
|
||||
}
|
||||
if (g_eli_mkey_verify(tmpmkey, key)) {
|
||||
bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
|
||||
bzero(tmpmkey, sizeof(tmpmkey));
|
||||
bzero(enckey, sizeof(enckey));
|
||||
if (nkeyp != NULL)
|
||||
*nkeyp = nkey;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
bzero(enckey, sizeof(enckey));
|
||||
bzero(tmpmkey, sizeof(tmpmkey));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt the Master-Key and calculate HMAC to be able to verify it in the
|
||||
* future.
|
||||
*/
|
||||
int
|
||||
g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
|
||||
unsigned char *mkey)
|
||||
{
|
||||
unsigned char enckey[SHA512_MDLEN]; /* Key for encryption. */
|
||||
int error;
|
||||
|
||||
/*
|
||||
* To calculate HMAC, the whole key (G_ELI_USERKEYLEN bytes long) will
|
||||
* be used.
|
||||
*/
|
||||
g_eli_mkey_hmac(mkey, key);
|
||||
/*
|
||||
* The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
|
||||
*/
|
||||
g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
|
||||
/*
|
||||
* Encrypt the Master-Key and HMAC() result with the given key (this
|
||||
* time only 'keylen' bits from the key are used).
|
||||
*/
|
||||
error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen);
|
||||
|
||||
bzero(enckey, sizeof(enckey));
|
||||
|
||||
return (error);
|
||||
}
|
123
sys/geom/eli/pkcs5v2.c
Normal file
123
sys/geom/eli/pkcs5v2.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#else
|
||||
#include <sys/resource.h>
|
||||
#include <stdint.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <geom/eli/g_eli.h>
|
||||
#include <geom/eli/pkcs5v2.h>
|
||||
|
||||
static __inline void
|
||||
xor(uint8_t *dst, const uint8_t *src, size_t size)
|
||||
{
|
||||
|
||||
for (; size > 0; size--)
|
||||
*dst++ ^= *src++;
|
||||
}
|
||||
|
||||
void
|
||||
pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
|
||||
size_t saltsize, const char *passphrase, u_int iterations)
|
||||
{
|
||||
uint8_t md[SHA512_MDLEN], saltcount[saltsize + sizeof(uint32_t)];
|
||||
uint8_t *counter, *keyp;
|
||||
u_int i, bsize, passlen;
|
||||
uint32_t count;
|
||||
|
||||
passlen = strlen(passphrase);
|
||||
bzero(key, keylen);
|
||||
bcopy(salt, saltcount, saltsize);
|
||||
counter = saltcount + saltsize;
|
||||
|
||||
keyp = key;
|
||||
for (count = 1; keylen > 0; count++, keylen -= bsize, keyp += bsize) {
|
||||
bsize = MIN(keylen, sizeof(md));
|
||||
|
||||
counter[0] = (count >> 24) & 0xff;
|
||||
counter[1] = (count >> 16) & 0xff;
|
||||
counter[2] = (count >> 8) & 0xff;
|
||||
counter[3] = count & 0xff;
|
||||
g_eli_crypto_hmac(passphrase, passlen, saltcount,
|
||||
sizeof(saltcount), md, 0);
|
||||
xor(keyp, md, bsize);
|
||||
|
||||
for(i = 1; i < iterations; i++) {
|
||||
g_eli_crypto_hmac(passphrase, passlen, md, sizeof(md),
|
||||
md, 0);
|
||||
xor(keyp, md, bsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _KERNEL
|
||||
/*
|
||||
* Return the number of microseconds needed for 'interations' iterations.
|
||||
*/
|
||||
static int
|
||||
pkcs5v2_probe(int iterations)
|
||||
{
|
||||
uint8_t key[G_ELI_USERKEYLEN], salt[G_ELI_SALTLEN];
|
||||
uint8_t passphrase[] = "passphrase";
|
||||
struct rusage start, end;
|
||||
int usecs;
|
||||
|
||||
getrusage(RUSAGE_SELF, &start);
|
||||
pkcs5v2_genkey(key, sizeof(key), salt, sizeof(salt), passphrase,
|
||||
iterations);
|
||||
getrusage(RUSAGE_SELF, &end);
|
||||
|
||||
usecs = end.ru_utime.tv_sec - start.ru_utime.tv_sec;
|
||||
usecs *= 1000000;
|
||||
usecs += end.ru_utime.tv_usec - start.ru_utime.tv_usec;
|
||||
return (usecs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of iterations which takes 'usecs' microseconds.
|
||||
*/
|
||||
int
|
||||
pkcs5v2_calculate(int usecs)
|
||||
{
|
||||
int iterations, v;
|
||||
|
||||
for (iterations = 1; ; iterations <<= 1) {
|
||||
v = pkcs5v2_probe(iterations);
|
||||
if (v > 2000000)
|
||||
break;
|
||||
}
|
||||
return (((intmax_t)iterations * (intmax_t)usecs) / v);
|
||||
}
|
||||
#endif /* !_KERNEL */
|
36
sys/geom/eli/pkcs5v2.h
Normal file
36
sys/geom/eli/pkcs5v2.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PKCS5V2_H_
|
||||
#define _PKCS5V2_H_
|
||||
void pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
|
||||
size_t saltsize, const char *passphrase, u_int iterations);
|
||||
#ifndef _KERNEL
|
||||
int pkcs5v2_calculate(int usecs);
|
||||
#endif
|
||||
#endif /* !_PKCS5V2_H_ */
|
113
sys/geom/zero/g_zero.c
Normal file
113
sys/geom/zero/g_zero.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <geom/geom.h>
|
||||
|
||||
|
||||
#define G_ZERO_CLASS_NAME "ZERO"
|
||||
|
||||
SYSCTL_DECL(_kern_geom);
|
||||
SYSCTL_NODE(_kern_geom, OID_AUTO, zero, CTLFLAG_RW, 0, "GEOM_ZERO stuff");
|
||||
static u_int g_zero_clear = 1;
|
||||
SYSCTL_UINT(_kern_geom_zero, OID_AUTO, clear, CTLFLAG_RW, &g_zero_clear, 0,
|
||||
"Zero-fill bio_data.");
|
||||
|
||||
static void
|
||||
g_zero_start(struct bio *bp)
|
||||
{
|
||||
int error = ENXIO;
|
||||
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
if (g_zero_clear)
|
||||
bzero(bp->bio_data, bp->bio_length);
|
||||
/* FALLTHROUGH */
|
||||
case BIO_DELETE:
|
||||
case BIO_WRITE:
|
||||
bp->bio_completed = bp->bio_length;
|
||||
error = 0;
|
||||
break;
|
||||
case BIO_GETATTR:
|
||||
default:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
g_io_deliver(bp, error);
|
||||
}
|
||||
|
||||
static void
|
||||
g_zero_init(struct g_class *mp)
|
||||
{
|
||||
struct g_geom *gp;
|
||||
struct g_provider *pp;
|
||||
|
||||
g_topology_assert();
|
||||
gp = g_new_geomf(mp, "gzero");
|
||||
gp->start = g_zero_start;
|
||||
gp->access = g_std_access;
|
||||
pp = g_new_providerf(gp, "%s", gp->name);
|
||||
pp->mediasize = 1152921504606846976LLU;
|
||||
pp->sectorsize = 512;
|
||||
g_error_provider(pp, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
g_zero_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused,
|
||||
struct g_geom *gp)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
|
||||
g_topology_assert();
|
||||
if (gp == NULL)
|
||||
return (0);
|
||||
pp = LIST_FIRST(&gp->provider);
|
||||
if (pp == NULL)
|
||||
return (0);
|
||||
if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
|
||||
return (EBUSY);
|
||||
g_wither_geom(gp, ENXIO);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
static struct g_class g_zero_class = {
|
||||
.name = G_ZERO_CLASS_NAME,
|
||||
.version = G_VERSION,
|
||||
.init = g_zero_init,
|
||||
.destroy_geom = g_zero_destroy_geom
|
||||
};
|
||||
|
||||
DECLARE_GEOM_CLASS(g_zero_class, g_zero);
|
9
sys/modules/geom/geom_eli/Makefile
Normal file
9
sys/modules/geom/geom_eli/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../geom/eli
|
||||
|
||||
KMOD= geom_eli
|
||||
SRCS= g_eli.c g_eli_crypto.c g_eli_ctl.c g_eli_key.c pkcs5v2.c
|
||||
WARNS?= 2
|
||||
|
||||
.include <bsd.kmod.mk>
|
8
sys/modules/geom/geom_zero/Makefile
Normal file
8
sys/modules/geom/geom_zero/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../geom/zero
|
||||
|
||||
KMOD= geom_zero
|
||||
SRCS= g_zero.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
38
tools/regression/geom_eli/attach-d.t
Normal file
38
tools/regression/geom_eli/attach-d.t
Normal file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
keyfile=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..3"
|
||||
|
||||
dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -P -K $keyfile md${no}
|
||||
geli attach -d -p -k $keyfile md${no}
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
# Be sure it doesn't detach on read.
|
||||
dd if=/dev/md${no}.eli of=/dev/null 2>/dev/null
|
||||
sleep 1
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
true > /dev/md${no}.eli
|
||||
sleep 1
|
||||
if [ ! -c /dev/md${no}.eli ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $keyfile
|
140
tools/regression/geom_eli/delkey.t
Normal file
140
tools/regression/geom_eli/delkey.t
Normal file
@ -0,0 +1,140 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
keyfile1=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile2=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile3=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile4=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..14"
|
||||
|
||||
dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile3} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile4} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -P -K $keyfile1 md${no}
|
||||
geli attach -p -k $keyfile1 md${no}
|
||||
geli setkey -n 1 -P -K $keyfile2 md${no}
|
||||
|
||||
# Remove key 0 for attached provider.
|
||||
geli delkey -n 0 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# We cannot use keyfile1 anymore.
|
||||
geli attach -p -k $keyfile1 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
|
||||
# Attach with key 1.
|
||||
geli attach -p -k $keyfile2 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
|
||||
# We cannot remove last key without -f option (for attached provider).
|
||||
geli delkey -n 1 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 4"
|
||||
else
|
||||
echo "not ok 4"
|
||||
fi
|
||||
|
||||
# Remove last key for attached provider.
|
||||
geli delkey -f -n 1 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 5"
|
||||
else
|
||||
echo "not ok 5"
|
||||
fi
|
||||
|
||||
# If there are no valid keys, but provider is attached, we can save situation.
|
||||
geli setkey -n 0 -P -K $keyfile3 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 6"
|
||||
else
|
||||
echo "not ok 6"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# We cannot use keyfile2 anymore.
|
||||
geli attach -p -k $keyfile2 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 7"
|
||||
else
|
||||
echo "not ok 7"
|
||||
fi
|
||||
|
||||
# Attach with key 0.
|
||||
geli attach -p -k $keyfile3 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 8"
|
||||
else
|
||||
echo "not ok 8"
|
||||
fi
|
||||
|
||||
# Setup key 1.
|
||||
geli setkey -n 1 -P -K $keyfile4 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 9"
|
||||
else
|
||||
echo "not ok 9"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# Remove key 1 for detached provider.
|
||||
geli delkey -n 1 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 10"
|
||||
else
|
||||
echo "not ok 10"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile4 anymore.
|
||||
geli attach -p -k $keyfile4 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 11"
|
||||
else
|
||||
echo "not ok 11"
|
||||
fi
|
||||
|
||||
# We cannot remove last key without -f option (for detached provider).
|
||||
geli delkey -n 0 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 12"
|
||||
else
|
||||
echo "not ok 12"
|
||||
fi
|
||||
|
||||
# Remove last key for detached provider.
|
||||
geli delkey -f -n 0 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 13"
|
||||
else
|
||||
echo "not ok 13"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile3 anymore.
|
||||
geli attach -p -k $keyfile3 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 14"
|
||||
else
|
||||
echo "not ok 14"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $keyfile1 $keyfile2 $keyfile3 $keyfile4
|
44
tools/regression/geom_eli/detach-l.t
Normal file
44
tools/regression/geom_eli/detach-l.t
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
keyfile=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..4"
|
||||
|
||||
dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -P -K $keyfile md${no}
|
||||
geli attach -p -k $keyfile md${no}
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
# Be sure it doesn't detach before 'detach -l'.
|
||||
dd if=/dev/md${no}.eli of=/dev/null 2>/dev/null
|
||||
sleep 1
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
geli detach -l md${no}
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
dd if=/dev/md${no}.eli of=/dev/null 2>/dev/null
|
||||
sleep 1
|
||||
if [ ! -c /dev/md${no}.eli ]; then
|
||||
echo "ok 4"
|
||||
else
|
||||
echo "not ok 4"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $keyfile
|
51
tools/regression/geom_eli/init.t
Normal file
51
tools/regression/geom_eli/init.t
Normal file
@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
rnd=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..36"
|
||||
|
||||
i=1
|
||||
for cipher in aes:0 aes:128 aes:192 aes:256 \
|
||||
3des:0 3des:192 \
|
||||
blowfish:0 blowfish:128 blowfish:160 blowfish:192 blowfish:224 \
|
||||
blowfish:256 blowfish:288 blowfish:320 blowfish:352 blowfish:384 \
|
||||
blowfish:416 blowfish:448; do
|
||||
algo=${cipher%%:*}
|
||||
keylen=${cipher##*:}
|
||||
|
||||
dd if=/dev/random of=${rnd} bs=512 count=${sectors} >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -a $algo -l $keylen -P -K $keyfile md${no}
|
||||
geli attach -p -k $keyfile md${no}
|
||||
|
||||
dd if=${rnd} of=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null
|
||||
|
||||
md_rnd=`dd if=${rnd} bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
md_ddev=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
md_edev=`dd if=/dev/md${no} bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
|
||||
if [ ${md_rnd} = ${md_ddev} ]; then
|
||||
echo "ok $i - ${cipher}"
|
||||
else
|
||||
echo "not ok $i - ${cipher}"
|
||||
fi
|
||||
i=$((i+1))
|
||||
if [ ${md_rnd} != ${md_edev} ]; then
|
||||
echo "ok $i - ${cipher}"
|
||||
else
|
||||
echo "not ok $i - ${cipher}"
|
||||
fi
|
||||
i=$((i+1))
|
||||
|
||||
geli detach md${no}
|
||||
done
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $rnd $keyfile
|
97
tools/regression/geom_eli/kill.t
Normal file
97
tools/regression/geom_eli/kill.t
Normal file
@ -0,0 +1,97 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
keyfile1=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile2=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..9"
|
||||
|
||||
dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -P -K $keyfile1 md${no}
|
||||
geli attach -p -k $keyfile1 md${no}
|
||||
geli setkey -n 1 -P -K $keyfile2 md${no}
|
||||
|
||||
# Kill attached provider.
|
||||
geli kill md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
sleep 1
|
||||
# Provider should be automatically detached.
|
||||
if [ ! -c /dev/md{$no}.eli ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile1 anymore.
|
||||
geli attach -p -k $keyfile1 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile2 anymore.
|
||||
geli attach -p -k $keyfile2 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 4"
|
||||
else
|
||||
echo "not ok 4"
|
||||
fi
|
||||
|
||||
geli init -P -K $keyfile1 md${no}
|
||||
geli setkey -n 1 -p -k $keyfile1 -P -K $keyfile2 md${no}
|
||||
|
||||
# Should be possible to attach with keyfile1.
|
||||
geli attach -p -k $keyfile1 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 5"
|
||||
else
|
||||
echo "not ok 5"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# Should be possible to attach with keyfile2.
|
||||
geli attach -p -k $keyfile2 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 6"
|
||||
else
|
||||
echo "not ok 6"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# Kill detached provider.
|
||||
geli kill md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 7"
|
||||
else
|
||||
echo "not ok 7"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile1 anymore.
|
||||
geli attach -p -k $keyfile1 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 8"
|
||||
else
|
||||
echo "not ok 8"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile2 anymore.
|
||||
geli attach -p -k $keyfile2 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 9"
|
||||
else
|
||||
echo "not ok 9"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $keyfile1 $keyfile2
|
33
tools/regression/geom_eli/onetime-d.t
Normal file
33
tools/regression/geom_eli/onetime-d.t
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
mdconfig -a -t malloc -s $sectors -u $no || exit 1
|
||||
|
||||
echo "1..3"
|
||||
|
||||
geli onetime -d md${no}
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
# Be sure it doesn't detach on read.
|
||||
dd if=/dev/md${no}.eli of=/dev/null 2>/dev/null
|
||||
sleep 1
|
||||
if [ -c /dev/md${no}.eli ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
true > /dev/md${no}.eli
|
||||
sleep 1
|
||||
if [ ! -c /dev/md${no}.eli ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
48
tools/regression/geom_eli/onetime.t
Normal file
48
tools/regression/geom_eli/onetime.t
Normal file
@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
rnd=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s $sectors -u $no || exit 1
|
||||
|
||||
echo "1..36"
|
||||
|
||||
i=1
|
||||
for cipher in aes:0 aes:128 aes:192 aes:256 \
|
||||
3des:0 3des:192 \
|
||||
blowfish:0 blowfish:128 blowfish:160 blowfish:192 blowfish:224 \
|
||||
blowfish:256 blowfish:288 blowfish:320 blowfish:352 blowfish:384 \
|
||||
blowfish:416 blowfish:448; do
|
||||
algo=${cipher%%:*}
|
||||
keylen=${cipher##*:}
|
||||
|
||||
dd if=/dev/random of=${rnd} bs=512 count=${sectors} >/dev/null 2>&1
|
||||
|
||||
geli onetime -a $algo -l $keylen md${no}
|
||||
|
||||
dd if=${rnd} of=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null
|
||||
|
||||
md_rnd=`dd if=${rnd} bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
md_ddev=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
md_edev=`dd if=/dev/md${no} bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
|
||||
if [ ${md_rnd} = ${md_ddev} ]; then
|
||||
echo "ok $i - ${cipher}"
|
||||
else
|
||||
echo "not ok $i - ${cipher}"
|
||||
fi
|
||||
i=$((i+1))
|
||||
if [ ${md_rnd} != ${md_edev} ]; then
|
||||
echo "ok $i - ${cipher}"
|
||||
else
|
||||
echo "not ok $i - ${cipher}"
|
||||
fi
|
||||
i=$((i+1))
|
||||
|
||||
geli detach md${no}
|
||||
done
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $rnd
|
156
tools/regression/geom_eli/setkey.t
Normal file
156
tools/regression/geom_eli/setkey.t
Normal file
@ -0,0 +1,156 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
base=`basename $0`
|
||||
no=45
|
||||
sectors=100
|
||||
rnd=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile1=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile2=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile3=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile4=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
keyfile5=`mktemp /tmp/$base.XXXXXX` || exit 1
|
||||
mdconfig -a -t malloc -s `expr $sectors + 1` -u $no || exit 1
|
||||
|
||||
echo "1..16"
|
||||
|
||||
dd if=/dev/random of=${rnd} bs=512 count=${sectors} >/dev/null 2>&1
|
||||
hash1=`dd if=${rnd} bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile3} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile4} bs=512 count=16 >/dev/null 2>&1
|
||||
dd if=/dev/random of=${keyfile5} bs=512 count=16 >/dev/null 2>&1
|
||||
|
||||
geli init -P -K $keyfile1 md${no}
|
||||
geli attach -p -k $keyfile1 md${no}
|
||||
|
||||
dd if=${rnd} of=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null
|
||||
rm -f $rnd
|
||||
hash2=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
|
||||
# Change current key (0) for attached provider.
|
||||
geli setkey -P -K $keyfile2 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 1"
|
||||
else
|
||||
echo "not ok 1"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# We cannot use keyfile1 anymore.
|
||||
geli attach -p -k $keyfile1 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 2"
|
||||
else
|
||||
echo "not ok 2"
|
||||
fi
|
||||
|
||||
# Attach with new key.
|
||||
geli attach -p -k $keyfile2 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 3"
|
||||
else
|
||||
echo "not ok 3"
|
||||
fi
|
||||
hash3=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
|
||||
# Change key 1 for attached provider.
|
||||
geli setkey -n 1 -P -K $keyfile3 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 4"
|
||||
else
|
||||
echo "not ok 4"
|
||||
fi
|
||||
geli detach md${no}
|
||||
|
||||
# Attach with key 1.
|
||||
geli attach -p -k $keyfile3 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 5"
|
||||
else
|
||||
echo "not ok 5"
|
||||
fi
|
||||
hash4=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
geli detach md${no}
|
||||
|
||||
# Change current (1) key for detached provider.
|
||||
geli setkey -p -k $keyfile3 -P -K $keyfile4 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 6"
|
||||
else
|
||||
echo "not ok 6"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile3 anymore.
|
||||
geli attach -p -k $keyfile3 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 7"
|
||||
else
|
||||
echo "not ok 7"
|
||||
fi
|
||||
|
||||
# Attach with key 1.
|
||||
geli attach -p -k $keyfile4 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 8"
|
||||
else
|
||||
echo "not ok 8"
|
||||
fi
|
||||
hash5=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
geli detach md${no}
|
||||
|
||||
# Change key 0 for detached provider.
|
||||
geli setkey -n 0 -p -k $keyfile4 -P -K $keyfile5 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 9"
|
||||
else
|
||||
echo "not ok 9"
|
||||
fi
|
||||
|
||||
# We cannot use keyfile2 anymore.
|
||||
geli attach -p -k $keyfile2 md${no} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ok 10"
|
||||
else
|
||||
echo "not ok 10"
|
||||
fi
|
||||
|
||||
# Attach with key 0.
|
||||
geli attach -p -k $keyfile5 md${no}
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ok 11"
|
||||
else
|
||||
echo "not ok 11"
|
||||
fi
|
||||
hash6=`dd if=/dev/md${no}.eli bs=512 count=${sectors} 2>/dev/null | md5`
|
||||
geli detach md${no}
|
||||
|
||||
if [ ${hash1} = ${hash2} ]; then
|
||||
echo "ok 12"
|
||||
else
|
||||
echo "not ok 12"
|
||||
fi
|
||||
if [ ${hash1} = ${hash3} ]; then
|
||||
echo "ok 13"
|
||||
else
|
||||
echo "not ok 13"
|
||||
fi
|
||||
if [ ${hash1} = ${hash4} ]; then
|
||||
echo "ok 14"
|
||||
else
|
||||
echo "not ok 14"
|
||||
fi
|
||||
if [ ${hash1} = ${hash5} ]; then
|
||||
echo "ok 15"
|
||||
else
|
||||
echo "not ok 15"
|
||||
fi
|
||||
if [ ${hash1} = ${hash6} ]; then
|
||||
echo "ok 16"
|
||||
else
|
||||
echo "not ok 16"
|
||||
fi
|
||||
|
||||
mdconfig -d -u $no
|
||||
rm -f $keyfile1 $keyfile2 $keyfile3 $keyfile4 $keyfile5
|
Loading…
x
Reference in New Issue
Block a user