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