0
0

ARM NEONを使ってAESの復号をする

Posted at

暗号化手順はよく紹介されていますが、復号手順はなかなかないのでまとめました。

復号するときのポイント

基本は暗号の手順と逆のことをすればいい。ただ、ラウンドキーに対して、AESIMC(vaesimcq_u8)を行う必要がある。

コード

#define ADD(a, b)              vreinterpretq_u8_u32(vaddq_u32(vreinterpretq_u32_u8((a)), (b)))
#define KEY_EXP_256_1(k, i, r) XOR3(TSHIFT_ADD((k)[(i)]), SUBWORD(ROTWORD((k)[(i) + 1])), RCON((r)))
#define KEY_EXP_256_2(k, i)    XOR(TSHIFT_ADD((k)[(i)]), SUBWORD(NOROTWORD((k)[(i) + 1])))
#define NOROTWORD(a)           vqtbl1q_u8((a), vreinterpretq_u8_u32(vdupq_n_u32(0x0f0e0d0c)))
#define RCON(a)                vreinterpretq_u8_u32(vdupq_n_u32((a)))
#define ROTWORD(a)             vqtbl1q_u8((a), vreinterpretq_u8_u32(vdupq_n_u32(0x0c0f0e0d)))
#define SHIFT_ADD(a)           veorq_u8((a), vextq_u8(vdupq_n_u8(0x00), (a), 12))
#define SUBWORD(a)             vaeseq_u8((a), vdupq_n_u8(0x00))
#define TSHIFT_ADD(a)          SHIFT_ADD(SHIFT_ADD(SHIFT_ADD((a))))
#define UINT32x4_C(a)          vextq_u32(vdupq_n_u32((a)), vdupq_n_u32(0x00000000), 3);
#define XOR(a, b)              veorq_u8((a), (b))
#define XOR3(a, b, c)          veorq_u8((a), veorq_u8((b), (c)))


void generate_dec_roundkey256(uint8_t* key, uint8x16_t* roundkey)
{
    // ラウンドキーを作る(暗号と同じ流れ)
    roundkey[0] = vld1q_u8(key);
    roundkey[1] = vld1q_u8(key + 16);
    roundkey[2] = KEY_EXP_256_1(roundkey, 0, 0x01);
    roundkey[3] = KEY_EXP_256_2(roundkey, 1);
    roundkey[4] = KEY_EXP_256_1(roundkey, 2, 0x02);
    roundkey[5] = KEY_EXP_256_2(roundkey, 3);
    roundkey[6] = KEY_EXP_256_1(roundkey, 4, 0x04);
    roundkey[7] = KEY_EXP_256_2(roundkey, 5);
    roundkey[8] = KEY_EXP_256_1(roundkey, 6, 0x08);
    roundkey[9] = KEY_EXP_256_2(roundkey, 7);
    roundkey[10] = KEY_EXP_256_1(roundkey, 8, 0x10);
    roundkey[11] = KEY_EXP_256_2(roundkey, 9);
    roundkey[12] = KEY_EXP_256_1(roundkey, 10, 0x20);
    roundkey[13] = KEY_EXP_256_2(roundkey, 11);
    roundkey[14] = KEY_EXP_256_1(roundkey, 12, 0x40);

    // 復号の場合、以下の処理が必要
    for(int i= 1; i<14; i++)
    {
        roundkey[i] = vaesimcq_u8(roundkey[i]);
    }
}

void decrypt256(uint8_t* key, uint8_t* crypt_text, uint8_t* plan_text)
{
    uint8x16_t roundkey[15];
    generate_dec_roundkey256(key, roundkey);

    uint8x16_t state = vld1q_u8(crypt_text);

    for(int i = 14; i>1; i--)
    {
        state = vaesdq_u8( state, roundkey[i] );
        state = vaesimcq_u8( state );
    }
    state = vaesdq_u8( state, roundkey[1] );
    state = veorq_u8( state, roundkey[0] );

    vst1q_u8(output, state);
}

参考

ARM NEON使って復号できない質問とその答え。
https://stackoverflow.com/questions/75581296/aes-encryption-do-not-work-on-arm-processor
ARM NEON使った実装と復号。
https://github.com/line/aes-gcm-siv/blob/master/lib/src/arm64/aes_arm64.c
https://github.com/microsoft/SymCrypt/blob/main/lib/aes-neon.c
ラウンドキー作るときに、復号の時はvaesimcq_u8を行っているのがわかる。
https://github.com/microsoft/SymCrypt/blob/171f6973dab9b76f0dc61d966d3e977021325bc1/lib/aes-key.c#L187

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0