qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

crypto_helper.c (9335B)


      1 /*
      2  * RISC-V Crypto Emulation Helpers for QEMU.
      3  *
      4  * Copyright (c) 2021 Ruibo Lu, luruibo2000@163.com
      5  * Copyright (c) 2021 Zewen Ye, lustrew@foxmail.com
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms and conditions of the GNU General Public License,
      9  * version 2 or later, as published by the Free Software Foundation.
     10  *
     11  * This program is distributed in the hope it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     14  * more details.
     15  *
     16  * You should have received a copy of the GNU General Public License along with
     17  * this program.  If not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "qemu/osdep.h"
     21 #include "cpu.h"
     22 #include "exec/exec-all.h"
     23 #include "exec/helper-proto.h"
     24 #include "crypto/aes.h"
     25 #include "crypto/sm4.h"
     26 
     27 #define AES_XTIME(a) \
     28     ((a << 1) ^ ((a & 0x80) ? 0x1b : 0))
     29 
     30 #define AES_GFMUL(a, b) (( \
     31     (((b) & 0x1) ? (a) : 0) ^ \
     32     (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \
     33     (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \
     34     (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF)
     35 
     36 static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd)
     37 {
     38     uint32_t u;
     39 
     40     if (fwd) {
     41         u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) |
     42             (AES_GFMUL(x, 2) << 0);
     43     } else {
     44         u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) |
     45             (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0);
     46     }
     47     return u;
     48 }
     49 
     50 #define sext32_xlen(x) (target_ulong)(int32_t)(x)
     51 
     52 static inline target_ulong aes32_operation(target_ulong shamt,
     53                                            target_ulong rs1, target_ulong rs2,
     54                                            bool enc, bool mix)
     55 {
     56     uint8_t si = rs2 >> shamt;
     57     uint8_t so;
     58     uint32_t mixed;
     59     target_ulong res;
     60 
     61     if (enc) {
     62         so = AES_sbox[si];
     63         if (mix) {
     64             mixed = aes_mixcolumn_byte(so, true);
     65         } else {
     66             mixed = so;
     67         }
     68     } else {
     69         so = AES_isbox[si];
     70         if (mix) {
     71             mixed = aes_mixcolumn_byte(so, false);
     72         } else {
     73             mixed = so;
     74         }
     75     }
     76     mixed = rol32(mixed, shamt);
     77     res = rs1 ^ mixed;
     78 
     79     return sext32_xlen(res);
     80 }
     81 
     82 target_ulong HELPER(aes32esmi)(target_ulong rs1, target_ulong rs2,
     83                                target_ulong shamt)
     84 {
     85     return aes32_operation(shamt, rs1, rs2, true, true);
     86 }
     87 
     88 target_ulong HELPER(aes32esi)(target_ulong rs1, target_ulong rs2,
     89                               target_ulong shamt)
     90 {
     91     return aes32_operation(shamt, rs1, rs2, true, false);
     92 }
     93 
     94 target_ulong HELPER(aes32dsmi)(target_ulong rs1, target_ulong rs2,
     95                                target_ulong shamt)
     96 {
     97     return aes32_operation(shamt, rs1, rs2, false, true);
     98 }
     99 
    100 target_ulong HELPER(aes32dsi)(target_ulong rs1, target_ulong rs2,
    101                               target_ulong shamt)
    102 {
    103     return aes32_operation(shamt, rs1, rs2, false, false);
    104 }
    105 
    106 #define BY(X, I) ((X >> (8 * I)) & 0xFF)
    107 
    108 #define AES_SHIFROWS_LO(RS1, RS2) ( \
    109     (((RS1 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \
    110     (((RS2 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \
    111     (((RS2 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \
    112     (((RS1 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0))
    113 
    114 #define AES_INVSHIFROWS_LO(RS1, RS2) ( \
    115     (((RS2 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \
    116     (((RS1 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \
    117     (((RS1 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \
    118     (((RS2 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0))
    119 
    120 #define AES_MIXBYTE(COL, B0, B1, B2, B3) ( \
    121     BY(COL, B3) ^ BY(COL, B2) ^ AES_GFMUL(BY(COL, B1), 3) ^ \
    122     AES_GFMUL(BY(COL, B0), 2))
    123 
    124 #define AES_MIXCOLUMN(COL) ( \
    125     AES_MIXBYTE(COL, 3, 0, 1, 2) << 24 | \
    126     AES_MIXBYTE(COL, 2, 3, 0, 1) << 16 | \
    127     AES_MIXBYTE(COL, 1, 2, 3, 0) << 8 | AES_MIXBYTE(COL, 0, 1, 2, 3) << 0)
    128 
    129 #define AES_INVMIXBYTE(COL, B0, B1, B2, B3) ( \
    130     AES_GFMUL(BY(COL, B3), 0x9) ^ AES_GFMUL(BY(COL, B2), 0xd) ^ \
    131     AES_GFMUL(BY(COL, B1), 0xb) ^ AES_GFMUL(BY(COL, B0), 0xe))
    132 
    133 #define AES_INVMIXCOLUMN(COL) ( \
    134     AES_INVMIXBYTE(COL, 3, 0, 1, 2) << 24 | \
    135     AES_INVMIXBYTE(COL, 2, 3, 0, 1) << 16 | \
    136     AES_INVMIXBYTE(COL, 1, 2, 3, 0) << 8 | \
    137     AES_INVMIXBYTE(COL, 0, 1, 2, 3) << 0)
    138 
    139 static inline target_ulong aes64_operation(target_ulong rs1, target_ulong rs2,
    140                                            bool enc, bool mix)
    141 {
    142     uint64_t RS1 = rs1;
    143     uint64_t RS2 = rs2;
    144     uint64_t result;
    145     uint64_t temp;
    146     uint32_t col_0;
    147     uint32_t col_1;
    148 
    149     if (enc) {
    150         temp = AES_SHIFROWS_LO(RS1, RS2);
    151         temp = (((uint64_t)AES_sbox[(temp >> 0) & 0xFF] << 0) |
    152                 ((uint64_t)AES_sbox[(temp >> 8) & 0xFF] << 8) |
    153                 ((uint64_t)AES_sbox[(temp >> 16) & 0xFF] << 16) |
    154                 ((uint64_t)AES_sbox[(temp >> 24) & 0xFF] << 24) |
    155                 ((uint64_t)AES_sbox[(temp >> 32) & 0xFF] << 32) |
    156                 ((uint64_t)AES_sbox[(temp >> 40) & 0xFF] << 40) |
    157                 ((uint64_t)AES_sbox[(temp >> 48) & 0xFF] << 48) |
    158                 ((uint64_t)AES_sbox[(temp >> 56) & 0xFF] << 56));
    159         if (mix) {
    160             col_0 = temp & 0xFFFFFFFF;
    161             col_1 = temp >> 32;
    162 
    163             col_0 = AES_MIXCOLUMN(col_0);
    164             col_1 = AES_MIXCOLUMN(col_1);
    165 
    166             result = ((uint64_t)col_1 << 32) | col_0;
    167         } else {
    168             result = temp;
    169         }
    170     } else {
    171         temp = AES_INVSHIFROWS_LO(RS1, RS2);
    172         temp = (((uint64_t)AES_isbox[(temp >> 0) & 0xFF] << 0) |
    173                 ((uint64_t)AES_isbox[(temp >> 8) & 0xFF] << 8) |
    174                 ((uint64_t)AES_isbox[(temp >> 16) & 0xFF] << 16) |
    175                 ((uint64_t)AES_isbox[(temp >> 24) & 0xFF] << 24) |
    176                 ((uint64_t)AES_isbox[(temp >> 32) & 0xFF] << 32) |
    177                 ((uint64_t)AES_isbox[(temp >> 40) & 0xFF] << 40) |
    178                 ((uint64_t)AES_isbox[(temp >> 48) & 0xFF] << 48) |
    179                 ((uint64_t)AES_isbox[(temp >> 56) & 0xFF] << 56));
    180         if (mix) {
    181             col_0 = temp & 0xFFFFFFFF;
    182             col_1 = temp >> 32;
    183 
    184             col_0 = AES_INVMIXCOLUMN(col_0);
    185             col_1 = AES_INVMIXCOLUMN(col_1);
    186 
    187             result = ((uint64_t)col_1 << 32) | col_0;
    188         } else {
    189             result = temp;
    190         }
    191     }
    192 
    193     return result;
    194 }
    195 
    196 target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2)
    197 {
    198     return aes64_operation(rs1, rs2, true, true);
    199 }
    200 
    201 target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2)
    202 {
    203     return aes64_operation(rs1, rs2, true, false);
    204 }
    205 
    206 target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2)
    207 {
    208     return aes64_operation(rs1, rs2, false, false);
    209 }
    210 
    211 target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2)
    212 {
    213     return aes64_operation(rs1, rs2, false, true);
    214 }
    215 
    216 target_ulong HELPER(aes64ks2)(target_ulong rs1, target_ulong rs2)
    217 {
    218     uint64_t RS1 = rs1;
    219     uint64_t RS2 = rs2;
    220     uint32_t rs1_hi = RS1 >> 32;
    221     uint32_t rs2_lo = RS2;
    222     uint32_t rs2_hi = RS2 >> 32;
    223 
    224     uint32_t r_lo = (rs1_hi ^ rs2_lo);
    225     uint32_t r_hi = (rs1_hi ^ rs2_lo ^ rs2_hi);
    226     target_ulong result = ((uint64_t)r_hi << 32) | r_lo;
    227 
    228     return result;
    229 }
    230 
    231 target_ulong HELPER(aes64ks1i)(target_ulong rs1, target_ulong rnum)
    232 {
    233     uint64_t RS1 = rs1;
    234     static const uint8_t round_consts[10] = {
    235         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
    236     };
    237 
    238     uint8_t enc_rnum = rnum;
    239     uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF;
    240     uint8_t rcon_ = 0;
    241     target_ulong result;
    242 
    243     if (enc_rnum != 0xA) {
    244         temp = ror32(temp, 8); /* Rotate right by 8 */
    245         rcon_ = round_consts[enc_rnum];
    246     }
    247 
    248     temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) |
    249            ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) |
    250            ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) |
    251            ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0);
    252 
    253     temp ^= rcon_;
    254 
    255     result = ((uint64_t)temp << 32) | temp;
    256 
    257     return result;
    258 }
    259 
    260 target_ulong HELPER(aes64im)(target_ulong rs1)
    261 {
    262     uint64_t RS1 = rs1;
    263     uint32_t col_0 = RS1 & 0xFFFFFFFF;
    264     uint32_t col_1 = RS1 >> 32;
    265     target_ulong result;
    266 
    267     col_0 = AES_INVMIXCOLUMN(col_0);
    268     col_1 = AES_INVMIXCOLUMN(col_1);
    269 
    270     result = ((uint64_t)col_1 << 32) | col_0;
    271 
    272     return result;
    273 }
    274 
    275 target_ulong HELPER(sm4ed)(target_ulong rs1, target_ulong rs2,
    276                            target_ulong shamt)
    277 {
    278     uint32_t sb_in = (uint8_t)(rs2 >> shamt);
    279     uint32_t sb_out = (uint32_t)sm4_sbox[sb_in];
    280 
    281     uint32_t x = sb_out ^ (sb_out << 8) ^ (sb_out << 2) ^ (sb_out << 18) ^
    282                  ((sb_out & 0x3f) << 26) ^ ((sb_out & 0xC0) << 10);
    283 
    284     uint32_t rotl = rol32(x, shamt);
    285 
    286     return sext32_xlen(rotl ^ (uint32_t)rs1);
    287 }
    288 
    289 target_ulong HELPER(sm4ks)(target_ulong rs1, target_ulong rs2,
    290                            target_ulong shamt)
    291 {
    292     uint32_t sb_in = (uint8_t)(rs2 >> shamt);
    293     uint32_t sb_out = sm4_sbox[sb_in];
    294 
    295     uint32_t x = sb_out ^ ((sb_out & 0x07) << 29) ^ ((sb_out & 0xFE) << 7) ^
    296                  ((sb_out & 0x01) << 23) ^ ((sb_out & 0xF8) << 13);
    297 
    298     uint32_t rotl = rol32(x, shamt);
    299 
    300     return sext32_xlen(rotl ^ (uint32_t)rs1);
    301 }
    302 #undef sext32_xlen