advances in serpent asm implementation

This commit is contained in:
bg 2008-08-10 14:04:06 +00:00
parent f0ca870318
commit c1553054f9
9 changed files with 622 additions and 19 deletions

View File

@ -16,10 +16,10 @@ TESTLOG_DIR = testlog/
TESTPREFIX = nessie- TESTPREFIX = nessie-
CC = avr-gcc CC = avr-gcc
override CFLAGS = -MMD -MF$(DEP_DIR)$(patsubst %.c,%.d,$(patsubst $(TESTSRC_DIR)%,%,$<)) -I. -pedantic -std=c99 -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) override CFLAGS = -MMD -MF$(DEP_DIR)$(patsubst %.c,%.d,$(patsubst $(TESTSRC_DIR)%,%,$<)) -I. -gdwarf-2 -pedantic -std=c99 -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS = -Wl,-Map, override LDFLAGS = -gdwarf-2 -Wl,-Map,
override ASFLAGS = -mmcu=$(MCU_TARGET) override ASFLAGS = -mmcu=$(MCU_TARGET) -gdwarf-2
SIZESTAT_FILE = sizestats.txt SIZESTAT_FILE = sizestats.txt

View File

@ -20,9 +20,9 @@
/* /*
* File: memxor.S * File: memxor.S
* Author: Daniel Otte * Author: Daniel Otte
* Date: 2006-07-06 * Date: 2008-08-07
* License: GPLv3 or later * License: GPLv3 or later
* Description: Implementation of the ARCFOUR (RC4 compatible) stream cipher algorithm. * Description: memxor, XORing one block into another
* *
*/ */

View File

@ -0,0 +1,13 @@
# Makefile for serpent
ALGO_NAME := SERPENT_ASM_FAST
# comment out the following line for removement of serpent from the build process
BLOCK_CIPHERS += $(ALGO_NAME)
$(ALGO_NAME)_OBJ := serpent.o serpent-sboxes-fast.o memxor.o
$(ALGO_NAME)_TEST_BIN := main-serpent-test.o debug.o uart.o serial-tools.o \
nessie_bc_test.o nessie_common.o cli.o performance_test.o
$(ALGO_NAME)_NESSIE_TEST := "nessie"
$(ALGO_NAME)_PEROFRMANCE_TEST := "performance"

View File

@ -0,0 +1,13 @@
# Makefile for serpent
ALGO_NAME := SERPENT_ASM_SMALL
# comment out the following line for removement of serpent from the build process
BLOCK_CIPHERS += $(ALGO_NAME)
$(ALGO_NAME)_OBJ := serpent.o serpent-sboxes-small.o memxor.o
$(ALGO_NAME)_TEST_BIN := main-serpent-test.o debug.o uart.o serial-tools.o \
nessie_bc_test.o nessie_common.o cli.o performance_test.o
$(ALGO_NAME)_NESSIE_TEST := "nessie"
$(ALGO_NAME)_PEROFRMANCE_TEST := "performance"

View File

@ -1,11 +1,11 @@
# Makefile for serpent # Makefile for serpent
ALGO_NAME := SERPENT ALGO_NAME := SERPENT_C
# comment out the following line for removement of serpent from the build process # comment out the following line for removement of serpent from the build process
BLOCK_CIPHERS += $(ALGO_NAME) BLOCK_CIPHERS += $(ALGO_NAME)
$(ALGO_NAME)_OBJ := serpent.o serpent-sboxes.o memxor.o $(ALGO_NAME)_OBJ := serpent.o serpent-sboxes_c.o memxor.o
$(ALGO_NAME)_TEST_BIN := main-serpent-test.o debug.o uart.o serial-tools.o \ $(ALGO_NAME)_TEST_BIN := main-serpent-test.o debug.o uart.o serial-tools.o \
nessie_bc_test.o nessie_common.o cli.o performance_test.o nessie_bc_test.o nessie_common.o cli.o performance_test.o
$(ALGO_NAME)_NESSIE_TEST := "nessie" $(ALGO_NAME)_NESSIE_TEST := "nessie"

