【发布时间】:2018-01-24 00:58:52
【问题描述】:
非常感谢,我正在尝试优化用C编写的Kasumi算法。FI函数中有S-box用于加密数据,S7-box有127个元素,S9-box有512个元素。 FI函数代码如下:
static u16 FI(u16 in, u16 subkey)
{
static u16 s7[] = {...};
static u16 s9[] = {...};
nine = (u16)(in>>7);
seven = (u16)(in&0x7F);
/* Now run the various operations */
nine = (u16)(S9[nine] ^ seven);
seven = (u16)(S7[seven] ^ (nine & 0x7F));
seven ^= (subkey>>9);
nine ^= (subkey&0x1FF);
nine = (u16)(S9[nine] ^ seven);
seven = (u16)(S7[seven] ^ (nine & 0x7F));
in = (u16)((seven<<9) + nine);
return( in );
}
u16 表示无符号短。
通过一些转换。我将 S7-box 和 S9-box 合并到 S16-box,并使用 avx 指令使 16 个数据并行。 FI函数代码如下:
static u16 FI(__m256i in, u16 subkey)
{
u16 arr[16];
_mm256_store_si256((__m256i*)arr, in);
u8 i;
for(i = 0; i < 16; i++)
{
arr[i] = (u16)(s16[arr[i]] ^ subkey);
arr[i] = (arr[i] << 7) | (arr[i] >> 9);
arr[i] = s16[arr[i]];
}
in = _mm256_load_si256((__m256i*)arr);
}
S16-box 有 65536 个元素,所以可能会发生一些缓存未命中。我还使用收集指令,例如:
inline static __m256i FI( __m256i in, u16 subkey )
{
__m256i _tmp = _mm256_set1_epi32(0xffff);
__m256i even_sequence = _mm256_and_si256(in, _tmp);
__m256i odd_sequence = _mm256_srli_epi32(in, 16);
even_sequence = _mm256_i32gather_epi32((int const*)s16, even_sequence, 2);
__m256i _subkey = _mm256_set1_epi16(subkey);
even_sequence = _mm256_xor_si256(even_sequence, _subkey);
even_sequence = _mm256_and_si256(even_sequence, _tmp);
odd_sequence = _mm256_i32gather_epi32((int const*)s16, odd_sequence, 2);
odd_sequence = _mm256_xor_si256(odd_sequence, _subkey);
odd_sequence = _mm256_and_si256(odd_sequence, _tmp);
// rotate
__m256i hi = _mm256_slli_epi16(even_sequence, 7);
__m256i lo = _mm256_srli_epi16(even_sequence, 9);
even_sequence = _mm256_or_si256(hi, lo);
//same for odd
hi = _mm256_slli_epi16(odd_sequence, 7);
lo = _mm256_srli_epi16(odd_sequence, 9);
odd_sequence = _mm256_or_si256(hi, lo);
even_sequence = _mm256_i32gather_epi32((int const*)s16, even_sequence, 2);
odd_sequence = _mm256_i32gather_epi32((int const*)s16, odd_sequence, 2);
even_sequence = _mm256_and_si256(even_sequence, _tmp);
odd_sequence = _mm256_slli_epi32(odd_sequence, 16);
in = _mm256_or_si256(even_sequence, odd_sequence);
return in;
}
但是性能不能满足要求,我也考虑bit-slice。我读了一篇论文,它可以并行处理 128 个数据,但需要一些硬件支持。我认为位转置操作很耗时并且有很多限制。
非常感谢!
【问题讨论】:
-
使用同一个子密钥加密多少字节/位? (您建议使用 16,但 Kasumi AFAIK 以 8 字节块加密数据?)添加 sbox 生成器功能怎么样?
-
那么这三个变体都是等价的吗?您是否对它们进行了描述,您能否分享一些数字,它们之间的差异有多大,或者最终大部分时间都花在了哪里?或者如果可能(足够短),添加一些初始化代码以使代码为minimal reproducible example,这样可以自己尝试,但仍然添加一些关于您当前位置的上下文(您离要求有多少)会很好。跨度>
-
@Bai,你能添加一些 L1 缓存未命中的数量吗?
-
使用 C11
_Alignas(32) u16 arr[16];确保 256b 存储不会出错。 (如果还没有,也许您正在使用将_mm256_store_si256编译为vmovdqu的编译器。某些编译器(如gcc)会将其编译为vmovdqa,因此它会在未对齐时出错,而不是可能运行得更慢(例如,对于缓存行拆分)。我想这只是您的参考实现,而不是您正在优化的内容,但在收集速度较慢的 CPU 上可能会更好。使用_mm_cvtsi128_si32执行前两个元素(并使用标量掩码/移位),因此您可以从较低的延迟开始。
标签: c assembly encryption optimization