AES-NI 256位块加密

AES-NI 256-Bit block encryption

本文关键字:加密 256位 AES-NI      更新时间:2023-10-16

我正试图使用这段代码,这是从英特尔白皮书中提取的,如下所示。我的目标是使用AES-NI执行256位块加密。我已经使用该方法成功地导出了密钥调度,该方法是在Intel 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);
}
}

你有:

UCHAR* Key_Schedule=Key_schedule+4;

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

你要求CPU做一些硬件无法做的事情,因为数据线的连接方式。这是一个粗略的过度简化,但是:您可以认为CPU有16个8位插槽,它必须从中读取。为了读取数据,它发送一个地址,这个地址是字节地址除以16,然后决定从哪个插槽读取。如果组成128位地址的所有16个字节的字节地址在除以16时不相同,则不可能将这16个字节读入16个插槽。

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

SSE操作需要对齐到16来加载和存储[。—AES intrinsic