AES-NI 256位块加密

时间:2014-07-15 09:16:05

标签: c++ encryption cryptography aes aes-ni

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

然而,当我将值传递给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);
}
}

1 个答案:

答案 0 :(得分:2)

你有:

UCHAR* Key_Schedule=Key_schedule+4;

这不对齐Key_Schedule,因为Key_schedule是(我希望!)对齐,并且你已经添加了32位。

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

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

  

SSE操作需要与16对齐才能加载和存储[。] - AES Intrinsics