⬢ DragonFlyBSD Kernel Audit
DF-4467 / fix.diff
← back to finding ↓ download raw
--- a/sys/crypto/cryptoapi/cryptoapi.c
+++ b/sys/crypto/cryptoapi/cryptoapi.c
@@ -410,21 +410,23 @@
 }
 
 static inline void
-aes_xts_reinit(struct aes_xts_ctx *ctx, const uint8_t *iv)
+aes_xts_reinit(struct aes_xts_ctx *ctx, const uint8_t *iv, uint8_t *tweak)
 {
-#if 0
 	/*
 	 * Prepare tweak as E_k2(IV). IV is specified as LE representation
 	 * of a 64-bit block number which we allow to be passed in directly.
+	 *
+	 * The tweak is built in a CALLER-SUPPLIED buffer: the session ctx
+	 * may be shared by concurrent cryptoapi_cipher_crypt() calls (e.g.
+	 * dm_target_crypt bio submission from several CPUs), and the XTS
+	 * tweak mutates per data block, so a ctx->tweak field would race.
 	 */
-	/* XXX: possibly use htole64? */
-#endif
-	memcpy(ctx->tweak, iv, AES_XTS_IV_LEN);
+	memcpy(tweak, iv, AES_XTS_IV_LEN);
 
 	/* Last 64 bits of IV are always zero */
-	bzero(ctx->tweak + AES_XTS_IV_LEN, AES_XTS_IV_LEN);
+	bzero(tweak + AES_XTS_IV_LEN, AES_XTS_IV_LEN);
 
-	rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
+	rijndael_encrypt(&ctx->key2, tweak, tweak);
 }
 
 static void
@@ -432,11 +434,12 @@
     bool encrypt)
 {
 	uint8_t block[AES_XTS_BLOCK_LEN];
+	uint8_t tweak[AES_XTS_BLOCK_LEN];
 	struct aes_xts_ctx *ctx = _ctx;
 
-	aes_xts_reinit(ctx, iv);
+	aes_xts_reinit(ctx, iv, tweak);
 
-	crypt_data_xts(&ctx->key1, data, datalen, ctx->tweak,
+	crypt_data_xts(&ctx->key1, data, datalen, tweak,
 	    encrypt ? rijndael_encrypt_wrap : rijndael_decrypt_wrap, block,
 	    AES_XTS_BLOCK_LEN, AES_XTS_ALPHA);
 }
@@ -729,25 +732,16 @@
 };
 
 static inline void
-twofish_xts_reinit(struct twofish_xts_ctx *ctx, const uint8_t *iv)
+twofish_xts_reinit(struct twofish_xts_ctx *ctx, const uint8_t *iv,
+    uint8_t *tweak)
 {
-#if 0
-	u_int64_t blocknum;
-#endif
-
-#if 0
-	/*
-	 * Prepare tweak as E_k2(IV). IV is specified as LE representation
-	 * of a 64-bit block number which we allow to be passed in directly.
-	 */
-	/* XXX: possibly use htole64? */
-#endif
-	memcpy(ctx->tweak, iv, TWOFISH_XTS_IV_LEN);
+	/* tweak is per-call: see aes_xts_reinit() */
+	memcpy(tweak, iv, TWOFISH_XTS_IV_LEN);
 
 	/* Last 64 bits of IV are always zero */
-	bzero(ctx->tweak + TWOFISH_XTS_IV_LEN, TWOFISH_XTS_IV_LEN);
+	bzero(tweak + TWOFISH_XTS_IV_LEN, TWOFISH_XTS_IV_LEN);
 
-	twofish_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
+	twofish_encrypt(&ctx->key2, tweak, tweak);
 }
 
 static int
@@ -782,11 +776,12 @@
     bool encrypt)
 {
 	uint8_t block[TWOFISH_XTS_BLOCK_LEN];
+	uint8_t tweak[TWOFISH_XTS_BLOCK_LEN];
 	struct twofish_xts_ctx *ctx = _ctx;
 
-	twofish_xts_reinit(ctx, iv);
+	twofish_xts_reinit(ctx, iv, tweak);
 
-	crypt_data_xts(&ctx->key1, data, datalen, ctx->tweak,
+	crypt_data_xts(&ctx->key1, data, datalen, tweak,
 	    encrypt ? twofish_encrypt_wrap : twofish_decrypt_wrap, block,
 	    TWOFISH_XTS_BLOCK_LEN, AES_XTS_ALPHA);
 }
@@ -892,27 +887,16 @@
 };
 
 static inline void
-serpent_xts_reinit(struct serpent_xts_ctx *ctx, const uint8_t *iv)
+serpent_xts_reinit(struct serpent_xts_ctx *ctx, const uint8_t *iv,
+    uint8_t *tweak)
 {
-#if 0
-	u_int64_t blocknum;
-	u_int i;
-#endif
-
-#if 0
-	/*
-	 * Prepare tweak as E_k2(IV). IV is specified as LE representation
-	 * of a 64-bit block number which we allow to be passed in directly.
-	 */
-	/* XXX: possibly use htole64? */
-#endif
-
-	memcpy(ctx->tweak, iv, SERPENT_XTS_IV_LEN);
+	/* tweak is per-call: see aes_xts_reinit() */
+	memcpy(tweak, iv, SERPENT_XTS_IV_LEN);
 
 	/* Last 64 bits of IV are always zero */
-	bzero(ctx->tweak + SERPENT_XTS_IV_LEN, SERPENT_XTS_IV_LEN);
+	bzero(tweak + SERPENT_XTS_IV_LEN, SERPENT_XTS_IV_LEN);
 
-	serpent_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
+	serpent_encrypt(&ctx->key2, tweak, tweak);
 }
 
 static int
@@ -947,11 +931,12 @@
     bool encrypt)
 {
 	uint8_t block[SERPENT_XTS_BLOCK_LEN];
+	uint8_t tweak[SERPENT_XTS_BLOCK_LEN];
 	struct serpent_xts_ctx *ctx = _ctx;
 
-	serpent_xts_reinit(ctx, iv);
+	serpent_xts_reinit(ctx, iv, tweak);
 
-	crypt_data_xts(&ctx->key1, data, datalen, ctx->tweak,
+	crypt_data_xts(&ctx->key1, data, datalen, tweak,
 	    encrypt ? serpent_encrypt_wrap : serpent_decrypt_wrap, block,
 	    SERPENT_XTS_BLOCK_LEN, AES_XTS_ALPHA);
 }