289
serpent-sboxes-fast.S Normal file
View File

@ -0,0 +1,289 @@
/* serpent-sboxes-fast.S */
/*
This file is part of the Crypto-avr-lib/microcrypt-lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* File: serpent-sboxes-fast.S
* Author: Daniel Otte
* Date: 2008-08-07
* License: GPLv3 or later
* Description: Implementation of the serpent sbox function.
*
*/
#include <avr/io.h>
/*******************************************************************************
* MACRO SECTION *
*******************************************************************************/
.macro push_ p1:req, p2:vararg
push \p1
.ifnb \p2
push_ \p2
.endif
.endm
.macro pop_ p1:req, p2:vararg
pop \p1
.ifnb \p2
pop_ \p2
.endif
.endm
.macro push_range from:req, to:req
push \from
.if \to-\from
push_range "(\from+1)",\to
.endif
.endm
.macro pop_range from:req, to:req
pop \to
.if \to-\from
pop_range \from,"(\to-1)"
.endif
.endm
.macro stack_alloc size:req, reg1=r30, reg2=r31
in r0, _SFR_IO_ADDR(SREG)
cli
in \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
sbiw \reg1, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
out _SFR_IO_ADDR(SREG), r0
.endm
.macro stack_free size:req, reg1=r30, reg2=r31
in r0, _SFR_IO_ADDR(SREG)
cli
in \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
adiw \reg1, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
out _SFR_IO_ADDR(SREG), r0
.endm
/*******************************************************************************
* END of MACRO SECTION *
*******************************************************************************/
serpent_sbox_fast:
.byte 0x33, 0x88, 0xFF, 0x11, 0xAA, 0x66, 0x55, 0xBB
.byte 0xEE, 0xDD, 0x44, 0x22, 0x77, 0x00, 0x99, 0xCC
.byte 0xFF, 0xCC, 0x22, 0x77, 0x99, 0x00, 0x55, 0xAA
.byte 0x11, 0xBB, 0xEE, 0x88, 0x66, 0xDD, 0x33, 0x44
.byte 0x88, 0x66, 0x77, 0x99, 0x33, 0xCC, 0xAA, 0xFF
.byte 0xDD, 0x11, 0xEE, 0x44, 0x00, 0xBB, 0x55, 0x22
.byte 0x00, 0xFF, 0xBB, 0x88, 0xCC, 0x99, 0x66, 0x33
.byte 0xDD, 0x11, 0x22, 0x44, 0xAA, 0x77, 0x55, 0xEE
.byte 0x11, 0xFF, 0x88, 0x33, 0xCC, 0x00, 0xBB, 0x66
.byte 0x22, 0x55, 0x44, 0xAA, 0x99, 0xEE, 0x77, 0xDD
.byte 0xFF, 0x55, 0x22, 0xBB, 0x44, 0xAA, 0x99, 0xCC
.byte 0x00, 0x33, 0xEE, 0x88, 0xDD, 0x66, 0x77, 0x11
.byte 0x77, 0x22, 0xCC, 0x55, 0x88, 0x44, 0x66, 0xBB
.byte 0xEE, 0x99, 0x11, 0xFF, 0xDD, 0x33, 0xAA, 0x00
.byte 0x11, 0xDD, 0xFF, 0x00, 0xEE, 0x88, 0x22, 0xBB
.byte 0x77, 0x44, 0xCC, 0xAA, 0x99, 0x33, 0x55, 0x66
serpent_sbox_inv_fast:
.byte 0xDD, 0x33, 0xBB, 0x00, 0xAA, 0x66, 0x55, 0xCC
.byte 0x11, 0xEE, 0x44, 0x77, 0xFF, 0x99, 0x88, 0x22
.byte 0x55, 0x88, 0x22, 0xEE, 0xFF, 0x66, 0xCC, 0x33
.byte 0xBB, 0x44, 0x77, 0x99, 0x11, 0xDD, 0xAA, 0x00
.byte 0xCC, 0x99, 0xFF, 0x44, 0xBB, 0xEE, 0x11, 0x22
.byte 0x00, 0x33, 0x66, 0xDD, 0x55, 0x88, 0xAA, 0x77
.byte 0x00, 0x99, 0xAA, 0x77, 0xBB, 0xEE, 0x66, 0xDD
.byte 0x33, 0x55, 0xCC, 0x22, 0x44, 0x88, 0xFF, 0x11
.byte 0x55, 0x00, 0x88, 0x33, 0xAA, 0x99, 0x77, 0xEE
.byte 0x22, 0xCC, 0xBB, 0x66, 0x44, 0xFF, 0xDD, 0x11
.byte 0x88, 0xFF, 0x22, 0x99, 0x44, 0x11, 0xDD, 0xEE
.byte 0xBB, 0x66, 0x55, 0x33, 0x77, 0xCC, 0xAA, 0x00
.byte 0xFF, 0xAA, 0x11, 0xDD, 0x55, 0x33, 0x66, 0x00
.byte 0x44, 0x99, 0xEE, 0x77, 0x22, 0xCC, 0x88, 0xBB
.byte 0x33, 0x00, 0x66, 0xDD, 0x99, 0xEE, 0xFF, 0x88
.byte 0x55, 0xCC, 0xBB, 0x77, 0xAA, 0x11, 0x44, 0x22
/*
* void ip(uint32_t *i, uint8_t *o){
*/
/*
* param i is given in r24:r25
* parma o is given in r22:r23
*/
.global serpent_ip
serpent_ip:
push_range 2, 17
movw r26, r24
ldi r24, 16
clr r31
ldi r30, 2
1:
ld r25, X+
st Z+, r25
dec r24
brne 1b
/* now the whole input is loaded in r2-r18 */
movw r26, r22
ldi r21, 4
4:
ldi r20, 8
2:
lsr r2
ror r19
lsr r6
ror 19
lsr r10
ror r19
lsr r14
ror 19
sbrc r20, 0
st X+, r19
dec r20
brne 2b
ldi r20, 15
ldi r30, 2
3:
ldd r19, Z+1
st Z+, r19
dec r20
brne 3b
dec r21
brne 4b
pop_range 2, 17
ret
/*
* void serpent_fp(uint32_t *i, uint8_t *o){
*/
/*
* param i is given in r24:r25
* parma o is given in r22:r23
*/
.global serpent_fp
serpent_fp:
movw r26, r24
movw r30, r22
ldi r18, 4
1:
ldi r19, 8
2:
sbrs r19, 0
ld r24, X+
3:
lsr r24
ror r20
lsr r24
ror r21
lsr r24
ror r22
lsr r24
ror r23
dec r19
brne 2b
st Z+, r20
std Z+3, r21
std Z+7, r22
std Z+11, r23
dec r18
brne 1b
ret
/*
* void inv_sbox128(void * w, uint8_t box)
*/
.global inv_sbox128
inv_sbox128:
andi r22, 0x07
ori r22, 0x08
rjmp sbox128x_fast
/*
* void sbox128(void * w, uint8_t box);
*/
/*
* param w is passed in r24:r25
* param box is passed in r22
*/
.global sbox128
sbox128:
andi r22, 0x07
sbox128x_fast:
stack_alloc 16
adiw r30, 1
push_ r24, r25, r22, r30, r31
movw r22, r30 /* Z points to the stack buffer */
rcall serpent_ip
pop_ r27, r26, r22
ldi r25, hi8(serpent_sbox_fast)
ldi r24, lo8(serpent_sbox_fast)
swap r22 /* r22 *= 16 */
add r24, r22
adc r25, r1
/* now we have X pointing to the buffer and (r24:r25) pointing to the SBox */
ldi r22, 16
1:
movw r30, r24
ld r18, X
mov r20, r18
andi r18, 0x0f
add r30, r18
adc r31, r1
lpm r19, Z
2:
swap r20
andi r20, 0x0f
movw r30, r24
add r30, r20
adc r31, r1
lpm r21, Z
3:
andi r19, 0x0F
andi r21, 0xF0
or r19, r21
st X+, r19
dec r22
brne 1b
pop_ r23, r22
movw r24, r26
sbiw r24, 16
rcall serpent_fp
stack_free 16
ret

