1

我正在尝试使用取自英特尔白皮书的代码,如下所示。我的目标是使用 AES-NI 执行 256 位块加密。我已经使用该方法成功导出了密钥计划,该方法在用于扩展密钥的英特尔 AES-NI 库中提供:iEncExpandKey256(key,expandedKey); 并且扩展密钥在我的非 AES-NI AES 实现中工作正常。

但是,当我将值传递给我时,Rijndael256_encrypt(testVector,testResult,expandedKey,32,1) ; 我收到“尝试访问受保护的内存,这通常表明内存已损坏”的错误,导致此问题的代码行data1 = _mm_xor_si128(data1, KS[0]); /* round 0 (initial xor) */如下所示。

所以我的问题是,这样的错误可能是什么错误?我目前的假设是 data1 和 KS[0] 的大小可能不同,我目前仍在验证它。除此之外,我不确定我还能在哪里看。如果有人能指出正确的方向来解决此错误,将不胜感激。

#include <wmmintrin.h>
#include <emmintrin.h>
#include <smmintrin.h>
void Rijndael256_encrypt (unsigned char *in,
unsigned char *out,
unsigned char *Key_Schedule,
unsigned long long length,
int number_of_rounds)
{
__m128i tmp1, tmp2, data1 ,data2;
__m128i RIJNDAEL256_MASK =
_mm_set_epi32(0x03020d0c, 0x0f0e0908, 0x0b0a0504, 0x07060100);
__m128i BLEND_MASK=
_mm_set_epi32(0x80000000, 0x80800000, 0x80800000, 0x80808000);
__m128i *KS = (__m128i*)Key_Schedule;
int i,j;
for(i=0; i < length/32; i++) { /* loop over the data blocks */
data1 = _mm_loadu_si128(&((__m128i*)in)[i*2+0]); /* load data block */
data2 = _mm_loadu_si128(&((__m128i*)in)[i*2+1]);
data1 = _mm_xor_si128(data1, KS[0]); /* round 0 (initial xor) */
data2 = _mm_xor_si128(data2, KS[1]);
/* Do number_of_rounds-1 AES rounds */
for(j=1; j < number_of_rounds; j++) {
/*Blend to compensate for the shift rows shifts bytes between two
128 bit blocks*/
tmp1 = _mm_blendv_epi8(data1, data2, BLEND_MASK);
tmp2 = _mm_blendv_epi8(data2, data1, BLEND_MASK);
/*Shuffle that compensates for the additional shift in rows 3 and 4
as opposed to rijndael128 (AES)*/
tmp1 = _mm_shuffle_epi8(tmp1, RIJNDAEL256_MASK);
tmp2 = _mm_shuffle_epi8(tmp2, RIJNDAEL256_MASK);
/*This is the encryption step that includes sub bytes, shift rows,
mix columns, xor with round key*/
data1 = _mm_aesenc_si128(tmp1, KS[j*2]);
data2 = _mm_aesenc_si128(tmp2, KS[j*2+1]);
}
tmp1 = _mm_blendv_epi8(data1, data2, BLEND_MASK);
tmp2 = _mm_blendv_epi8(data2, data1, BLEND_MASK);
tmp1 = _mm_shuffle_epi8(tmp1, RIJNDAEL256_MASK);
tmp2 = _mm_shuffle_epi8(tmp2, RIJNDAEL256_MASK);
tmp1 = _mm_aesenclast_si128(tmp1, KS[j*2+0]); /*last AES round */
tmp2 = _mm_aesenclast_si128(tmp2, KS[j*2+1]);
_mm_storeu_si128(&((__m128i*)out)[i*2+0],tmp1);
_mm_storeu_si128(&((__m128i*)out)[i*2+1],tmp2);
}
}
4

1 回答 1

2

你有:

UCHAR* Key_Schedule=Key_schedule+4;

这 unaligns Key_Schedule,因为Key_schedule(我希望!)对齐并且您已向其添加了 32 位。

由于数据线的接线方式,您要求 CPU 执行硬件无法执行的操作。这是一个严重的过度简化,但是:您可以将 CPU 视为必须从中读取的 16 个 8 位插槽。要读取数据,它会发送一个地址,该地址是字节地址除以 16,然后决定从哪个插槽读取。如果组成 128 位地址的所有 16 个字节的字节地址在除以 16 时不相同,则无法将这 16 个字节读入 16 个插槽。

如果您不想对函数的所有参数施加对齐要求,那么您需要让函数本身将它们复制到对齐的缓冲区中。

SSE 操作需要对齐到 16 以进行加载和存储[。] -- AES Intrinsics

于 2014-07-15T10:17:34.290 回答