optimized rotates for keccak

This commit is contained in:
bg 2010-08-30 18:04:40 +00:00
parent 794b705a0b
commit 25ccd391d2
5 changed files with 261 additions and 15 deletions

View File

@ -22,6 +22,7 @@
#include <string.h>
#include <avr/pgmspace.h>
#include "memxor.h"
#include "rotate64.h"
#include "keccak.h"
#ifdef DEBUG
@ -60,6 +61,7 @@ void keccak_dump_ctx(keccak_ctx_t* ctx){
#endif
/*
static uint64_t rc[] PROGMEM = {
0x0000000000000001LL, 0x0000000000008082LL,
0x800000000000808ALL, 0x8000000080008000LL,
@ -74,32 +76,45 @@ static uint64_t rc[] PROGMEM = {
0x8000000080008081LL, 0x8000000000008080LL,
0x0000000080000001LL, 0x8000000080008008LL
};
*/
static uint8_t rc_comp[] PROGMEM = {
0x01, 0x92, 0xda, 0x70,
0x9b, 0x21, 0xf1, 0x59,
0x8a, 0x88, 0x39, 0x2a,
0xbb, 0xcb, 0xd9, 0x53,
0x52, 0xc0, 0x1a, 0x6a,
0xf1, 0xd0, 0x21, 0x78,
};
uint64_t rotl64(uint64_t a, uint8_t r){
return (a<<r)|(a>>(64-r));
}
static uint8_t r[5][5] PROGMEM = {
{ 0, 36, 3, 41, 18 },
{ 1, 44, 10, 45, 2 },
{ 62, 6, 43, 15, 61 },
{ 28, 55, 25, 21, 56 },
{ 27, 20, 39, 8, 14 }
{ ROT_CODE( 0), ROT_CODE(36), ROT_CODE( 3), ROT_CODE(41), ROT_CODE(18) },
{ ROT_CODE( 1), ROT_CODE(44), ROT_CODE(10), ROT_CODE(45), ROT_CODE( 2) },
{ ROT_CODE(62), ROT_CODE( 6), ROT_CODE(43), ROT_CODE(15), ROT_CODE(61) },
{ ROT_CODE(28), ROT_CODE(55), ROT_CODE(25), ROT_CODE(21), ROT_CODE(56) },
{ ROT_CODE(27), ROT_CODE(20), ROT_CODE(39), ROT_CODE( 8), ROT_CODE(14) }
};
static inline
void keccak_round(uint64_t a[5][5], uint8_t rci){
uint64_t b[5][5];
uint8_t i,j;
union {
uint64_t v64;
uint8_t v8[8];
} t;
/* theta */
for(i=0; i<5; ++i){
b[i][0] = a[0][i] ^ a[1][i] ^ a[2][i] ^ a[3][i] ^ a[4][i];
}
for(i=0; i<5; ++i){
b[i][1] = b[(4+i)%5][0] ^ rotl64(b[(i+1)%5][0], 1);
}
for(i=0; i<5; ++i){
t.v64 = b[(4+i)%5][0] ^ rotate64_1bit_left(b[(i+1)%5][0]);
for(j=0; j<5; ++j){
a[j][i] ^= b[i][1];
a[j][i] ^= t.v64;
}
}
#if DEBUG
@ -109,7 +124,8 @@ void keccak_round(uint64_t a[5][5], uint8_t rci){
/* rho & pi */
for(i=0; i<5; ++i){
for(j=0; j<5; ++j){
b[(2*i+3*j)%5][j] = rotl64(a[j][i], pgm_read_byte(&(r[i][j])));
// b[(2*i+3*j)%5][j] = rotl64(a[j][i], pgm_read_byte(&(r[i][j])));
b[(2*i+3*j)%5][j] = rotate64left_code(a[j][i], pgm_read_byte(&(r[i][j])));
}
}
#if DEBUG
@ -127,9 +143,22 @@ void keccak_round(uint64_t a[5][5], uint8_t rci){
keccak_dump_state(a);
#endif
/* iota */
uint64_t t;
memcpy_P(&t, &(rc[rci]), 8);
a[0][0] ^= t;
// memcpy_P(&t, &(rc_comp[rci]), 8);
t.v64 = 0;
t.v8[0] = pgm_read_byte(&(rc_comp[rci]));
if(t.v8[0]&0x40){
t.v8[7] = 0x80;
}
if(t.v8[0]&0x20){
t.v8[3] = 0x80;
}
if(t.v8[0]&0x10){
t.v8[1] = 0x80;
}
t.v8[0] &= 0x8F;
a[0][0] ^= t.v64;
#if DEBUG
cli_putstr_P(PSTR("\r\nAfter iota:"));
keccak_dump_state(a);

168
keccak/rotate64.S Normal file
View File

@ -0,0 +1,168 @@
/* rotate64.S */
/*
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2006-2010 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/>.
*/
.global rotate64_1bit_left
rotate64_1bit_left:
bst r25, 7
rol r18
rol r19
rol r20
rol r21
rol r22
rol r23
rol r24
rol r25
bld r18, 0
ret
.global rotate64_1bit_right
rotate64_1bit_right:
bst r18, 0
ror r25
ror r24
ror r23
ror r22
ror r21
ror r20
ror r19
ror r18
bld r25, 7
ret
.global rotate64_nbit_autodir
rotate64_nbit_autodir:
lsr r16
brcc rotate64_nbit_left
.global rotate64_nbit_right
rotate64_nbit_right:
ldi r30, pm_lo8(rotate64_1bit_right)
ldi r31, pm_hi8(rotate64_1bit_right)
rjmp icall_r16_times
.global rotate64_nbit_left
rotate64_nbit_left:
ldi r30, pm_lo8(rotate64_1bit_left)
ldi r31, pm_hi8(rotate64_1bit_left)
icall_r16_times:
1: dec r16
brmi 2f
icall
rjmp 1b
2:
pop r16
ret
rotate64_1byte_left:
mov r0, r25
mov r25, r24
mov r24, r23
mov r23, r22
mov r22, r21
mov r21, r20
mov r20, r19
mov r19, r18
mov r18, r0
ret
rotate64_2byte_left:
movw r0, r24
movw r24, r22
movw r22, r20
movw r20, r18
movw r18, r0
ret
rotate64_3byte_left:
mov r0, r25
mov r25, r22
mov r22, r19
mov r19, r24
mov r24, r21
mov r21, r18
mov r18, r23
mov r23, r20
mov r20, r0
ret
rotate64_4byte_left:
movw r0, r24
movw r24, r20
movw r20, r0
movw r0, r22
movw r22, r18
movw r18, r0
ret
rotate64_5byte_left:
mov r0, r25
mov r25, r20
mov r20, r23
mov r23, r18
mov r18, r21
mov r21, r24
mov r24, r19
mov r19, r22
mov r22, r0
ret
rotate64_6byte_left:
movw r0, r18
movw r18, r20
movw r20, r22
movw r22, r24
movw r24, r0
ret
rotate64_7byte_left:
mov r0, r18
mov r18, r19
mov r19, r20
mov r20, r21
mov r21, r22
mov r22, r23
mov r23, r24
mov r24, r25
mov r25, r0
ret
byte_rot_jmp_table:
ret
rjmp rotate64_1byte_left
rjmp rotate64_2byte_left
rjmp rotate64_3byte_left
rjmp rotate64_4byte_left
rjmp rotate64_5byte_left
rjmp rotate64_6byte_left
rjmp rotate64_7byte_left
.global rotate64left_code
rotate64left_code:
ldi r30, pm_lo8(byte_rot_jmp_table)
ldi r31, pm_hi8(byte_rot_jmp_table)
push r16
mov r0, r16
andi r16, 0x70
swap r16
add r30, r16
adc r31, r1
mov r16, r0
andi r16, 0x0f
icall
clr r1
rjmp rotate64_nbit_autodir

48
keccak/rotate64.h Normal file
View File

@ -0,0 +1,48 @@
/* rotate64.h */
/*
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 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/>.
*/
#ifndef ROTATE64_H_
#define ROTATE64_H_
#include <stdint.h>
#define ROTL_0 0
#define ROTL_1 1
#define ROTL_2 2
#define ROTL_3 3
#define ROTL_4 4
#define ROTR_0 0
#define ROTR_1 (8+1)
#define ROTR_2 (8+2)
#define ROTR_3 (8+3)
#define ROT_BIT(a) (((a)<=4)?((a)<<1):(0x01|((8-(a))<<1)))
//#define ROT_CODE(a,b) (((a)<<4) | ((b)&0x0f))
#define ROT_CODE(a) ((((a)/8+((((a)%8)>4)?1:0))<<4) | ROT_BIT(((a)%8)))
//#define ROT_CODE(a) ((((a)/8)<<4) | ((a)%8)) /* rotations only to the left */
uint64_t rotate64_1bit_left(uint64_t a);
uint64_t rotate64_1bit_right(uint64_t a);
uint64_t rotate64_nbit_autodir(uint64_t a, int8_t n);
uint64_t rotate64left_code(uint64_t a, int8_t code);
#endif /* ROTATE64_H_ */

View File

@ -5,7 +5,7 @@ ALGO_NAME := KECCAK_C
HASHES += $(ALGO_NAME)
$(ALGO_NAME)_DIR := keccak/
$(ALGO_NAME)_OBJ := keccak.o memxor.o
$(ALGO_NAME)_OBJ := keccak.o memxor.o rotate64.o
$(ALGO_NAME)_TEST_BIN := main-keccak-test.o hfal_keccak.o $(CLI_STD) $(HFAL_STD)
$(ALGO_NAME)_NESSIE_TEST := test nessie
$(ALGO_NAME)_PERFORMANCE_TEST := performance

View File

@ -60,7 +60,8 @@ void test_256(void){
memset(null, 0, KECCAK256_BLOCKSIZE_B);
keccak_ctx_t ctx;
keccak256_init(&ctx);
keccak_lastBlock(&ctx, data, 29);
keccak_nextBlock(&ctx, null);
// keccak_lastBlock(&ctx, data, 29);
keccak256_ctx2hash(hash, &ctx);
cli_putstr_P(PSTR("\r\n testhash: "));
cli_hexdump(hash, 32);