286
serpent-sboxes-small.S Normal file
View File

@ -0,0 +1,286 @@
/* serpent_sboxes.S */
/*
This file is part of the Crypto-avr-lib/microcrypt-lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* File: serpent_sboxes.S
* Author: Daniel Otte
* Date: 2008-08-07
* License: GPLv3 or later
* Description: Implementation of the serpent sbox function.
*
*/
#include <avr/io.h>
/*******************************************************************************
* MACRO SECTION *
*******************************************************************************/
.macro push_ p1:req, p2:vararg
push \p1
.ifnb \p2
push_ \p2
.endif
.endm
.macro pop_ p1:req, p2:vararg
pop \p1
.ifnb \p2
pop_ \p2
.endif
.endm
.macro push_range from:req, to:req
push \from
.if \to-\from
push_range "(\from+1)",\to
.endif
.endm
.macro pop_range from:req, to:req
pop \to
.if \to-\from
pop_range \from,"(\to-1)"
.endif
.endm
.macro stack_alloc size:req, reg1=r30, reg2=r31
in r0, _SFR_IO_ADDR(SREG)
cli
in \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
sbiw \reg1, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
out _SFR_IO_ADDR(SREG), r0
.endm
.macro stack_free size:req, reg1=r30, reg2=r31
in r0, _SFR_IO_ADDR(SREG)
cli
in \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
adiw \reg1, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
out _SFR_IO_ADDR(SREG), r0
.endm
/*******************************************************************************
* END of MACRO SECTION *
*******************************************************************************/
serpent_sbox:
.byte 0x83, 0x1F, 0x6A, 0xB5, 0xDE, 0x24, 0x07, 0xC9
.byte 0xCF, 0x72, 0x09, 0xA5, 0xB1, 0x8E, 0xD6, 0x43
.byte 0x68, 0x97, 0xC3, 0xFA, 0x1D, 0x4E, 0xB0, 0x25
.byte 0xF0, 0x8B, 0x9C, 0x36, 0x1D, 0x42, 0x7A, 0xE5
.byte 0xF1, 0x38, 0x0C, 0x6B, 0x52, 0xA4, 0xE9, 0xD7
.byte 0x5F, 0xB2, 0xA4, 0xC9, 0x30, 0x8E, 0x6D, 0x17
.byte 0x27, 0x5C, 0x48, 0xB6, 0x9E, 0xF1, 0x3D, 0x0A
.byte 0xD1, 0x0F, 0x8E, 0xB2, 0x47, 0xAC, 0x39, 0x65
serpent_sbox_inv:
.byte 0x3D, 0x0B, 0x6A, 0xC5, 0xE1, 0x74, 0x9F, 0x28
.byte 0x85, 0xE2, 0x6F, 0x3C, 0x4B, 0x97, 0xD1, 0x0A
.byte 0x9C, 0x4F, 0xEB, 0x21, 0x30, 0xD6, 0x85, 0x7A
.byte 0x90, 0x7A, 0xEB, 0xD6, 0x53, 0x2C, 0x84, 0x1F
.byte 0x05, 0x38, 0x9A, 0xE7, 0xC2, 0x6B, 0xF4, 0x1D
.byte 0xF8, 0x92, 0x14, 0xED, 0x6B, 0x35, 0xC7, 0x0A
.byte 0xAF, 0xD1, 0x35, 0x06, 0x94, 0x7E, 0xC2, 0xB8
.byte 0x03, 0xD6, 0xE9, 0x8F, 0xC5, 0x7B, 0x1A, 0x24
/*
* void ip(uint32_t *i, uint8_t *o){
*/
/*
* param i is given in r24:r25
* parma o is given in r22:r23
*/
.global serpent_ip
serpent_ip:
push_range 2, 17
movw r26, r24
ldi r24, 16
clr r31
ldi r30, 2
1:
ld r25, X+
st Z+, r25
dec r24
brne 1b
/* now the whole input is loaded in r2-r18 */
movw r26, r22
ldi r21, 4
4:
ldi r20, 8
2:
lsr r2
ror r19
lsr r6
ror 19
lsr r10
ror r19
lsr r14
ror 19
sbrc r20, 0
st X+, r19
dec r20
brne 2b
ldi r20, 15
ldi r30, 2
3:
ldd r19, Z+1
st Z+, r19
dec r20
brne 3b
dec r21
brne 4b
pop_range 2, 17
ret
/*
* void serpent_fp(uint32_t *i, uint8_t *o){
*/
/*
* param i is given in r24:r25
* parma o is given in r22:r23
*/
.global serpent_fp
serpent_fp:
movw r26, r24
movw r30, r22
ldi r18, 4
1:
ldi r19, 8
2:
sbrs r19, 0
ld r24, X+
3:
lsr r24
ror r20
lsr r24
ror r21
lsr r24
ror r22
lsr r24
ror r23
dec r19
brne 2b
st Z+, r20
std Z+3, r21
std Z+7, r22
std Z+11, r23
dec r18
brne 1b
ret
/*
* void inv_sbox128(void * w, uint8_t box)
*/
.global inv_sbox128
inv_sbox128:
andi r22, 0x07
ori r22, 0x08
rjmp sbox128x
/*
* void sbox128(void * w, uint8_t box);
*/
/*
* param w is passed in r24:r25
* param box is passed in r22
*/
.global sbox128
sbox128:
andi r22, 0x07
/*
* void sbox128x(void * w, uint8_t box);
*/
/*
* param w is passed in r24:r25
* param box is passed in r22
*/
.global sbox128x
sbox128x:
stack_alloc 16
adiw r30, 1
push_ r24, r25, r22, r30, r31
movw r22, r30 /* Z points to the stack buffer */
rcall serpent_ip
pop_ r27, r26, r22
ldi r25, hi8(serpent_sbox)
ldi r24, lo8(serpent_sbox)
swap r22
lsr r22 /* r22 *= 8 */
add r24, r22
adc r25, r1
/* now we have X pointing to the buffer and (r24:r25) pointing to the SBox */
ldi r22, 16
1:
movw r30, r24
ld r18, X
mov r20, r18
andi r18, 0x0f
bst r18, 0
lsr r18
add r30, r18
adc r31, r1
lpm r19, Z
brtc 2f
swap r19
2:
swap r20
andi r20, 0x0f
bst r20, 0
lsr r20
movw r30, r24
add r30, r20
adc r31, r1
lpm r21, Z
brts 3f
swap r21
3:
andi r19, 0x0F
andi r21, 0xF0
or r19, r21
st X+, r19
dec r22
brne 1b
pop_ r23, r22
movw r24, r26
sbiw r24, 16
rcall serpent_fp
stack_free 16
ret

