256-битное блочное шифрование AES-NI

Я пытаюсь использовать этот код, который взят из технической документации Intel, как показано ниже.
Моя цель — выполнить 256-битное блочное шифрование с использованием AES-NI.
Я успешно вывел расписание ключей, используя метод, этот метод был предоставлен в библиотеке Intel AES-NI, которая используется для расширения ключей: iEncExpandKey256(key,expandedKey);
и extendedKey прекрасно работает в моей реализации AES без AES-NI.

Тем не менее, когда я передаю значения в 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

Решение

У тебя есть:

UCHAR* Key_Schedule=Key_schedule+4;

Это выравнивает Key_Schedule, поскольку Key_schedule выровнен (я надеюсь!), и вы добавили к нему 32-битную версию.

Вы просите процессор сделать что-то, на что аппаратное обеспечение не способно из-за способа соединения линий данных. Это грубое упрощение, но: вы можете думать о ЦП как о шестнадцати 8-битных слотах, из которых он должен читать. Чтобы прочитать данные, он отправляет адрес, который является байтовым адресом, разделенным на 16, а затем решает, из каких слотов читать. Если байтовый адрес всех 16 байтов, составляющих 128-битный адрес, не совпадает при делении на 16, то невозможно прочитать 16 байтов в 16 слотах.

Если вы не хотите навязывать требования выравнивания для всех параметров функции, то вам нужно, чтобы сама функция скопировала их в выровненные буферы.

Операции SSE должны быть выровнены до 16 для загрузки и хранения [.] — AES Intrinsics

2

Другие решения