mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-10-21 13:52:36 +00:00
Windows: handle extended processor state save failures
Use per-context software SHA-256/SHA-512 after a failed state save without changing global dispatch. Return an error and clear Argon2's output before its accelerated core can run.
This commit is contained in:
+52
-12
@@ -44,6 +44,15 @@
|
||||
#include "Pkcs5.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
/* Driver calls can select a software initializer without changing global dispatch. */
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
#define SHA256_HMAC_BEGIN sha256Begin
|
||||
#define SHA512_HMAC_BEGIN sha512Begin
|
||||
#else
|
||||
#define SHA256_HMAC_BEGIN sha256_begin
|
||||
#define SHA512_HMAC_BEGIN sha512_begin
|
||||
#endif
|
||||
|
||||
#if !defined(TC_WINDOWS_BOOT) || defined(TC_WINDOWS_BOOT_SHA2)
|
||||
|
||||
typedef struct hmac_sha256_ctx_struct
|
||||
@@ -96,10 +105,15 @@ void hmac_sha256
|
||||
int b;
|
||||
unsigned char key[SHA256_DIGESTSIZE];
|
||||
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*sha256Begin)(sha256_ctx*) = sha256_begin;
|
||||
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
|
||||
XSTATE_SAVE SaveState;
|
||||
if (IsCpuIntel() && HasSAVX())
|
||||
{
|
||||
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
|
||||
if (!NT_SUCCESS(saveStatus))
|
||||
sha256Begin = sha256_begin_software;
|
||||
}
|
||||
#endif
|
||||
/* If the key is longer than the hash algorithm block size,
|
||||
let key = sha256(key), as per HMAC specifications. */
|
||||
@@ -107,7 +121,7 @@ void hmac_sha256
|
||||
{
|
||||
sha256_ctx tctx;
|
||||
|
||||
sha256_begin (&tctx);
|
||||
SHA256_HMAC_BEGIN (&tctx);
|
||||
sha256_hash (k, lk, &tctx);
|
||||
sha256_end (key, &tctx);
|
||||
|
||||
@@ -120,7 +134,7 @@ void hmac_sha256
|
||||
/**** Precompute HMAC Inner Digest ****/
|
||||
|
||||
ctx = &(hmac.inner_digest_ctx);
|
||||
sha256_begin (ctx);
|
||||
SHA256_HMAC_BEGIN (ctx);
|
||||
|
||||
/* Pad the key for inner digest */
|
||||
for (b = 0; b < lk; ++b)
|
||||
@@ -132,7 +146,7 @@ void hmac_sha256
|
||||
/**** Precompute HMAC Outer Digest ****/
|
||||
|
||||
ctx = &(hmac.outer_digest_ctx);
|
||||
sha256_begin (ctx);
|
||||
SHA256_HMAC_BEGIN (ctx);
|
||||
|
||||
for (b = 0; b < lk; ++b)
|
||||
buf[b] = (unsigned char) (k[b] ^ 0x5C);
|
||||
@@ -226,10 +240,15 @@ void derive_key_sha256 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
#ifndef TC_WINDOWS_BOOT
|
||||
unsigned char key[SHA256_DIGESTSIZE];
|
||||
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*sha256Begin)(sha256_ctx*) = sha256_begin;
|
||||
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
|
||||
XSTATE_SAVE SaveState;
|
||||
if (IsCpuIntel() && HasSAVX())
|
||||
{
|
||||
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
|
||||
if (!NT_SUCCESS(saveStatus))
|
||||
sha256Begin = sha256_begin_software;
|
||||
}
|
||||
#endif
|
||||
/* If the password is longer than the hash algorithm block size,
|
||||
let pwd = sha256(pwd), as per HMAC specifications. */
|
||||
@@ -237,7 +256,7 @@ void derive_key_sha256 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
{
|
||||
sha256_ctx tctx;
|
||||
|
||||
sha256_begin (&tctx);
|
||||
SHA256_HMAC_BEGIN (&tctx);
|
||||
sha256_hash (pwd, pwd_len, &tctx);
|
||||
sha256_end (key, &tctx);
|
||||
|
||||
@@ -262,7 +281,7 @@ void derive_key_sha256 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
/**** Precompute HMAC Inner Digest ****/
|
||||
|
||||
ctx = &(hmac.inner_digest_ctx);
|
||||
sha256_begin (ctx);
|
||||
SHA256_HMAC_BEGIN (ctx);
|
||||
|
||||
/* Pad the key for inner digest */
|
||||
for (b = 0; b < pwd_len; ++b)
|
||||
@@ -274,7 +293,7 @@ void derive_key_sha256 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
/**** Precompute HMAC Outer Digest ****/
|
||||
|
||||
ctx = &(hmac.outer_digest_ctx);
|
||||
sha256_begin (ctx);
|
||||
SHA256_HMAC_BEGIN (ctx);
|
||||
|
||||
for (b = 0; b < pwd_len; ++b)
|
||||
buf[b] = (unsigned char) (pwd[b] ^ 0x5C);
|
||||
@@ -375,10 +394,15 @@ void hmac_sha512
|
||||
int b;
|
||||
unsigned char key[SHA512_DIGESTSIZE];
|
||||
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*sha512Begin)(sha512_ctx*) = sha512_begin;
|
||||
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
|
||||
XSTATE_SAVE SaveState;
|
||||
if (IsCpuIntel() && HasSAVX())
|
||||
{
|
||||
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
|
||||
if (!NT_SUCCESS(saveStatus))
|
||||
sha512Begin = sha512_begin_software;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the key is longer than the hash algorithm block size,
|
||||
@@ -387,7 +411,7 @@ void hmac_sha512
|
||||
{
|
||||
sha512_ctx tctx;
|
||||
|
||||
sha512_begin (&tctx);
|
||||
SHA512_HMAC_BEGIN (&tctx);
|
||||
sha512_hash (k, lk, &tctx);
|
||||
sha512_end (key, &tctx);
|
||||
|
||||
@@ -400,7 +424,7 @@ void hmac_sha512
|
||||
/**** Precompute HMAC Inner Digest ****/
|
||||
|
||||
ctx = &(hmac.inner_digest_ctx);
|
||||
sha512_begin (ctx);
|
||||
SHA512_HMAC_BEGIN (ctx);
|
||||
|
||||
/* Pad the key for inner digest */
|
||||
for (b = 0; b < lk; ++b)
|
||||
@@ -412,7 +436,7 @@ void hmac_sha512
|
||||
/**** Precompute HMAC Outer Digest ****/
|
||||
|
||||
ctx = &(hmac.outer_digest_ctx);
|
||||
sha512_begin (ctx);
|
||||
SHA512_HMAC_BEGIN (ctx);
|
||||
|
||||
for (b = 0; b < lk; ++b)
|
||||
buf[b] = (unsigned char) (k[b] ^ 0x5C);
|
||||
@@ -470,10 +494,15 @@ void derive_key_sha512 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
int b, l, r;
|
||||
unsigned char key[SHA512_DIGESTSIZE];
|
||||
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*sha512Begin)(sha512_ctx*) = sha512_begin;
|
||||
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
|
||||
XSTATE_SAVE SaveState;
|
||||
if (IsCpuIntel() && HasSAVX())
|
||||
{
|
||||
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
|
||||
if (!NT_SUCCESS(saveStatus))
|
||||
sha512Begin = sha512_begin_software;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the password is longer than the hash algorithm block size,
|
||||
@@ -482,7 +511,7 @@ void derive_key_sha512 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
{
|
||||
sha512_ctx tctx;
|
||||
|
||||
sha512_begin (&tctx);
|
||||
SHA512_HMAC_BEGIN (&tctx);
|
||||
sha512_hash (pwd, pwd_len, &tctx);
|
||||
sha512_end (key, &tctx);
|
||||
|
||||
@@ -506,7 +535,7 @@ void derive_key_sha512 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
/**** Precompute HMAC Inner Digest ****/
|
||||
|
||||
ctx = &(hmac.inner_digest_ctx);
|
||||
sha512_begin (ctx);
|
||||
SHA512_HMAC_BEGIN (ctx);
|
||||
|
||||
/* Pad the key for inner digest */
|
||||
for (b = 0; b < pwd_len; ++b)
|
||||
@@ -518,7 +547,7 @@ void derive_key_sha512 (const unsigned char *pwd, int pwd_len, const unsigned ch
|
||||
/**** Precompute HMAC Outer Digest ****/
|
||||
|
||||
ctx = &(hmac.outer_digest_ctx);
|
||||
sha512_begin (ctx);
|
||||
SHA512_HMAC_BEGIN (ctx);
|
||||
|
||||
for (b = 0; b < pwd_len; ++b)
|
||||
buf[b] = (unsigned char) (pwd[b] ^ 0x5C);
|
||||
@@ -1331,7 +1360,15 @@ int derive_key_argon2(const unsigned char *pwd, int pwd_len, const unsigned char
|
||||
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
|
||||
XSTATE_SAVE SaveState;
|
||||
if (HasSAVX2())
|
||||
{
|
||||
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
|
||||
if (!NT_SUCCESS(saveStatus))
|
||||
{
|
||||
result = (saveStatus == STATUS_INSUFFICIENT_RESOURCES)
|
||||
? ARGON2_MEMORY_ALLOCATION_ERROR : ARGON2_INCORRECT_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
result = argon2id_hash_raw(
|
||||
iterations, // number of iterations
|
||||
@@ -1342,6 +1379,9 @@ int derive_key_argon2(const unsigned char *pwd, int pwd_len, const unsigned char
|
||||
dk, dklen,// derived key and its length
|
||||
pAbortKeyDerivation
|
||||
);
|
||||
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
err:
|
||||
#endif
|
||||
if (0 != result)
|
||||
{
|
||||
// If the Argon2 derivation fails, ensure unchecked legacy callers cannot use stale data.
|
||||
|
||||
+50
-8
@@ -251,24 +251,40 @@ void sha512_begin(sha512_ctx* ctx)
|
||||
#endif
|
||||
transfunc = StdTransform;
|
||||
}
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
ctx->transform = transfunc;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void sha512_begin_software(sha512_ctx* ctx)
|
||||
{
|
||||
sha512_begin(ctx);
|
||||
ctx->transform = StdTransform;
|
||||
}
|
||||
#endif
|
||||
|
||||
void sha512_end(unsigned char * result, sha512_ctx* ctx)
|
||||
{
|
||||
int i;
|
||||
uint_64t mlen, pos = ctx->count[0];
|
||||
uint_8t* m = (uint_8t*) ctx->wbuf;
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
transformFn transform = ctx->transform;
|
||||
#else
|
||||
transformFn transform = transfunc;
|
||||
#endif
|
||||
m[pos++] = 0x80;
|
||||
if (pos > 112)
|
||||
{
|
||||
memset(m + pos, 0, (size_t) (128 - pos));
|
||||
transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
pos = 0;
|
||||
}
|
||||
memset(m + pos, 0, (size_t) (128 - pos));
|
||||
mlen = SHA2_BE64(ctx->count[1]);
|
||||
memcpy(m + (128 - 8), &mlen, 64 / 8);
|
||||
transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
ctx->hash[i] = SHA2_BE64(ctx->hash[i]);
|
||||
@@ -281,10 +297,15 @@ void sha512_hash(const unsigned char * data, uint_64t len, sha512_ctx *ctx)
|
||||
uint_64t pos = ctx->count[0];
|
||||
uint_64t total = ctx->count[1];
|
||||
uint_8t* m = (uint_8t*) ctx->wbuf;
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
transformFn transform = ctx->transform;
|
||||
#else
|
||||
transformFn transform = transfunc;
|
||||
#endif
|
||||
if (pos && pos + len >= 128)
|
||||
{
|
||||
memcpy(m + pos, data, (size_t) (128 - pos));
|
||||
transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
len -= 128 - pos;
|
||||
total += (128 - pos) * 8;
|
||||
data += 128 - pos;
|
||||
@@ -294,7 +315,7 @@ void sha512_hash(const unsigned char * data, uint_64t len, sha512_ctx *ctx)
|
||||
{
|
||||
uint_64t blocks = len / 128;
|
||||
uint_64t bytes = blocks * 128;
|
||||
transfunc(ctx, (void*)data, blocks);
|
||||
transform(ctx, (void*)data, blocks);
|
||||
len -= bytes;
|
||||
total += (bytes)* 8;
|
||||
data += bytes;
|
||||
@@ -853,24 +874,40 @@ void sha256_begin(sha256_ctx* ctx)
|
||||
sha256transfunc = StdSha256Transform;
|
||||
#endif
|
||||
}
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
ctx->transform = sha256transfunc;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void sha256_begin_software(sha256_ctx* ctx)
|
||||
{
|
||||
sha256_begin(ctx);
|
||||
ctx->transform = StdSha256Transform;
|
||||
}
|
||||
#endif
|
||||
|
||||
void sha256_end(unsigned char * result, sha256_ctx* ctx)
|
||||
{
|
||||
int i;
|
||||
uint_64t mlen, pos = ctx->count[0];
|
||||
uint_8t* m = (uint_8t*) ctx->wbuf;
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
sha256transformFn transform = ctx->transform;
|
||||
#else
|
||||
sha256transformFn transform = sha256transfunc;
|
||||
#endif
|
||||
m[pos++] = 0x80;
|
||||
if (pos > 56)
|
||||
{
|
||||
memset(m + pos, 0, (size_t) (64 - pos));
|
||||
sha256transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
pos = 0;
|
||||
}
|
||||
memset(m + pos, 0, (size_t) (56 - pos));
|
||||
mlen = SHA2_BE64((uint_64t) ctx->count[1]);
|
||||
memcpy(m + (64 - 8), &mlen, 64 / 8);
|
||||
sha256transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
ctx->hash[i] = SHA2_BE32(ctx->hash[i]);
|
||||
@@ -883,10 +920,15 @@ void sha256_hash(const unsigned char * data, uint_32t len, sha256_ctx *ctx)
|
||||
uint_32t pos = ctx->count[0];
|
||||
uint_32t total = ctx->count[1];
|
||||
uint_8t* m = (uint_8t*) ctx->wbuf;
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
sha256transformFn transform = ctx->transform;
|
||||
#else
|
||||
sha256transformFn transform = sha256transfunc;
|
||||
#endif
|
||||
if (pos && pos + len >= 64)
|
||||
{
|
||||
memcpy(m + pos, data, 64 - pos);
|
||||
sha256transfunc(ctx, m, 1);
|
||||
transform(ctx, m, 1);
|
||||
len -= 64 - pos;
|
||||
total += (64 - pos) * 8;
|
||||
data += 64 - pos;
|
||||
@@ -896,7 +938,7 @@ void sha256_hash(const unsigned char * data, uint_32t len, sha256_ctx *ctx)
|
||||
{
|
||||
uint_32t blocks = len / 64;
|
||||
uint_32t bytes = blocks * 64;
|
||||
sha256transfunc(ctx, (void*)data, blocks);
|
||||
transform(ctx, (void*)data, blocks);
|
||||
len -= bytes;
|
||||
total += (bytes)* 8;
|
||||
data += bytes;
|
||||
|
||||
+14
-2
@@ -39,14 +39,20 @@ extern "C" {
|
||||
typedef struct wc_Sha512 sha512_ctx;
|
||||
typedef struct wc_Sha256 sha256_ctx;
|
||||
#else
|
||||
typedef struct
|
||||
typedef struct sha512_ctx
|
||||
{ uint_64t count[2];
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*transform)(struct sha512_ctx*, void*, uint_64t);
|
||||
#endif
|
||||
SHA2_ALIGN uint_64t hash[8];
|
||||
SHA2_ALIGN uint_64t wbuf[16];
|
||||
} sha512_ctx;
|
||||
|
||||
typedef struct
|
||||
typedef struct sha256_ctx
|
||||
{ uint_32t count[2];
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
void (*transform)(struct sha256_ctx*, void*, uint_64t);
|
||||
#endif
|
||||
SHA2_ALIGN uint_32t hash[8];
|
||||
SHA2_ALIGN uint_32t wbuf[16];
|
||||
} sha256_ctx;
|
||||
@@ -63,6 +69,12 @@ void sha256_hash(const unsigned char * source, uint_32t sourceLen, sha256_ctx *c
|
||||
void sha256_end(unsigned char * result, sha256_ctx* ctx);
|
||||
void sha256(unsigned char * result, const unsigned char* source, uint_32t sourceLen);
|
||||
|
||||
#if defined(DEVICE_DRIVER) && !defined(_M_ARM64)
|
||||
/* Per-context fallback when the driver cannot save extended processor state. */
|
||||
void sha512_begin_software(sha512_ctx* ctx);
|
||||
void sha256_begin_software(sha256_ctx* ctx);
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user