View File

@ -52,7 +52,7 @@ uint8_t sbox[] PROGMEM = {
#define SHR_O(a) c=(a)&1; ((a) = (a)>>1) #define SHR_O(a) c=(a)&1; ((a) = (a)>>1)
#define SHR_I(a) ((a) = (c?0x80:0x00)| ((a)>>1)) #define SHR_I(a) ((a) = (c?0x80:0x00)| ((a)>>1))
static void ip(uint8_t *o, uint32_t *i){ static void serpent_ip(uint32_t *i, uint8_t *o){
uint8_t c; // carry uint8_t c; // carry
uint8_t n,m; uint8_t n,m;
memset(o, 0, 16); memset(o, 0, 16);
@ -73,8 +73,7 @@ static void ip(uint8_t *o, uint32_t *i){
#undef SHR_I #undef SHR_I
#define SHR_I(a) ((a) = (c?0x80000000L:0x00L)| ((a)>>1)) /* we use 32-bit words here */ #define SHR_I(a) ((a) = (c?0x80000000L:0x00L)| ((a)>>1)) /* we use 32-bit words here */
static void serpent_fp(uint32_t *i, uint32_t *o){
static void fp(uint32_t *o, uint32_t *i){
uint8_t c; // carry uint8_t c; // carry
uint8_t n,m; uint8_t n,m;
memset(o, 0, 16); memset(o, 0, 16);
@ -93,7 +92,6 @@ static void fp(uint32_t *o, uint32_t *i){
} }
/******************************************************************************/ /******************************************************************************/
static void sbox128x(uint8_t box, void* w){ static void sbox128x(uint8_t box, void* w){
uint8_t sb[16]; uint8_t sb[16];
uint8_t i,t,x; uint8_t i,t,x;
@ -105,7 +103,7 @@ static void sbox128x(uint8_t box, void* w){
sb[2*i+1]=t&0xf; sb[2*i+1]=t&0xf;
} }
uint8_t o[16]; uint8_t o[16];
ip(o, w); serpent_ip(w,o);
for(i=0; i<16; ++i){ for(i=0; i<16; ++i){
t = ((uint8_t*)o)[i]; t = ((uint8_t*)o)[i];
@ -114,13 +112,17 @@ static void sbox128x(uint8_t box, void* w){
x |= sb[t&0xf]; x |= sb[t&0xf];
((uint8_t*)o)[i] = x; ((uint8_t*)o)[i] = x;
} }
fp(w, (uint32_t*)o); serpent_fp((uint32_t*)o, w);
} }
void sbox128(void * w, uint8_t box){ void sbox128(void * w, uint8_t box){
sbox128x(box&0x7, w); sbox128x(box&0x7, w);
} }
void inv_sbox128(void * w, uint8_t box){ void inv_sbox128(void * w, uint8_t box){
sbox128x(((box&0x7)|0x8), w); sbox128x(((box&0x7)|0x8), w);
} }

View File

@ -111,28 +111,28 @@ void serpent_init(const void* key, uint16_t keysize, serpent_ctx_t* ctx){
void serpent_enc(void* buffer, const serpent_ctx_t* ctx){ void serpent_enc(void* buffer, const serpent_ctx_t* ctx){
uint8_t i; uint8_t i;
for(i=0; i<31; ++i){ for(i=0; i<31; ++i){
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor(buffer, ctx->k[i], 16);
sbox128(buffer, i); sbox128(buffer, i);
lt((uint8_t*)buffer); lt((uint8_t*)buffer);
} }
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor(buffer, ctx->k[i], 16);
sbox128(buffer, i); sbox128(buffer, i);
++i; ++i;
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor(buffer, ctx->k[i], 16);
} }
void serpent_dec(void* buffer, const serpent_ctx_t* ctx){ void serpent_dec(void* buffer, const serpent_ctx_t* ctx){
int8_t i=32; int8_t i=32;
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor(buffer, ctx->k[i], 16);
--i; --i;
inv_sbox128(buffer, i); inv_sbox128(buffer, i);
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor((uint8_t*)buffer, ctx->k[i], 16);
--i; --i;
for(; i>=0; --i){ for(; i>=0; --i){
inv_lt((uint8_t*)buffer); inv_lt(buffer);
inv_sbox128(buffer, i); inv_sbox128(buffer, i);
memxor((uint8_t*)buffer, ctx->k[i], 16); memxor(buffer, ctx->k[i], 16);
} }
} }