mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
Ensure our aes_ni_context is 16-byte aligned.
The 32-bit x86 Windows build can crash with an alignment fault the first time it tries to write into the key schedule array, because it turns out that the x86 VS C library's malloc doesn't guarantee 16-byte alignment on the returned block even though there is a machine type that needs it. To avoid having to faff with non-portable library APIs, I solve the problem locally in aes_hw_new, by over-allocating enough to guarantee that an aligned block of the right size must exist somewhere in the region.
This commit is contained in:
parent
2edae0d9d6
commit
ced0f19118
19
sshaes.c
19
sshaes.c
@ -1330,6 +1330,7 @@ typedef struct aes_ni_context aes_ni_context;
|
|||||||
struct aes_ni_context {
|
struct aes_ni_context {
|
||||||
__m128i keysched_e[MAXROUNDKEYS], keysched_d[MAXROUNDKEYS], iv;
|
__m128i keysched_e[MAXROUNDKEYS], keysched_d[MAXROUNDKEYS], iv;
|
||||||
|
|
||||||
|
void *pointer_to_free;
|
||||||
ssh2_cipher ciph;
|
ssh2_cipher ciph;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1338,16 +1339,30 @@ static ssh2_cipher *aes_hw_new(const ssh2_cipheralg *alg)
|
|||||||
if (!aes_hw_available_cached())
|
if (!aes_hw_available_cached())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
aes_ni_context *ctx = snew(aes_ni_context);
|
/*
|
||||||
|
* The __m128i variables in the context structure need to be
|
||||||
|
* 16-byte aligned, but not all malloc implementations that this
|
||||||
|
* code has to work with will guarantee to return a 16-byte
|
||||||
|
* aligned pointer. So we over-allocate, manually realign the
|
||||||
|
* pointer ourselves, and store the original one inside the
|
||||||
|
* context so we know how to free it later.
|
||||||
|
*/
|
||||||
|
void *allocation = smalloc(sizeof(aes_ni_context) + 15);
|
||||||
|
uintptr_t alloc_address = (uintptr_t)allocation;
|
||||||
|
uintptr_t aligned_address = (alloc_address + 15) & ~15;
|
||||||
|
aes_ni_context *ctx = (aes_ni_context *)aligned_address;
|
||||||
|
|
||||||
ctx->ciph.vt = alg;
|
ctx->ciph.vt = alg;
|
||||||
|
ctx->pointer_to_free = allocation;
|
||||||
return &ctx->ciph;
|
return &ctx->ciph;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aes_hw_free(ssh2_cipher *ciph)
|
static void aes_hw_free(ssh2_cipher *ciph)
|
||||||
{
|
{
|
||||||
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
|
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
|
||||||
|
void *allocation = ctx->pointer_to_free;
|
||||||
smemclr(ctx, sizeof(*ctx));
|
smemclr(ctx, sizeof(*ctx));
|
||||||
sfree(ctx);
|
sfree(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aes_hw_setkey(ssh2_cipher *ciph, const void *vkey)
|
static void aes_hw_setkey(ssh2_cipher *ciph, const void *vkey)
|
||||||
|
Loading…
Reference in New Issue
Block a user