root/lib/crypto/powerpc/aes-spe-keys.S
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Key handling functions for PPC AES implementation
 *
 * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
 */

#include <asm/ppc_asm.h>

#ifdef __BIG_ENDIAN__
#define LOAD_KEY(d, s, off) \
        lwz             d,off(s);
#else
#define LOAD_KEY(d, s, off) \
        li              r0,off; \
        lwbrx           d,s,r0;
#endif

#define INITIALIZE_KEY \
        stwu            r1,-32(r1);     /* create stack frame           */ \
        stw             r14,8(r1);      /* save registers               */ \
        stw             r15,12(r1);                                        \
        stw             r16,16(r1);

#define FINALIZE_KEY \
        lwz             r14,8(r1);      /* restore registers            */ \
        lwz             r15,12(r1);                                        \
        lwz             r16,16(r1);                                        \
        xor             r5,r5,r5;       /* clear sensitive data         */ \
        xor             r6,r6,r6;                                          \
        xor             r7,r7,r7;                                          \
        xor             r8,r8,r8;                                          \
        xor             r9,r9,r9;                                          \
        xor             r10,r10,r10;                                       \
        xor             r11,r11,r11;                                       \
        xor             r12,r12,r12;                                       \
        addi            r1,r1,32;       /* cleanup stack                */

#define LS_BOX(r, t1, t2) \
        lis             t2,PPC_AES_4K_ENCTAB@h;                            \
        ori             t2,t2,PPC_AES_4K_ENCTAB@l;                         \
        rlwimi          t2,r,4,20,27;                                      \
        lbz             t1,8(t2);                                          \
        rlwimi          r,t1,0,24,31;                                      \
        rlwimi          t2,r,28,20,27;                                     \
        lbz             t1,8(t2);                                          \
        rlwimi          r,t1,8,16,23;                                      \
        rlwimi          t2,r,20,20,27;                                     \
        lbz             t1,8(t2);                                          \
        rlwimi          r,t1,16,8,15;                                      \
        rlwimi          t2,r,12,20,27;                                     \
        lbz             t1,8(t2);                                          \
        rlwimi          r,t1,24,0,7;

#define GF8_MUL(out, in, t1, t2) \
        lis t1,0x8080;                  /* multiplication in GF8        */ \
        ori t1,t1,0x8080;                                                  \
        and t1,t1,in;                                                      \
        srwi t1,t1,7;                                                      \
        mulli t1,t1,0x1b;                                                  \
        lis t2,0x7f7f;                                                     \
        ori t2,t2,0x7f7f;                                                  \
        and t2,t2,in;                                                      \
        slwi t2,t2,1;                                                      \
        xor out,t1,t2;

/*
 * ppc_expand_key_128(u32 *key_enc, const u8 *key)
 *
 * Expand 128 bit key into 176 bytes encryption key. It consists of
 * key itself plus 10 rounds with 16 bytes each
 *
 */
_GLOBAL(ppc_expand_key_128)
        INITIALIZE_KEY
        LOAD_KEY(r5,r4,0)
        LOAD_KEY(r6,r4,4)
        LOAD_KEY(r7,r4,8)
        LOAD_KEY(r8,r4,12)
        stw             r5,0(r3)        /* key[0..3] = input data       */
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        li              r16,10          /* 10 expansion rounds          */
        lis             r0,0x0100       /* RCO(1)                       */
ppc_expand_128_loop:
        addi            r3,r3,16
        mr              r14,r8          /* apply LS_BOX to 4th temp     */
        rotlwi          r14,r14,8
        LS_BOX(r14, r15, r4)
        xor             r14,r14,r0
        xor             r5,r5,r14       /* xor next 4 keys              */
        xor             r6,r6,r5
        xor             r7,r7,r6
        xor             r8,r8,r7
        stw             r5,0(r3)        /* store next 4 keys            */
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        GF8_MUL(r0, r0, r4, r14)        /* multiply RCO by 2 in GF      */
        subi            r16,r16,1
        cmpwi           r16,0
        bt              eq,ppc_expand_128_end
        b               ppc_expand_128_loop
ppc_expand_128_end:
        FINALIZE_KEY
        blr

/*
 * ppc_expand_key_192(u32 *key_enc, const u8 *key)
 *
 * Expand 192 bit key into 208 bytes encryption key. It consists of key
 * itself plus 12 rounds with 16 bytes each
 *
 */
_GLOBAL(ppc_expand_key_192)
        INITIALIZE_KEY
        LOAD_KEY(r5,r4,0)
        LOAD_KEY(r6,r4,4)
        LOAD_KEY(r7,r4,8)
        LOAD_KEY(r8,r4,12)
        LOAD_KEY(r9,r4,16)
        LOAD_KEY(r10,r4,20)
        stw             r5,0(r3)
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        stw             r9,16(r3)
        stw             r10,20(r3)
        li              r16,8           /* 8 expansion rounds           */
        lis             r0,0x0100       /* RCO(1)                       */
