Changeset View
Changeset View
Standalone View
Standalone View
sys/geom/eli/g_eli.h
Show All 34 Lines | |||||
#include <crypto/sha2/sha256.h> | #include <crypto/sha2/sha256.h> | ||||
#include <crypto/sha2/sha512.h> | #include <crypto/sha2/sha512.h> | ||||
#include <opencrypto/cryptodev.h> | #include <opencrypto/cryptodev.h> | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/libkern.h> | #include <sys/libkern.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/queue.h> | |||||
#include <sys/tree.h> | |||||
#include <geom/geom.h> | #include <geom/geom.h> | ||||
#else | #else | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <strings.h> | #include <strings.h> | ||||
#endif | #endif | ||||
#include <sys/queue.h> | |||||
#include <sys/tree.h> | |||||
#ifndef _OpenSSL_ | #ifndef _OpenSSL_ | ||||
#include <sys/md5.h> | #include <sys/md5.h> | ||||
#endif | #endif | ||||
#define G_ELI_CLASS_NAME "ELI" | #define G_ELI_CLASS_NAME "ELI" | ||||
#define G_ELI_MAGIC "GEOM::ELI" | #define G_ELI_MAGIC "GEOM::ELI" | ||||
#define G_ELI_SUFFIX ".eli" | #define G_ELI_SUFFIX ".eli" | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
#define G_ELI_SALTLEN 64 | #define G_ELI_SALTLEN 64 | ||||
#define G_ELI_DATAIVKEYLEN (G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN) | #define G_ELI_DATAIVKEYLEN (G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN) | ||||
/* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */ | /* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */ | ||||
#define G_ELI_MKEYLEN (G_ELI_DATAIVKEYLEN + SHA512_MDLEN) | #define G_ELI_MKEYLEN (G_ELI_DATAIVKEYLEN + SHA512_MDLEN) | ||||
#define G_ELI_OVERWRITES 5 | #define G_ELI_OVERWRITES 5 | ||||
/* Switch data encryption key every 2^20 blocks. */ | /* Switch data encryption key every 2^20 blocks. */ | ||||
#define G_ELI_KEY_SHIFT 20 | #define G_ELI_KEY_SHIFT 20 | ||||
#define G_ELI_CRYPTO_UNKNOWN 0 | |||||
#define G_ELI_CRYPTO_HW 1 | |||||
#define G_ELI_CRYPTO_SW 2 | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
extern int g_eli_debug; | extern int g_eli_debug; | ||||
extern u_int g_eli_overwrites; | extern u_int g_eli_overwrites; | ||||
extern u_int g_eli_batch; | extern u_int g_eli_batch; | ||||
#define G_ELI_CRYPTO_UNKNOWN 0 | |||||
#define G_ELI_CRYPTO_HW 1 | |||||
#define G_ELI_CRYPTO_SW 2 | |||||
#define G_ELI_DEBUG(lvl, ...) do { \ | #define G_ELI_DEBUG(lvl, ...) do { \ | ||||
if (g_eli_debug >= (lvl)) { \ | if (g_eli_debug >= (lvl)) { \ | ||||
printf("GEOM_ELI"); \ | printf("GEOM_ELI"); \ | ||||
if (g_eli_debug > 0) \ | if (g_eli_debug > 0) \ | ||||
printf("[%u]", lvl); \ | printf("[%u]", lvl); \ | ||||
printf(": "); \ | printf(": "); \ | ||||
printf(__VA_ARGS__); \ | printf(__VA_ARGS__); \ | ||||
printf("\n"); \ | printf("\n"); \ | ||||
Show All 16 Lines | struct g_eli_worker { | ||||
struct g_eli_softc *w_softc; | struct g_eli_softc *w_softc; | ||||
struct proc *w_proc; | struct proc *w_proc; | ||||
u_int w_number; | u_int w_number; | ||||
uint64_t w_sid; | uint64_t w_sid; | ||||
boolean_t w_active; | boolean_t w_active; | ||||
LIST_ENTRY(g_eli_worker) w_next; | LIST_ENTRY(g_eli_worker) w_next; | ||||
}; | }; | ||||
#else /* !_KERNEL */ | |||||
typedef int boolean_t; | |||||
pjd: Maybe we could just use 'bool' now? | |||||
#endif /* _KERNEL */ | |||||
struct g_eli_softc { | struct g_eli_softc { | ||||
struct g_geom *sc_geom; | struct g_geom *sc_geom; | ||||
u_int sc_version; | u_int sc_version; | ||||
u_int sc_crypto; | u_int sc_crypto; | ||||
uint8_t sc_mkey[G_ELI_DATAIVKEYLEN]; | uint8_t sc_mkey[G_ELI_DATAIVKEYLEN]; | ||||
uint8_t sc_ekey[G_ELI_DATAKEYLEN]; | uint8_t sc_ekey[G_ELI_DATAKEYLEN]; | ||||
TAILQ_HEAD(, g_eli_key) sc_ekeys_queue; | TAILQ_HEAD(, g_eli_key) sc_ekeys_queue; | ||||
RB_HEAD(g_eli_key_tree, g_eli_key) sc_ekeys_tree; | RB_HEAD(g_eli_key_tree, g_eli_key) sc_ekeys_tree; | ||||
Show All 13 Lines | struct g_eli_softc { | ||||
uint32_t sc_flags; | uint32_t sc_flags; | ||||
int sc_inflight; | int sc_inflight; | ||||
off_t sc_mediasize; | off_t sc_mediasize; | ||||
size_t sc_sectorsize; | size_t sc_sectorsize; | ||||
u_int sc_bytes_per_sector; | u_int sc_bytes_per_sector; | ||||
u_int sc_data_per_sector; | u_int sc_data_per_sector; | ||||
boolean_t sc_cpubind; | boolean_t sc_cpubind; | ||||
#ifdef _KERNEL | |||||
/* Only for software cryptography. */ | /* Only for software cryptography. */ | ||||
struct bio_queue_head sc_queue; | struct bio_queue_head sc_queue; | ||||
struct mtx sc_queue_mtx; | struct mtx sc_queue_mtx; | ||||
LIST_HEAD(, g_eli_worker) sc_workers; | LIST_HEAD(, g_eli_worker) sc_workers; | ||||
#endif /* _KERNEL */ | |||||
}; | }; | ||||
#define sc_name sc_geom->name | #define sc_name sc_geom->name | ||||
Not Done Inline ActionsUsually ! _KERNEL for consistency. delphij: Usually ! _KERNEL for consistency. | |||||
#endif /* _KERNEL */ | |||||
#define G_ELI_KEY_MAGIC 0xe11341c | |||||
Done Inline ActionsCan the software portion be #ifdef'ed instead? delphij: Can the software portion be #ifdef'ed instead? | |||||
Not Done Inline Actionsnot sure why I didn't do it this way originally. At first I was cutting too much stuff out, like struct mtx, and RB_HEAD, to avoid those includes. allanjude: not sure why I didn't do it this way originally. At first I was cutting too much stuff out… | |||||
struct g_eli_key { | |||||
/* Key value, must be first in the structure. */ | |||||
uint8_t gek_key[G_ELI_DATAKEYLEN]; | |||||
/* Magic. */ | |||||
int gek_magic; | |||||
/* Key number. */ | |||||
uint64_t gek_keyno; | |||||
/* Reference counter. */ | |||||
int gek_count; | |||||
/* Keeps keys sorted by most recent use. */ | |||||
TAILQ_ENTRY(g_eli_key) gek_next; | |||||
/* Keeps keys sorted by number. */ | |||||
RB_ENTRY(g_eli_key) gek_link; | |||||
}; | |||||
struct g_eli_metadata { | struct g_eli_metadata { | ||||
char md_magic[16]; /* Magic value. */ | char md_magic[16]; /* Magic value. */ | ||||
uint32_t md_version; /* Version number. */ | uint32_t md_version; /* Version number. */ | ||||
uint32_t md_flags; /* Additional flags. */ | uint32_t md_flags; /* Additional flags. */ | ||||
uint16_t md_ealgo; /* Encryption algorithm. */ | uint16_t md_ealgo; /* Encryption algorithm. */ | ||||
uint16_t md_keylen; /* Key length. */ | uint16_t md_keylen; /* Key length. */ | ||||
uint16_t md_aalgo; /* Authentication algorithm. */ | uint16_t md_aalgo; /* Authentication algorithm. */ | ||||
uint64_t md_provsize; /* Provider's size. */ | uint64_t md_provsize; /* Provider's size. */ | ||||
▲ Show 20 Lines • Show All 343 Lines • ▼ Show 20 Lines | g_eli_hashlen(u_int algo) | ||||
case CRYPTO_SHA2_384_HMAC: | case CRYPTO_SHA2_384_HMAC: | ||||
return (48); | return (48); | ||||
case CRYPTO_SHA2_512_HMAC: | case CRYPTO_SHA2_512_HMAC: | ||||
return (64); | return (64); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static __inline void | |||||
eli_metadata_softc(struct g_eli_softc *sc, const struct g_eli_metadata *md, | |||||
u_int sectorsize, off_t mediasize) | |||||
{ | |||||
sc->sc_version = md->md_version; | |||||
sc->sc_inflight = 0; | |||||
sc->sc_crypto = G_ELI_CRYPTO_UNKNOWN; | |||||
sc->sc_flags = md->md_flags; | |||||
/* Backward compatibility. */ | |||||
if (md->md_version < G_ELI_VERSION_04) | |||||
sc->sc_flags |= G_ELI_FLAG_NATIVE_BYTE_ORDER; | |||||
if (md->md_version < G_ELI_VERSION_05) | |||||
sc->sc_flags |= G_ELI_FLAG_SINGLE_KEY; | |||||
if (md->md_version < G_ELI_VERSION_06 && | |||||
(sc->sc_flags & G_ELI_FLAG_AUTH) != 0) { | |||||
sc->sc_flags |= G_ELI_FLAG_FIRST_KEY; | |||||
} | |||||
if (md->md_version < G_ELI_VERSION_07) | |||||
sc->sc_flags |= G_ELI_FLAG_ENC_IVKEY; | |||||
sc->sc_ealgo = md->md_ealgo; | |||||
if (sc->sc_flags & G_ELI_FLAG_AUTH) { | |||||
sc->sc_akeylen = sizeof(sc->sc_akey) * 8; | |||||
sc->sc_aalgo = md->md_aalgo; | |||||
sc->sc_alen = g_eli_hashlen(sc->sc_aalgo); | |||||
sc->sc_data_per_sector = sectorsize - sc->sc_alen; | |||||
/* | |||||
* Some hash functions (like SHA1 and RIPEMD160) generates hash | |||||
* which length is not multiple of 128 bits, but we want data | |||||
* length to be multiple of 128, so we can encrypt without | |||||
* padding. The line below rounds down data length to multiple | |||||
* of 128 bits. | |||||
*/ | |||||
sc->sc_data_per_sector -= sc->sc_data_per_sector % 16; | |||||
sc->sc_bytes_per_sector = | |||||
(md->md_sectorsize - 1) / sc->sc_data_per_sector + 1; | |||||
sc->sc_bytes_per_sector *= sectorsize; | |||||
} | |||||
sc->sc_sectorsize = md->md_sectorsize; | |||||
sc->sc_mediasize = mediasize; | |||||
if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) | |||||
sc->sc_mediasize -= sectorsize; | |||||
if (!(sc->sc_flags & G_ELI_FLAG_AUTH)) | |||||
sc->sc_mediasize -= (sc->sc_mediasize % sc->sc_sectorsize); | |||||
else { | |||||
sc->sc_mediasize /= sc->sc_bytes_per_sector; | |||||
sc->sc_mediasize *= sc->sc_sectorsize; | |||||
} | |||||
sc->sc_ekeylen = md->md_keylen; | |||||
} | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
int g_eli_read_metadata(struct g_class *mp, struct g_provider *pp, | int g_eli_read_metadata(struct g_class *mp, struct g_provider *pp, | ||||
struct g_eli_metadata *md); | struct g_eli_metadata *md); | ||||
struct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp, | struct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp, | ||||
struct g_provider *bpp, const struct g_eli_metadata *md, | struct g_provider *bpp, const struct g_eli_metadata *md, | ||||
const u_char *mkey, int nkey); | const u_char *mkey, int nkey); | ||||
int g_eli_destroy(struct g_eli_softc *sc, boolean_t force); | 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); | 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); | void g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb); | ||||
void g_eli_read_done(struct bio *bp); | void g_eli_read_done(struct bio *bp); | ||||
void g_eli_write_done(struct bio *bp); | void g_eli_write_done(struct bio *bp); | ||||
int g_eli_crypto_rerun(struct cryptop *crp); | int g_eli_crypto_rerun(struct cryptop *crp); | ||||
void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv, | |||||
size_t size); | |||||
void g_eli_crypto_read(struct g_eli_softc *sc, struct bio *bp, boolean_t fromworker); | void g_eli_crypto_read(struct g_eli_softc *sc, struct bio *bp, boolean_t fromworker); | ||||
void g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp); | void g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp); | ||||
void g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp); | void g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp); | ||||
void g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp); | void g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp); | ||||
#endif | #endif | ||||
void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv, | |||||
size_t size); | |||||
void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key); | void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key); | ||||
int g_eli_mkey_decrypt(const struct g_eli_metadata *md, | int g_eli_mkey_decrypt(const struct g_eli_metadata *md, | ||||
const unsigned char *key, unsigned char *mkey, unsigned *nkeyp); | const unsigned char *key, unsigned char *mkey, unsigned *nkeyp); | ||||
int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen, | int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen, | ||||
unsigned char *mkey); | unsigned char *mkey); | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
void g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey); | void g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey); | ||||
Show All 12 Lines | |||||
void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey, | void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey, | ||||
size_t hkeylen); | size_t hkeylen); | ||||
void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data, | void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data, | ||||
size_t datasize); | size_t datasize); | ||||
void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize); | 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, | 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); | const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize); | ||||
void g_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, | |||||
uint64_t keyno); | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
void g_eli_key_init(struct g_eli_softc *sc); | void g_eli_key_init(struct g_eli_softc *sc); | ||||
void g_eli_key_destroy(struct g_eli_softc *sc); | void g_eli_key_destroy(struct g_eli_softc *sc); | ||||
uint8_t *g_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize); | uint8_t *g_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize); | ||||
void g_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey); | void g_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey); | ||||
#endif | #endif | ||||
#endif /* !_G_ELI_H_ */ | #endif /* !_G_ELI_H_ */ |
Maybe we could just use 'bool' now?