我正在移植一个使用AES加密和解密指令的应用程序,以将某些数据从x86随机分配到POWER8。我用_mm_aesdec_si128指令碰壁,它似乎与等效的IBM __builtin_crypto_vncipher有所不同。 https://link.springer.com/content/pdf/10.1007/978-3-642-03317-9_4.pdf(第52-54页)上的文档提到它遵循FIPS 197。 位于https://ibm.ent.box.com/s/jd5w15gz301s5b5dt375mshpq9c3lh4u,第305页的IBM文档还说它遵循FIPS197,唯一的区别是InvMixColumns和带有圆键的xor的顺序被翻转了,但这会改变结果吗?
如果结果不同,他们俩怎么能说他们遵循规范?
以下C程序在x86上可以正常运行,但在ppc64中将为aesdec输出错误的结果。 ppc64中的aesenc可以按预期工作。
目前,我通过使用aesdec的软件实现解决了该问题,但是我想在硬件中做所有事情。
C程序:
//compile with "gcc -maes aestest.c -o aestest" in x86
//compile with "gcc -mcrypto -flax-vector-conversions aestest.c -o aestest" in power8
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#ifdef __x86_64__
#include <x86intrin.h>
__m128i aesenc(__m128i d,__m128i k){
return _mm_aesenc_si128(d,k);
}
__m128i aesdec(__m128i d,__m128i k){
return _mm_aesdec_si128(d,k);
}
#endif
#ifdef __PPC64__
#include <endian.h>
#include <altivec.h>
#undef vector
#undef pixel
#undef bool
typedef __vector uint8_t __m128i;
//flip vector to BE order
__m128i vrev(__m128i v){
#if __BYTE_ORDER == __BIG_ENDIAN
return v;
#else
return vec_perm(v,(__m128i){0},(__m128i){15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0});
#endif
}
__m128i aesenc(__m128i d,__m128i k){
return vrev(__builtin_crypto_vcipher(vrev(d),vrev(k)));
}
__m128i aesdec(__m128i d,__m128i k){
return vrev(__builtin_crypto_vncipher(vrev(d),vrev(k)));
}
#endif
void print_m128(char* msg, __m128i v){
uint8_t* t = (uint8_t*)&v;
printf("%s: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",msg,t[0],t[1],t[2],t[3], t[4],t[5],t[6],t[7], t[8],t[9],t[10],t[11], t[12],t[13],t[14],t[15]) ;
}
int main(int argc,char* argv[]){
uint8_t msg[] = "0123456789abcde";
uint8_t key1[] = {255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255};
uint8_t key2[] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
uint8_t* c;
__m128i xmm1 = (__m128i){0};
__m128i xmm2 = (__m128i){0};
__m128i encR = (__m128i){0};
__m128i decR = (__m128i){0};
//zero test
printf("zero test\n");
print_m128("xmm1",xmm1);
print_m128("xmm2",xmm2);
encR = aesenc(xmm1,xmm2);
decR = aesdec(xmm1,xmm2);
print_m128("enc ",encR);
print_m128("dec ",decR);
//zero key test
printf("zero key test\n");
c = (uint8_t*)&xmm1;
memcpy(c,msg,16);
print_m128("xmm1",xmm1);
print_m128("xmm2",xmm2);
encR = aesenc(xmm1,xmm2);
decR = aesdec(xmm1,xmm2);
print_m128("enc ",encR);
print_m128("dec ",decR);
//ff key test
printf("ff key test\n");
c = (uint8_t*)&xmm1;
memcpy(c,msg,16);
c = (uint8_t*)&xmm2;
memcpy(c,key1,16);
print_m128("xmm1",xmm1);
print_m128("xmm2",xmm2);
encR = aesenc(xmm1,xmm2);
decR = aesdec(xmm1,xmm2);
print_m128("enc ",encR);
print_m128("dec ",decR);
//key test
printf("key test\n");
c = (uint8_t*)&xmm1;
memcpy(c,msg,16);
c = (uint8_t*)&xmm2;
memcpy(c,key2,16);
print_m128("xmm1",xmm1);
print_m128("xmm2",xmm2);
encR = aesenc(xmm1,xmm2);
decR = aesdec(xmm1,xmm2);
print_m128("enc ",encR);
print_m128("dec ",decR);
}
#Results in x86:
zero test
xmm1: 00000000000000000000000000000000
xmm2: 00000000000000000000000000000000
enc : 63636363636363636363636363636363
dec : 52525252525252525252525252525252
zero key test
xmm1: 30313233343536373839616263646500
xmm2: 00000000000000000000000000000000
enc : 257af2b38828ceea727eb74610cbd39b
dec : a903befadbaa6d0dc8b9a78af780e18f
ff key test
xmm1: 30313233343536373839616263646500
xmm2: ffffffffffffffffffffffffffffffff
enc : da850d4c77d731158d8148b9ef342c64
dec : 56fc4105245592f237465875087f1e70
key test
xmm1: 30313233343536373839616263646500
xmm2: 00112233445566778899aabbccddeeff
enc : 256bd080cc7da89dfae71dfddc163d64
dec : a9129cc99fff0b7a40200d313b5d0f70
#Results in ppc64:
zero test
xmm1: 00000000000000000000000000000000
xmm2: 00000000000000000000000000000000
enc : 63636363636363636363636363636363
dec : 52525252525252525252525252525252
zero key test
xmm1: 30313233343536373839616263646500
xmm2: 00000000000000000000000000000000
enc : 257af2b38828ceea727eb74610cbd39b
dec : a903befadbaa6d0dc8b9a78af780e18f
ff key test
xmm1: 30313233343536373839616263646500
xmm2: ffffffffffffffffffffffffffffffff
enc : da850d4c77d731158d8148b9ef342c64
dec : 56fc4105245592f237465875087f1e70
key test
xmm1: 30313233343536373839616263646500
xmm2: 00112233445566778899aabbccddeeff
enc : 256bd080cc7da89dfae71dfddc163d64
dec : 03fc36273511a194eacea7df91b3a59e
如图所示,最后一次测试失败。
答案 0 :(得分:2)
解决方案是使用零键在中间返回标识中执行异或步骤,然后在末尾使用实键进行异或。
__m128i aesd(__m128i d,__m128i k){
__m128i out = vrev(__builtin_crypto_vncipher(vrev(d),(__m128i){0}));
return vec_xor(out,k);
}