162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Key handling functions for PPC AES implementation 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <asm/ppc_asm.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN__ 1162306a36Sopenharmony_ci#define LOAD_KEY(d, s, off) \ 1262306a36Sopenharmony_ci lwz d,off(s); 1362306a36Sopenharmony_ci#else 1462306a36Sopenharmony_ci#define LOAD_KEY(d, s, off) \ 1562306a36Sopenharmony_ci li r0,off; \ 1662306a36Sopenharmony_ci lwbrx d,s,r0; 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define INITIALIZE_KEY \ 2062306a36Sopenharmony_ci stwu r1,-32(r1); /* create stack frame */ \ 2162306a36Sopenharmony_ci stw r14,8(r1); /* save registers */ \ 2262306a36Sopenharmony_ci stw r15,12(r1); \ 2362306a36Sopenharmony_ci stw r16,16(r1); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define FINALIZE_KEY \ 2662306a36Sopenharmony_ci lwz r14,8(r1); /* restore registers */ \ 2762306a36Sopenharmony_ci lwz r15,12(r1); \ 2862306a36Sopenharmony_ci lwz r16,16(r1); \ 2962306a36Sopenharmony_ci xor r5,r5,r5; /* clear sensitive data */ \ 3062306a36Sopenharmony_ci xor r6,r6,r6; \ 3162306a36Sopenharmony_ci xor r7,r7,r7; \ 3262306a36Sopenharmony_ci xor r8,r8,r8; \ 3362306a36Sopenharmony_ci xor r9,r9,r9; \ 3462306a36Sopenharmony_ci xor r10,r10,r10; \ 3562306a36Sopenharmony_ci xor r11,r11,r11; \ 3662306a36Sopenharmony_ci xor r12,r12,r12; \ 3762306a36Sopenharmony_ci addi r1,r1,32; /* cleanup stack */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define LS_BOX(r, t1, t2) \ 4062306a36Sopenharmony_ci lis t2,PPC_AES_4K_ENCTAB@h; \ 4162306a36Sopenharmony_ci ori t2,t2,PPC_AES_4K_ENCTAB@l; \ 4262306a36Sopenharmony_ci rlwimi t2,r,4,20,27; \ 4362306a36Sopenharmony_ci lbz t1,8(t2); \ 4462306a36Sopenharmony_ci rlwimi r,t1,0,24,31; \ 4562306a36Sopenharmony_ci rlwimi t2,r,28,20,27; \ 4662306a36Sopenharmony_ci lbz t1,8(t2); \ 4762306a36Sopenharmony_ci rlwimi r,t1,8,16,23; \ 4862306a36Sopenharmony_ci rlwimi t2,r,20,20,27; \ 4962306a36Sopenharmony_ci lbz t1,8(t2); \ 5062306a36Sopenharmony_ci rlwimi r,t1,16,8,15; \ 5162306a36Sopenharmony_ci rlwimi t2,r,12,20,27; \ 5262306a36Sopenharmony_ci lbz t1,8(t2); \ 5362306a36Sopenharmony_ci rlwimi r,t1,24,0,7; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define GF8_MUL(out, in, t1, t2) \ 5662306a36Sopenharmony_ci lis t1,0x8080; /* multiplication in GF8 */ \ 5762306a36Sopenharmony_ci ori t1,t1,0x8080; \ 5862306a36Sopenharmony_ci and t1,t1,in; \ 5962306a36Sopenharmony_ci srwi t1,t1,7; \ 6062306a36Sopenharmony_ci mulli t1,t1,0x1b; \ 6162306a36Sopenharmony_ci lis t2,0x7f7f; \ 6262306a36Sopenharmony_ci ori t2,t2,0x7f7f; \ 6362306a36Sopenharmony_ci and t2,t2,in; \ 6462306a36Sopenharmony_ci slwi t2,t2,1; \ 6562306a36Sopenharmony_ci xor out,t1,t2; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* 6862306a36Sopenharmony_ci * ppc_expand_key_128(u32 *key_enc, const u8 *key) 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Expand 128 bit key into 176 bytes encryption key. It consists of 7162306a36Sopenharmony_ci * key itself plus 10 rounds with 16 bytes each 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci_GLOBAL(ppc_expand_key_128) 7562306a36Sopenharmony_ci INITIALIZE_KEY 7662306a36Sopenharmony_ci LOAD_KEY(r5,r4,0) 7762306a36Sopenharmony_ci LOAD_KEY(r6,r4,4) 7862306a36Sopenharmony_ci LOAD_KEY(r7,r4,8) 7962306a36Sopenharmony_ci LOAD_KEY(r8,r4,12) 8062306a36Sopenharmony_ci stw r5,0(r3) /* key[0..3] = input data */ 8162306a36Sopenharmony_ci stw r6,4(r3) 8262306a36Sopenharmony_ci stw r7,8(r3) 8362306a36Sopenharmony_ci stw r8,12(r3) 8462306a36Sopenharmony_ci li r16,10 /* 10 expansion rounds */ 8562306a36Sopenharmony_ci lis r0,0x0100 /* RCO(1) */ 8662306a36Sopenharmony_cippc_expand_128_loop: 8762306a36Sopenharmony_ci addi r3,r3,16 8862306a36Sopenharmony_ci mr r14,r8 /* apply LS_BOX to 4th temp */ 8962306a36Sopenharmony_ci rotlwi r14,r14,8 9062306a36Sopenharmony_ci LS_BOX(r14, r15, r4) 9162306a36Sopenharmony_ci xor r14,r14,r0 9262306a36Sopenharmony_ci xor r5,r5,r14 /* xor next 4 keys */ 9362306a36Sopenharmony_ci xor r6,r6,r5 9462306a36Sopenharmony_ci xor r7,r7,r6 9562306a36Sopenharmony_ci xor r8,r8,r7 9662306a36Sopenharmony_ci stw r5,0(r3) /* store next 4 keys */ 9762306a36Sopenharmony_ci stw r6,4(r3) 9862306a36Sopenharmony_ci stw r7,8(r3) 9962306a36Sopenharmony_ci stw r8,12(r3) 10062306a36Sopenharmony_ci GF8_MUL(r0, r0, r4, r14) /* multiply RCO by 2 in GF */ 10162306a36Sopenharmony_ci subi r16,r16,1 10262306a36Sopenharmony_ci cmpwi r16,0 10362306a36Sopenharmony_ci bt eq,ppc_expand_128_end 10462306a36Sopenharmony_ci b ppc_expand_128_loop 10562306a36Sopenharmony_cippc_expand_128_end: 10662306a36Sopenharmony_ci FINALIZE_KEY 10762306a36Sopenharmony_ci blr 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* 11062306a36Sopenharmony_ci * ppc_expand_key_192(u32 *key_enc, const u8 *key) 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * Expand 192 bit key into 208 bytes encryption key. It consists of key 11362306a36Sopenharmony_ci * itself plus 12 rounds with 16 bytes each 11462306a36Sopenharmony_ci * 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci_GLOBAL(ppc_expand_key_192) 11762306a36Sopenharmony_ci INITIALIZE_KEY 11862306a36Sopenharmony_ci LOAD_KEY(r5,r4,0) 11962306a36Sopenharmony_ci LOAD_KEY(r6,r4,4) 12062306a36Sopenharmony_ci LOAD_KEY(r7,r4,8) 12162306a36Sopenharmony_ci LOAD_KEY(r8,r4,12) 12262306a36Sopenharmony_ci LOAD_KEY(r9,r4,16) 12362306a36Sopenharmony_ci LOAD_KEY(r10,r4,20) 12462306a36Sopenharmony_ci stw r5,0(r3) 12562306a36Sopenharmony_ci stw r6,4(r3) 12662306a36Sopenharmony_ci stw r7,8(r3) 12762306a36Sopenharmony_ci stw r8,12(r3) 12862306a36Sopenharmony_ci stw r9,16(r3) 12962306a36Sopenharmony_ci stw r10,20(r3) 13062306a36Sopenharmony_ci li r16,8 /* 8 expansion rounds */ 13162306a36Sopenharmony_ci lis r0,0x0100 /* RCO(1) */ 13262306a36Sopenharmony_cippc_expand_192_loop: 13362306a36Sopenharmony_ci addi r3,r3,24 13462306a36Sopenharmony_ci mr r14,r10 /* apply LS_BOX to 6th temp */ 13562306a36Sopenharmony_ci rotlwi r14,r14,8 13662306a36Sopenharmony_ci LS_BOX(r14, r15, r4) 13762306a36Sopenharmony_ci xor r14,r14,r0 13862306a36Sopenharmony_ci xor r5,r5,r14 /* xor next 6 keys */ 13962306a36Sopenharmony_ci xor r6,r6,r5 14062306a36Sopenharmony_ci xor r7,r7,r6 14162306a36Sopenharmony_ci xor r8,r8,r7 14262306a36Sopenharmony_ci xor r9,r9,r8 14362306a36Sopenharmony_ci xor r10,r10,r9 14462306a36Sopenharmony_ci stw r5,0(r3) 14562306a36Sopenharmony_ci stw r6,4(r3) 14662306a36Sopenharmony_ci stw r7,8(r3) 14762306a36Sopenharmony_ci stw r8,12(r3) 14862306a36Sopenharmony_ci subi r16,r16,1 14962306a36Sopenharmony_ci cmpwi r16,0 /* last round early kick out */ 15062306a36Sopenharmony_ci bt eq,ppc_expand_192_end 15162306a36Sopenharmony_ci stw r9,16(r3) 15262306a36Sopenharmony_ci stw r10,20(r3) 15362306a36Sopenharmony_ci GF8_MUL(r0, r0, r4, r14) /* multiply RCO GF8 */ 15462306a36Sopenharmony_ci b ppc_expand_192_loop 15562306a36Sopenharmony_cippc_expand_192_end: 15662306a36Sopenharmony_ci FINALIZE_KEY 15762306a36Sopenharmony_ci blr 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* 16062306a36Sopenharmony_ci * ppc_expand_key_256(u32 *key_enc, const u8 *key) 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * Expand 256 bit key into 240 bytes encryption key. It consists of key 16362306a36Sopenharmony_ci * itself plus 14 rounds with 16 bytes each 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci */ 16662306a36Sopenharmony_ci_GLOBAL(ppc_expand_key_256) 16762306a36Sopenharmony_ci INITIALIZE_KEY 16862306a36Sopenharmony_ci LOAD_KEY(r5,r4,0) 16962306a36Sopenharmony_ci LOAD_KEY(r6,r4,4) 17062306a36Sopenharmony_ci LOAD_KEY(r7,r4,8) 17162306a36Sopenharmony_ci LOAD_KEY(r8,r4,12) 17262306a36Sopenharmony_ci LOAD_KEY(r9,r4,16) 17362306a36Sopenharmony_ci LOAD_KEY(r10,r4,20) 17462306a36Sopenharmony_ci LOAD_KEY(r11,r4,24) 17562306a36Sopenharmony_ci LOAD_KEY(r12,r4,28) 17662306a36Sopenharmony_ci stw r5,0(r3) 17762306a36Sopenharmony_ci stw r6,4(r3) 17862306a36Sopenharmony_ci stw r7,8(r3) 17962306a36Sopenharmony_ci stw r8,12(r3) 18062306a36Sopenharmony_ci stw r9,16(r3) 18162306a36Sopenharmony_ci stw r10,20(r3) 18262306a36Sopenharmony_ci stw r11,24(r3) 18362306a36Sopenharmony_ci stw r12,28(r3) 18462306a36Sopenharmony_ci li r16,7 /* 7 expansion rounds */ 18562306a36Sopenharmony_ci lis r0,0x0100 /* RCO(1) */ 18662306a36Sopenharmony_cippc_expand_256_loop: 18762306a36Sopenharmony_ci addi r3,r3,32 18862306a36Sopenharmony_ci mr r14,r12 /* apply LS_BOX to 8th temp */ 18962306a36Sopenharmony_ci rotlwi r14,r14,8 19062306a36Sopenharmony_ci LS_BOX(r14, r15, r4) 19162306a36Sopenharmony_ci xor r14,r14,r0 19262306a36Sopenharmony_ci xor r5,r5,r14 /* xor 4 keys */ 19362306a36Sopenharmony_ci xor r6,r6,r5 19462306a36Sopenharmony_ci xor r7,r7,r6 19562306a36Sopenharmony_ci xor r8,r8,r7 19662306a36Sopenharmony_ci mr r14,r8 19762306a36Sopenharmony_ci LS_BOX(r14, r15, r4) /* apply LS_BOX to 4th temp */ 19862306a36Sopenharmony_ci xor r9,r9,r14 /* xor 4 keys */ 19962306a36Sopenharmony_ci xor r10,r10,r9 20062306a36Sopenharmony_ci xor r11,r11,r10 20162306a36Sopenharmony_ci xor r12,r12,r11 20262306a36Sopenharmony_ci stw r5,0(r3) 20362306a36Sopenharmony_ci stw r6,4(r3) 20462306a36Sopenharmony_ci stw r7,8(r3) 20562306a36Sopenharmony_ci stw r8,12(r3) 20662306a36Sopenharmony_ci subi r16,r16,1 20762306a36Sopenharmony_ci cmpwi r16,0 /* last round early kick out */ 20862306a36Sopenharmony_ci bt eq,ppc_expand_256_end 20962306a36Sopenharmony_ci stw r9,16(r3) 21062306a36Sopenharmony_ci stw r10,20(r3) 21162306a36Sopenharmony_ci stw r11,24(r3) 21262306a36Sopenharmony_ci stw r12,28(r3) 21362306a36Sopenharmony_ci GF8_MUL(r0, r0, r4, r14) 21462306a36Sopenharmony_ci b ppc_expand_256_loop 21562306a36Sopenharmony_cippc_expand_256_end: 21662306a36Sopenharmony_ci FINALIZE_KEY 21762306a36Sopenharmony_ci blr 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* 22062306a36Sopenharmony_ci * ppc_generate_decrypt_key: derive decryption key from encryption key 22162306a36Sopenharmony_ci * number of bytes to handle are calculated from length of key (16/24/32) 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci_GLOBAL(ppc_generate_decrypt_key) 22562306a36Sopenharmony_ci addi r6,r5,24 22662306a36Sopenharmony_ci slwi r6,r6,2 22762306a36Sopenharmony_ci lwzx r7,r4,r6 /* first/last 4 words are same */ 22862306a36Sopenharmony_ci stw r7,0(r3) 22962306a36Sopenharmony_ci lwz r7,0(r4) 23062306a36Sopenharmony_ci stwx r7,r3,r6 23162306a36Sopenharmony_ci addi r6,r6,4 23262306a36Sopenharmony_ci lwzx r7,r4,r6 23362306a36Sopenharmony_ci stw r7,4(r3) 23462306a36Sopenharmony_ci lwz r7,4(r4) 23562306a36Sopenharmony_ci stwx r7,r3,r6 23662306a36Sopenharmony_ci addi r6,r6,4 23762306a36Sopenharmony_ci lwzx r7,r4,r6 23862306a36Sopenharmony_ci stw r7,8(r3) 23962306a36Sopenharmony_ci lwz r7,8(r4) 24062306a36Sopenharmony_ci stwx r7,r3,r6 24162306a36Sopenharmony_ci addi r6,r6,4 24262306a36Sopenharmony_ci lwzx r7,r4,r6 24362306a36Sopenharmony_ci stw r7,12(r3) 24462306a36Sopenharmony_ci lwz r7,12(r4) 24562306a36Sopenharmony_ci stwx r7,r3,r6 24662306a36Sopenharmony_ci addi r3,r3,16 24762306a36Sopenharmony_ci add r4,r4,r6 24862306a36Sopenharmony_ci subi r4,r4,28 24962306a36Sopenharmony_ci addi r5,r5,20 25062306a36Sopenharmony_ci srwi r5,r5,2 25162306a36Sopenharmony_cippc_generate_decrypt_block: 25262306a36Sopenharmony_ci li r6,4 25362306a36Sopenharmony_ci mtctr r6 25462306a36Sopenharmony_cippc_generate_decrypt_word: 25562306a36Sopenharmony_ci lwz r6,0(r4) 25662306a36Sopenharmony_ci GF8_MUL(r7, r6, r0, r7) 25762306a36Sopenharmony_ci GF8_MUL(r8, r7, r0, r8) 25862306a36Sopenharmony_ci GF8_MUL(r9, r8, r0, r9) 25962306a36Sopenharmony_ci xor r10,r9,r6 26062306a36Sopenharmony_ci xor r11,r7,r8 26162306a36Sopenharmony_ci xor r11,r11,r9 26262306a36Sopenharmony_ci xor r12,r7,r10 26362306a36Sopenharmony_ci rotrwi r12,r12,24 26462306a36Sopenharmony_ci xor r11,r11,r12 26562306a36Sopenharmony_ci xor r12,r8,r10 26662306a36Sopenharmony_ci rotrwi r12,r12,16 26762306a36Sopenharmony_ci xor r11,r11,r12 26862306a36Sopenharmony_ci rotrwi r12,r10,8 26962306a36Sopenharmony_ci xor r11,r11,r12 27062306a36Sopenharmony_ci stw r11,0(r3) 27162306a36Sopenharmony_ci addi r3,r3,4 27262306a36Sopenharmony_ci addi r4,r4,4 27362306a36Sopenharmony_ci bdnz ppc_generate_decrypt_word 27462306a36Sopenharmony_ci subi r4,r4,32 27562306a36Sopenharmony_ci subi r5,r5,1 27662306a36Sopenharmony_ci cmpwi r5,0 27762306a36Sopenharmony_ci bt gt,ppc_generate_decrypt_block 27862306a36Sopenharmony_ci blr 279