ppc_expand_192_loop:
        addi            r3,r3,24
        mr              r14,r10         /* apply LS_BOX to 6th temp     */
        rotlwi          r14,r14,8
        LS_BOX(r14, r15, r4)
        xor             r14,r14,r0
        xor             r5,r5,r14       /* xor next 6 keys              */
        xor             r6,r6,r5
        xor             r7,r7,r6
        xor             r8,r8,r7
        xor             r9,r9,r8
        xor             r10,r10,r9
        stw             r5,0(r3)
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        subi            r16,r16,1
        cmpwi           r16,0           /* last round early kick out    */
        bt              eq,ppc_expand_192_end
        stw             r9,16(r3)
        stw             r10,20(r3)
        GF8_MUL(r0, r0, r4, r14)        /* multiply RCO GF8             */
        b               ppc_expand_192_loop
ppc_expand_192_end:
        FINALIZE_KEY
        blr

/*
 * ppc_expand_key_256(u32 *key_enc, const u8 *key)
 *
 * Expand 256 bit key into 240 bytes encryption key. It consists of key
 * itself plus 14 rounds with 16 bytes each
 *
 */
_GLOBAL(ppc_expand_key_256)
        INITIALIZE_KEY
        LOAD_KEY(r5,r4,0)
        LOAD_KEY(r6,r4,4)
        LOAD_KEY(r7,r4,8)
        LOAD_KEY(r8,r4,12)
        LOAD_KEY(r9,r4,16)
        LOAD_KEY(r10,r4,20)
        LOAD_KEY(r11,r4,24)
        LOAD_KEY(r12,r4,28)
        stw             r5,0(r3)
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        stw             r9,16(r3)
        stw             r10,20(r3)
        stw             r11,24(r3)
        stw             r12,28(r3)
        li              r16,7           /* 7 expansion rounds           */
        lis             r0,0x0100       /* RCO(1)                       */
ppc_expand_256_loop:
        addi            r3,r3,32
        mr              r14,r12         /* apply LS_BOX to 8th temp     */
        rotlwi          r14,r14,8
        LS_BOX(r14, r15, r4)
        xor             r14,r14,r0
        xor             r5,r5,r14       /* xor 4 keys                   */
        xor             r6,r6,r5
        xor             r7,r7,r6
        xor             r8,r8,r7
        mr              r14,r8
        LS_BOX(r14, r15, r4)            /* apply LS_BOX to 4th temp     */
        xor             r9,r9,r14       /* xor 4 keys                   */
        xor             r10,r10,r9
        xor             r11,r11,r10
        xor             r12,r12,r11
        stw             r5,0(r3)
        stw             r6,4(r3)
        stw             r7,8(r3)
        stw             r8,12(r3)
        subi            r16,r16,1
        cmpwi           r16,0           /* last round early kick out    */
        bt              eq,ppc_expand_256_end
        stw             r9,16(r3)
        stw             r10,20(r3)
        stw             r11,24(r3)
        stw             r12,28(r3)
        GF8_MUL(r0, r0, r4, r14)
        b               ppc_expand_256_loop
ppc_expand_256_end:
        FINALIZE_KEY
        blr

/*
 * ppc_generate_decrypt_key: derive decryption key from encryption key
 * number of bytes to handle are calculated from length of key (16/24/32)
 *
 */
_GLOBAL(ppc_generate_decrypt_key)
        addi            r6,r5,24
        slwi            r6,r6,2
        lwzx            r7,r4,r6        /* first/last 4 words are same  */
        stw             r7,0(r3)
        lwz             r7,0(r4)
        stwx            r7,r3,r6
        addi            r6,r6,4
        lwzx            r7,r4,r6
        stw             r7,4(r3)
        lwz             r7,4(r4)
        stwx            r7,r3,r6
        addi            r6,r6,4
        lwzx            r7,r4,r6
        stw             r7,8(r3)
        lwz             r7,8(r4)
        stwx            r7,r3,r6
        addi            r6,r6,4
        lwzx            r7,r4,r6
        stw             r7,12(r3)
        lwz             r7,12(r4)
        stwx            r7,r3,r6
        addi            r3,r3,16
        add             r4,r4,r6
        subi            r4,r4,28
        addi            r5,r5,20
        srwi            r5,r5,2
ppc_generate_decrypt_block:
        li      r6,4
        mtctr   r6
ppc_generate_decrypt_word:
        lwz             r6,0(r4)
        GF8_MUL(r7, r6, r0, r7)
        GF8_MUL(r8, r7, r0, r8)
        GF8_MUL(r9, r8, r0, r9)
        xor             r10,r9,r6
        xor             r11,r7,r8
        xor             r11,r11,r9
        xor             r12,r7,r10
        rotrwi          r12,r12,24
        xor             r11,r11,r12
        xor             r12,r8,r10
        rotrwi          r12,r12,16
        xor             r11,r11,r12
        rotrwi          r12,r10,8
        xor             r11,r11,r12
        stw             r11,0(r3)
        addi            r3,r3,4
        addi            r4,r4,4
        bdnz            ppc_generate_decrypt_word
        subi            r4,r4,32
        subi            r5,r5,1
        cmpwi           r5,0
        bt              gt,ppc_generate_decrypt_block
        blr