diff --git a/library/aes.c b/library/aes.c index 36aa7f2999..c68eddb012 100644 --- a/library/aes.c +++ b/library/aes.c @@ -983,6 +983,39 @@ void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_AESNI_HAVE_CODE) || \ + (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) +/* VIA Padlock and our intrinsics-based implementation of AESNI require + * the round keys to be aligned on a 16-byte boundary. We take care of this + * before creating them, but the AES context may have moved (this can happen + * if the library is called from a language with managed memory), and in later + * calls it might have a different alignment with respect to 16-byte memory. + * So we may need to realign. + * NOTE: In the LTS branch, the context contains a pointer to within itself, + * so if it has been moved, things will probably go pear-shaped. We keep this + * code for compatibility with the development branch, in case of future changes. + */ +static void aes_maybe_realign(mbedtls_aes_context *ctx) +{ + /* We want a 16-byte alignment. Note that rk and buf are pointers to uint32_t + * and offset is in units of uint32_t words = 4 bytes. We want a + * 4-word alignment. */ + unsigned current_offset = (unsigned)(ctx->rk - ctx->buf); + uintptr_t current_address = (uintptr_t)ctx->rk; + unsigned current_alignment = (current_address & 0x0000000f) / 4; + if (current_alignment != 0) { + unsigned new_offset = current_offset + 4 - current_alignment; + if (new_offset >= 4) { + new_offset -= 4; + } + memmove(ctx->buf + new_offset, // new address + ctx->buf + current_offset, // current address + (ctx->nr + 1) * 16); // number of round keys * bytes per rk + ctx->rk = ctx->buf + new_offset; + } +} +#endif + /* * AES-ECB block encryption/decryption */ @@ -999,19 +1032,15 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + aes_maybe_realign(ctx); return mbedtls_aesni_crypt_ecb(ctx, mode, input, output); } #endif #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) if (aes_padlock_ace) { - if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) { - return 0; - } - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // + aes_maybe_realign(ctx); + return mbedtls_padlock_xcryptecb(ctx, mode, input, output); } #endif