mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +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 {
|
||||
__m128i keysched_e[MAXROUNDKEYS], keysched_d[MAXROUNDKEYS], iv;
|
||||
|
||||
void *pointer_to_free;
|
||||
ssh2_cipher ciph;
|
||||
};
|
||||
|
||||
@ -1338,16 +1339,30 @@ static ssh2_cipher *aes_hw_new(const ssh2_cipheralg *alg)
|
||||
if (!aes_hw_available_cached())
|
||||
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->pointer_to_free = allocation;
|
||||
return &ctx->ciph;
|
||||
}
|
||||
|
||||
static void aes_hw_free(ssh2_cipher *ciph)
|
||||
{
|
||||
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
|
||||
void *allocation = ctx->pointer_to_free;
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
sfree(allocation);
|
||||
}
|
||||
|
||||
static void aes_hw_setkey(ssh2_cipher *ciph, const void *vkey)
|
||||
|
Loading…
Reference in New Issue
Block a user