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:
Mounir IDRASSI
2026-10-16 14:47:34 +09:00
parent ced6890945
commit 762b374db0
3 changed files with 116 additions and 22 deletions
+52 -12
View File
@@ -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
View File
@@ -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
View File
@@ -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