summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/softraid_crypto.c134
-rw-r--r--sys/dev/softraidvar.h19
2 files changed, 142 insertions, 11 deletions
diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c
index 05133c67099..1f9253dc818 100644
--- a/sys/dev/softraid_crypto.c
+++ b/sys/dev/softraid_crypto.c
@@ -1,7 +1,8 @@
-/* $OpenBSD: softraid_crypto.c,v 1.24 2008/06/13 22:08:17 djm Exp $ */
+/* $OpenBSD: softraid_crypto.c,v 1.25 2008/06/14 00:12:21 djm Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org>
+ * Copyright (c) 2008 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,6 +17,25 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*-
+ * sr_crypto_hmac_sha1
+ *
+ * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
#include "bio.h"
#include <sys/param.h>
@@ -40,6 +60,7 @@
#include <crypto/cryptodev.h>
#include <crypto/cryptosoft.h>
#include <crypto/rijndael.h>
+#include <crypto/sha1.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
@@ -62,6 +83,10 @@ int sr_crypto_rw2(struct sr_workunit *, struct cryptop *);
void sr_crypto_intr(struct buf *);
int sr_crypto_read(struct cryptop *);
void sr_crypto_finish_io(struct sr_workunit *);
+void sr_crypto_hmac_sha1(const u_int8_t *, size_t, const u_int8_t *,
+ size_t, u_int8_t[SHA1_DIGEST_LENGTH]);
+void sr_crypto_calculate_check_hmac_sha1(struct sr_discipline *,
+ u_char[SHA1_DIGEST_LENGTH]);
#ifdef SR_DEBUG0
void sr_crypto_dumpkeys(struct sr_discipline *);
@@ -209,6 +234,73 @@ out:
return (rv);
}
+/*
+ * HMAC-SHA-1 (from RFC 2202).
+ * XXX this really belongs in sys/crypto, but it needs to be done
+ * generically and so far, nothing else needs it.
+ */
+void
+sr_crypto_hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
+ size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
+{
+ SHA1_CTX ctx;
+ u_int8_t k_pad[SHA1_BLOCK_LENGTH];
+ u_int8_t tk[SHA1_DIGEST_LENGTH];
+ int i;
+
+ if (key_len > SHA1_BLOCK_LENGTH) {
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, key, key_len);
+ SHA1Final(tk, &ctx);
+
+ key = tk;
+ key_len = SHA1_DIGEST_LENGTH;
+ }
+
+ bzero(k_pad, sizeof k_pad);
+ bcopy(key, k_pad, key_len);
+ for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
+ k_pad[i] ^= 0x36;
+
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
+ SHA1Update(&ctx, text, text_len);
+ SHA1Final(digest, &ctx);
+
+ bzero(k_pad, sizeof k_pad);
+ bcopy(key, k_pad, key_len);
+ for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
+ k_pad[i] ^= 0x5c;
+
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
+ SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
+ SHA1Final(digest, &ctx);
+}
+
+void
+sr_crypto_calculate_check_hmac_sha1(struct sr_discipline *sd,
+ u_char check_digest[SHA1_DIGEST_LENGTH])
+{
+ u_char check_key[SHA1_DIGEST_LENGTH];
+ SHA1_CTX shactx;
+
+ bzero(check_key, sizeof(check_key));
+ /* k = SHA1(mask_key) */
+ SHA1Init(&shactx);
+ SHA1Update(&shactx, sd->mds.mdd_crypto.scr_maskkey,
+ sizeof(sd->mds.mdd_crypto.scr_maskkey));
+ SHA1Final(check_key, &shactx);
+
+ bzero(&shactx, sizeof(shactx));
+ /* sch_mac = HMAC_SHA1_k(unencrypted scm_key) */
+ sr_crypto_hmac_sha1((u_char *)sd->mds.mdd_crypto.scr_key,
+ sizeof(sd->mds.mdd_crypto.scr_key),
+ check_key, sizeof(check_key),
+ check_digest);
+ bzero(check_key, sizeof(check_key));
+}
+
int
sr_crypto_decrypt_key(struct sr_discipline *sd)
{
@@ -216,9 +308,13 @@ sr_crypto_decrypt_key(struct sr_discipline *sd)
u_char *p, *c;
size_t ksz;
int i, rv = 1;
+ u_char check_digest[SHA1_DIGEST_LENGTH];
DNPRINTF(SR_D_DIS, "%s: sr_crypto_decrypt_key\n", DEVNAME(sd->sd_sc));
+ if (sd->mds.mdd_crypto.scr_meta.scm_check_alg != SR_CRYPTOC_HMAC_SHA1)
+ goto out;
+
c = (u_char *)sd->mds.mdd_crypto.scr_meta.scm_key;
p = (u_char *)sd->mds.mdd_crypto.scr_key;
ksz = sizeof(sd->mds.mdd_crypto.scr_key);
@@ -237,11 +333,22 @@ sr_crypto_decrypt_key(struct sr_discipline *sd)
sd->mds.mdd_crypto.scr_meta.scm_mask_alg);
goto out;
}
- rv = 0; /* Success */
#ifdef SR_DEBUG0
sr_crypto_dumpkeys(sd);
#endif
+ /* Check that the key decrypted properly */
+ sr_crypto_calculate_check_hmac_sha1(sd, check_digest);
+ if (memcmp(sd->mds.mdd_crypto.scr_meta.chk_hmac_sha1.sch_mac,
+ check_digest, sizeof(check_digest)) != 0) {
+ bzero(sd->mds.mdd_crypto.scr_key,
+ sizeof(sd->mds.mdd_crypto.scr_key));
+ bzero(check_digest, sizeof(check_digest));
+ goto out;
+ }
+ bzero(check_digest, sizeof(check_digest));
+
+ rv = 0; /* Success */
out:
/* we don't need the mask key anymore */
bzero(&sd->mds.mdd_crypto.scr_maskkey,
@@ -264,13 +371,14 @@ sr_crypto_create_keys(struct sr_discipline *sd)
if (AES_MAXKEYBYTES < sizeof(sd->mds.mdd_crypto.scr_maskkey))
return (1);
+ /* XXX allow user to specify */
+ sd->mds.mdd_crypto.scr_meta.scm_alg = SR_CRYPTOA_AES_XTS_256;
+
/* generate crypto keys */
arc4random_buf(sd->mds.mdd_crypto.scr_key,
sizeof(sd->mds.mdd_crypto.scr_key));
- /* XXX 128 for now */
- sd->mds.mdd_crypto.scr_meta.scm_alg = SR_CRYPTOA_AES_XTS_128;
-
+ /* Mask the disk keys */
sd->mds.mdd_crypto.scr_meta.scm_mask_alg = SR_CRYPTOM_AES_ECB_256;
if (rijndael_set_key_enc_only(&ctx, sd->mds.mdd_crypto.scr_maskkey,
256) != 0) {
@@ -279,16 +387,22 @@ sr_crypto_create_keys(struct sr_discipline *sd)
bzero(&ctx, sizeof(ctx));
return (1);
}
-
p = (u_char *)sd->mds.mdd_crypto.scr_key;
c = (u_char *)sd->mds.mdd_crypto.scr_meta.scm_key;
ksz = sizeof(sd->mds.mdd_crypto.scr_key);
-
for (i = 0; i < ksz; i += RIJNDAEL128_BLOCK_LEN)
rijndael_encrypt(&ctx, &p[i], &c[i]);
bzero(&ctx, sizeof(ctx));
+
+ /* Prepare key decryption check code */
+ sd->mds.mdd_crypto.scr_meta.scm_check_alg = SR_CRYPTOC_HMAC_SHA1;
+ sr_crypto_calculate_check_hmac_sha1(sd,
+ sd->mds.mdd_crypto.scr_meta.chk_hmac_sha1.sch_mac);
+
+ /* Erase the plaintext disk keys */
bzero(sd->mds.mdd_crypto.scr_key, sizeof(sd->mds.mdd_crypto.scr_key));
+
#ifdef SR_DEBUG0
sr_crypto_dumpkeys(sd);
#endif
@@ -313,10 +427,10 @@ sr_crypto_alloc_resources(struct sr_discipline *sd)
if (sr_alloc_wu(sd))
return (ENOMEM);
if (sr_alloc_ccb(sd))
- return (ENOMEM); /* XXX */
+ return (ENOMEM);
if (sr_crypto_decrypt_key(sd))
- return (1); /* XXX */
+ return (EPERM);
bzero(&cri, sizeof(cri));
cri.cri_alg = CRYPTO_AES_XTS;
@@ -328,7 +442,7 @@ sr_crypto_alloc_resources(struct sr_discipline *sd)
cri.cri_klen = 512;
break;
default:
- return (1); /* XXX */
+ return (EINVAL);
}
cri.cri_key = sd->mds.mdd_crypto.scr_key[0];
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index 5d5dedff200..328052cf077 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.56 2008/06/13 22:08:17 djm Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.57 2008/06/14 00:12:21 djm Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -99,6 +99,7 @@ struct sr_chunk_meta {
#define SR_CRYPTO_KEYBITS 512 /* AES-XTS with 2 * 256 bit keys */
#define SR_CRYPTO_KEYBYTES (SR_CRYPTO_KEYBITS >> 3)
#define SR_CRYPTO_KDFHINTBYTES 256
+#define SR_CRYPTO_CHECKBYTES 64
struct sr_crypto_genkdf {
u_int32_t len;
@@ -116,6 +117,14 @@ struct sr_crypto_kdf_pbkdf2 {
u_int8_t salt[128];
};
+/*
+ * Check that HMAC-SHA1_k(decrypted scm_key) == sch_mac, where
+ * k = SHA1(masking key)
+ */
+struct sr_crypto_chk_hmac_sha1 {
+ u_int8_t sch_mac[20];
+};
+
struct sr_crypto_kdfinfo {
u_int32_t len;
u_int32_t flags;
@@ -145,6 +154,14 @@ struct sr_crypto_metadata {
u_int8_t scm_key[SR_CRYPTO_MAXKEYS][SR_CRYPTO_KEYBYTES];
u_int8_t scm_kdfhint[SR_CRYPTO_KDFHINTBYTES];
+
+ u_int32_t scm_check_alg;
+#define SR_CRYPTOC_HMAC_SHA1 1
+ union {
+ struct sr_crypto_chk_hmac_sha1 chk_hmac_sha1;
+ u_int8_t chk_reserved2[64];
+ } _scm_chk;
+#define chk_hmac_sha1 _scm_chk.chk_hmac_sha1
};
#define SR_OPT_VERSION 1 /* bump when sr_opt_meta changes */