more mqq stuff
This commit is contained in:
parent
c9c11514d9
commit
056b130e81
|
@ -146,15 +146,6 @@ void hfal_stacksize(const hfdesc_t* hd){
|
|||
cli_putstr_P(PSTR("\r\n\r\n === "));
|
||||
cli_putstr_P(hf.name);
|
||||
cli_putstr_P(PSTR(" stack-usage === "
|
||||
"\r\n type: hashfunction"
|
||||
"\r\n hashsize (bits): "));
|
||||
printvalue(hf.hashsize_b);
|
||||
|
||||
cli_putstr_P(PSTR("\r\n ctxsize (bytes): "));
|
||||
printvalue(hf.ctxsize_B);
|
||||
|
||||
cli_putstr_P(PSTR("\r\n blocksize (bits): "));
|
||||
printvalue(hf.blocksize_b);
|
||||
|
||||
cli();
|
||||
stack_measure_init(&smctx, PATTERN_A);
|
||||
|
|
|
@ -73,10 +73,26 @@ def process_hashfunction(fin, name, fsize)
|
|||
lb = fin.readline()
|
||||
m = lb.match(/ctx2hash \(cycles\):[\s]*([\d]*)/)
|
||||
convtime = m[1].to_i()
|
||||
begin
|
||||
lb = fin.readline()
|
||||
end until m = lb.match(/init \(bytes\):[\s]*([\d]*)/)
|
||||
initstack = m[1].to_i()
|
||||
lb = fin.readline()
|
||||
m = lb.match(/nextBlock \(bytes\):[\s]*([\d]*)/)
|
||||
nextblockstack = m[1].to_i()
|
||||
lb = fin.readline()
|
||||
m = lb.match(/lastBlock \(bytes\):[\s]*([\d]*)/)
|
||||
lastblockstack = m[1].to_i()
|
||||
lb = fin.readline()
|
||||
m = lb.match(/ctx2hash \(bytes\):[\s]*([\d]*)/)
|
||||
convstack = m[1].to_i()
|
||||
s1 = (initstack>nextblockstack)?initstack:nextblockstack
|
||||
s2 = (lastblockstack>convstack)?lastblockstack:convstack
|
||||
stack = (s1>s2)?s1:s2
|
||||
size = get_size_string(fsize)
|
||||
printf("| %20s || %3s || %3s \n| %s \n| %4d || || %4d || %4d ||" +
|
||||
printf("| %20s || %3s || %3s \n| %s \n| %4d || %4d || %4d || %4d ||" +
|
||||
" %6d || %6d || %7.2f || %6d || || || \n|-\n" ,
|
||||
name, $lang, $lang, size, ctxsize, hashsize, blocksize,
|
||||
name, $lang, $lang, size, ctxsize, stack, hashsize, blocksize,
|
||||
inittime, nextblocktime, nextblocktime.to_f/(blocksize/8),
|
||||
lastblocktime+convtime)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# Makefile for MQQ160-sign
|
||||
ALGO_NAME := MQQ160-SIGN
|
||||
|
||||
# comment out the following line for removement of MQQ160-sign from the build process
|
||||
SIGNATURE += $(ALGO_NAME)
|
||||
|
||||
$(ALGO_NAME)_DIR := mqq-sign/
|
||||
$(ALGO_NAME)_OBJ := mqq160-sign-asm.o mqq160-sign_P-asm.o mqq160-sign_testkey.o
|
||||
$(ALGO_NAME)_TEST_BIN := main-mqq160-sign-test.o performance_test.o stack_measuring.o $(CLI_STD)
|
||||
$(ALGO_NAME)_NESSIE_TEST := test
|
||||
$(ALGO_NAME)_PERFORMANCE_TEST := performance
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# Makefile for MQQ160-sign
|
||||
ALGO_NAME := MQQ160-SIGN_C
|
||||
|
||||
# comment out the following line for removement of MQQ160-sign from the build process
|
||||
SIGNATURE += $(ALGO_NAME)
|
||||
|
||||
$(ALGO_NAME)_DIR := mqq-sign/
|
||||
$(ALGO_NAME)_OBJ := mqq160-sign.o mqq160-sign_P.o mqq160-sign_testkey.o memxor.o
|
||||
$(ALGO_NAME)_TEST_BIN := main-mqq160-sign-test.o performance_test.o stack_measuring.o $(CLI_STD)
|
||||
$(ALGO_NAME)_NESSIE_TEST := test
|
||||
$(ALGO_NAME)_PERFORMANCE_TEST := performance
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* memxor.S */
|
||||
/*
|
||||
This file is part of the AVR-Crypto-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: memxor.S
|
||||
* Author: Daniel Otte
|
||||
* Date: 2008-08-07
|
||||
* License: GPLv3 or later
|
||||
* Description: memxor, XORing one block into another
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* void memxor(void* dest, const void* src, uint16_t n);
|
||||
*/
|
||||
/*
|
||||
* param dest is passed in r24:r25
|
||||
* param src is passed in r22:r23
|
||||
* param n is passed in r20:r21
|
||||
*/
|
||||
.global memxor
|
||||
memxor:
|
||||
movw r30, r24
|
||||
movw r26, r22
|
||||
movw r24, r20
|
||||
adiw r24, 0
|
||||
breq 2f
|
||||
1:
|
||||
ld r20, X+
|
||||
ld r21, Z
|
||||
eor r20, r21
|
||||
st Z+, r20
|
||||
sbiw r24, 1
|
||||
brne 1b
|
||||
2:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef MEMXOR_H_
|
||||
#define MEMXOR_H_
|
||||
#include <stdint.h>
|
||||
|
||||
void memxor(void* dest, const void* src, uint16_t n);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,540 @@
|
|||
/* mqq160-sign_P-asm.S */
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
* \file mqq160-sign_P-asm.S
|
||||
* \email daniel.otte@rub.de
|
||||
* \author Daniel Otte
|
||||
* \date 2010-03-21
|
||||
* \license GPLv3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "avr-asm-macros.S"
|
||||
|
||||
#if 0
|
||||
static void mqq_inv_affine_transformation(uint8_t* input_bytes, uint8_t* result, const mqq160_sign_key_t* key){
|
||||
/* The matrix SInv is given as two permutations of 160 elements. */
|
||||
uint8_t j, byteindex, bitindex, bitindex_d, byteindex_d, rp1, rp5;
|
||||
uint8_t *r1_ptr, *r5_ptr;
|
||||
uint8_t h1[20];
|
||||
|
||||
/* Initialize H1 and H2 = 0 */
|
||||
memset(h1, 0, 20);
|
||||
memset(result, 0, 20);
|
||||
|
||||
/*
|
||||
Fill H1 with bits of InputBytes accordingly to RP1 permutation
|
||||
and fill H2 with bits of InputBytes accordingly to RP5 permutation
|
||||
*/
|
||||
bitindex_d = 0x80;
|
||||
byteindex_d = 0;
|
||||
j=160;
|
||||
r1_ptr = key->rp1;
|
||||
r5_ptr = key->rp5;
|
||||
do{
|
||||
rp1 = pgm_read_byte(r1_ptr++);
|
||||
rp5 = pgm_read_byte(r5_ptr++);
|
||||
byteindex = rp1>>3;
|
||||
bitindex = 0x80 >> (rp1&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
h1[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
|
||||
byteindex = rp5>>3;
|
||||
bitindex = 0x80 >> (rp5&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
result[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
bitindex_d >>= 1;
|
||||
if(bitindex_d==0){
|
||||
++byteindex_d;
|
||||
bitindex_d = 0x80;
|
||||
}
|
||||
}while(--j);
|
||||
|
||||
for (j=0; j<20; j++){
|
||||
result[j] ^= h1[j] ^ h1[pgm_read_byte(j+mod20_table)]
|
||||
^ h1[pgm_read_byte(8+j+mod20_table)]
|
||||
^ h1[pgm_read_byte(12+j+mod20_table)];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fetch_bit:
|
||||
ld r0, Z+
|
||||
mov r28, r0
|
||||
ldi r29, 0x80
|
||||
andi r28, 7
|
||||
breq 3f
|
||||
2: lsr r29
|
||||
dec r28
|
||||
brne 2b
|
||||
3: mov r28, r0
|
||||
lsr r28
|
||||
lsr r28
|
||||
lsr r28
|
||||
mov r0, r29
|
||||
clr r29
|
||||
add r28, r24
|
||||
adc r29, r25
|
||||
ld r28, Y
|
||||
clt
|
||||
and r28, r0
|
||||
breq 4f
|
||||
set
|
||||
4: ret
|
||||
|
||||
xres_0 = 18
|
||||
xres_1 = 19
|
||||
h_0 = 20
|
||||
h_1 = 21
|
||||
xrp5_0 = 22
|
||||
xrp5_1 = 23
|
||||
inp_0 = 24
|
||||
inp_1 = 25
|
||||
tmp_0 = 22
|
||||
tmp_1 = 23
|
||||
tmp_2 = 24
|
||||
tmp_3 = 25
|
||||
tmp_4 = 18
|
||||
|
||||
/*
|
||||
param input_bytes: r24:r25
|
||||
param result: r22:r23
|
||||
param key: r20:r21
|
||||
*/
|
||||
;.global mqq_inv_affine_transformation
|
||||
mqq_inv_affine_transformation:
|
||||
push r17
|
||||
; push r28
|
||||
; push r29
|
||||
stack_alloc 20
|
||||
adiw r30, 1 /* Z points to stack space for h1 */
|
||||
movw r28, r20 /* Y points to the key struct in RAM */
|
||||
movw xres_0, r22
|
||||
movw r26, r30 /* X points to h1[0] */
|
||||
ldd xrp5_0, Y+8 /* load pointer rp5 to xrp5 */
|
||||
ldd xrp5_1, Y+9
|
||||
movw h_0, r30
|
||||
ldd r30, Y+6 /* load pointer to rp1 in Z */
|
||||
ldd r31, Y+7
|
||||
ldi r17, 20
|
||||
20: rcall fetch_bit
|
||||
bld r1, 7
|
||||
rcall fetch_bit
|
||||
bld r1, 6
|
||||
rcall fetch_bit
|
||||
bld r1, 5
|
||||
rcall fetch_bit
|
||||
bld r1, 4
|
||||
rcall fetch_bit
|
||||
bld r1, 3
|
||||
rcall fetch_bit
|
||||
bld r1, 2
|
||||
rcall fetch_bit
|
||||
bld r1, 1
|
||||
rcall fetch_bit
|
||||
bld r1, 0
|
||||
st X+, r1
|
||||
dec r17
|
||||
brne 20b
|
||||
;----
|
||||
movw r26, xres_0 /* X points to result */
|
||||
movw r30, xrp5_0
|
||||
ldi r17, 20
|
||||
20: rcall fetch_bit
|
||||
bld r1, 7
|
||||
rcall fetch_bit
|
||||
bld r1, 6
|
||||
rcall fetch_bit
|
||||
bld r1, 5
|
||||
rcall fetch_bit
|
||||
bld r1, 4
|
||||
rcall fetch_bit
|
||||
bld r1, 3
|
||||
rcall fetch_bit
|
||||
bld r1, 2
|
||||
rcall fetch_bit
|
||||
bld r1, 1
|
||||
rcall fetch_bit
|
||||
bld r1, 0
|
||||
st X+, r1
|
||||
dec r17
|
||||
brne 20b
|
||||
clr r1
|
||||
; --- now we mix result with h1
|
||||
sbiw r26, 20 /* adjusting X to point at result[0] */
|
||||
movw tmp_2, h_0
|
||||
ldi r30, lo8(affine_mix_lut)
|
||||
ldi r31, hi8(affine_mix_lut)
|
||||
ldi r17, 20
|
||||
30:
|
||||
ld tmp_0, X
|
||||
movw r28, tmp_2
|
||||
ld tmp_1, Y+
|
||||
movw tmp_2, r28
|
||||
eor tmp_0, tmp_1
|
||||
movw r28, h_0
|
||||
lpm r0, Z+
|
||||
mov tmp_4, r0
|
||||
andi tmp_4, 0x0f
|
||||
add r28, tmp_4
|
||||
adc r29, r1
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
adiw r28, 4
|
||||
sbrc r0, 7
|
||||
adiw r28, 4
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
adiw r28, 4
|
||||
sbrc r0, 6
|
||||
adiw r28, 4
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
st X+, tmp_0
|
||||
dec r17
|
||||
brne 30b
|
||||
|
||||
stack_free 20
|
||||
; pop r29
|
||||
; pop r28
|
||||
pop r17
|
||||
ret
|
||||
|
||||
affine_mix_lut:
|
||||
.byte 0x84, 0x85, 0x86, 0x87
|
||||
.byte 0xC0, 0xC1, 0xC2, 0xC3
|
||||
.byte 0x40, 0x41, 0x42, 0x43
|
||||
.byte 0x44, 0x45, 0x46, 0x47
|
||||
.byte 0x80, 0x81, 0x82, 0x83
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
xres = 20
|
||||
tmp_0 = 23
|
||||
tmp_1 = 22
|
||||
tmp_2 = 21
|
||||
tmp_3 = 19
|
||||
/*
|
||||
param i: r24
|
||||
param b1: r22
|
||||
param b2: r20
|
||||
param key: r18:r19
|
||||
*/
|
||||
;.global mqq_q
|
||||
mqq_q:
|
||||
; push r28
|
||||
; push r29
|
||||
; stack_alloc 25, r26, r27
|
||||
; adiw r26, 1 /* X points to e[0] */
|
||||
movw r28, r18
|
||||
sbrs r24, 0
|
||||
adiw r28, 2
|
||||
ldd r30, Y+2
|
||||
ldd r31, Y+3
|
||||
ldi r28, 9
|
||||
10: ld r0, Z+
|
||||
st X+, r0
|
||||
dec r28
|
||||
brne 10b
|
||||
sbiw r26, 9 /* adjust X to point at e[0] */
|
||||
;---
|
||||
movw r28, r18
|
||||
ld r30, Y+ /* Z points to a[0] in progmem */
|
||||
ld r31, Y
|
||||
sbrs r24, 0
|
||||
rjmp 40f
|
||||
20:
|
||||
sbrs r22, 7
|
||||
rjmp 30f
|
||||
ldi r25, 9
|
||||
movw r28, r30
|
||||
25: ld r0, Z
|
||||
adiw r30, 9
|
||||
ld r24, X
|
||||
eor r24, r0
|
||||
st X+, r24
|
||||
dec r25
|
||||
brne 25b
|
||||
movw r30, r28
|
||||
sbiw r26, 9
|
||||
30:
|
||||
adiw r30, 1
|
||||
lsl r22
|
||||
breq 60f
|
||||
rjmp 20b
|
||||
40:
|
||||
sbrs r22, 7
|
||||
rjmp 50f
|
||||
ldi r25, 9
|
||||
movw r28, r30
|
||||
45: ld r0, Z+
|
||||
ld r24, X
|
||||
eor r24, r0
|
||||
st X+, r24
|
||||
dec r25
|
||||
brne 45b
|
||||
movw r30, r28
|
||||
sbiw r26, 9
|
||||
50:
|
||||
adiw r30, 9
|
||||
lsl r22
|
||||
breq 60f
|
||||
rjmp 40b
|
||||
60:
|
||||
;------ all inputs are consumed, X points at e[0]
|
||||
;------ So we finished with obtaining e0 .. e7 and e8
|
||||
movw r28, r26
|
||||
ldd r0, Y+8
|
||||
eor xres, r0
|
||||
;---
|
||||
|
||||
/*
|
||||
We can look at the bits of e0 .. e7 as a columns of a given matrix. We want to define 8 variables that have the rows
|
||||
of that matrix. The variables need to be 16-bit because we will put into the upper 8 bits the bits of e0 .. e7,
|
||||
and the bits of the variable result will be the Least Significant Bits of a[0] ... a[7].
|
||||
*/
|
||||
adiw r28, 9 /* Y points at a[0] */
|
||||
ldi r25, 8
|
||||
63:
|
||||
ldi r24, 8
|
||||
clr tmp_0
|
||||
65: ld tmp_1, X
|
||||
lsl tmp_1
|
||||
st X+, tmp_1
|
||||
rol tmp_0
|
||||
dec r24
|
||||
brne 65b
|
||||
;---
|
||||
clr tmp_1
|
||||
lsl xres
|
||||
rol tmp_1
|
||||
st Y+, tmp_1
|
||||
st Y+, tmp_0
|
||||
sbiw r26, 8
|
||||
dec r25
|
||||
brne 63b
|
||||
;------- First we apply upper triangular transformation
|
||||
sbiw r28, 16 /* Y points at a[0] */
|
||||
movw r30, r28 /* Z points at a[0] */
|
||||
|
||||
col = 25
|
||||
ldi r24, 8
|
||||
clr col
|
||||
70:
|
||||
mov r1, col
|
||||
ldi tmp_3, 0x80
|
||||
tst r1
|
||||
breq 72f
|
||||
71: lsr tmp_3
|
||||
dec r1
|
||||
brne 71b
|
||||
72:
|
||||
clt
|
||||
movw r28, r30 /* Y points at a[row]*/
|
||||
73: ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
brne 74f
|
||||
set
|
||||
adiw r28, 2
|
||||
rjmp 73b
|
||||
74:
|
||||
/* Y points at a[row] */
|
||||
/* if T is set we have to permute [Y] and [Z] */
|
||||
brtc 75f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
st Y, tmp_1
|
||||
st Z, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
std Y+1, tmp_1
|
||||
std Z+1, tmp_0
|
||||
75: /* permutation done */
|
||||
ldi r26, 7
|
||||
sub r26, col
|
||||
breq 78f
|
||||
movw r28, r30
|
||||
76: adiw r28, 2
|
||||
ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
breq 77f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
eor tmp_0, tmp_1
|
||||
st Y, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
eor tmp_0, tmp_1
|
||||
std Y+1, tmp_0
|
||||
77:
|
||||
dec r26
|
||||
brne 76b
|
||||
78:
|
||||
adiw r30, 2
|
||||
inc col
|
||||
dec r24
|
||||
brne 70b
|
||||
79:
|
||||
;------ Then we eliminate 1s above the main diagonal
|
||||
|
||||
ldi col, 7
|
||||
ldi tmp_3, 1
|
||||
sbiw r30, 2
|
||||
80:
|
||||
movw r28, r30
|
||||
mov r26, col
|
||||
81:
|
||||
sbiw r28, 2
|
||||
ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
breq 82f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
eor tmp_0, tmp_1
|
||||
st Y, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
eor tmp_0, tmp_1
|
||||
std Y+1, tmp_0
|
||||
82:
|
||||
dec r26
|
||||
brne 81b
|
||||
sbiw r30, 2
|
||||
lsl tmp_3
|
||||
dec col
|
||||
brne 80b
|
||||
89:
|
||||
;------ The result is in the Least Significant Bits of a[0] ... a[7]
|
||||
/* Z should point at a[0] */
|
||||
ldi r25, 8
|
||||
clr r24
|
||||
90:
|
||||
ld tmp_0, Z
|
||||
adiw r30, 2
|
||||
lsr tmp_0
|
||||
rol r24
|
||||
dec r25
|
||||
brne 90b
|
||||
mqq_q_exit:
|
||||
; stack_free 25
|
||||
; pop r29
|
||||
; pop r28
|
||||
ret
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
param dest: r24:r25
|
||||
param hash: r22:r23
|
||||
param key: r20:r21
|
||||
*/
|
||||
|
||||
dest_0 = 2
|
||||
dest_1 = 3
|
||||
xr1_0 = 4
|
||||
xr1_1 = 5
|
||||
key_0 = 6
|
||||
key_1 = 7
|
||||
i = 8
|
||||
c = 9
|
||||
qstack_0 = 10
|
||||
qstack_1 = 11
|
||||
|
||||
.global mqq160_sign
|
||||
mqq160_sign:
|
||||
push_range 2, 11
|
||||
push_range 28, 29
|
||||
stack_alloc 20, r26, r27 /* r1[20] + key */
|
||||
adiw r26, 1 /* X points to stack memory */
|
||||
movw key_0, r20
|
||||
movw xr1_0, r26
|
||||
movw dest_0, r24
|
||||
/* call to mqq_inv_affine_transformation(hash, dest, &key); */
|
||||
movw r24, r22
|
||||
movw r22, dest_0
|
||||
movw r20, key_0
|
||||
rcall mqq_inv_affine_transformation
|
||||
|
||||
/* r1[0]=((uint8_t*)dest)[0]; */
|
||||
movw r26, dest_0
|
||||
movw r30, xr1_0
|
||||
ld r0, X
|
||||
st Z, r0
|
||||
;----
|
||||
ldi r18, 19
|
||||
mov c, r18
|
||||
clr i
|
||||
inc i
|
||||
stack_alloc 25, r28, r29
|
||||
adiw r28, 1
|
||||
movw qstack_0, r28
|
||||
20: mov r24, i
|
||||
movw r26, xr1_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
sbiw r26, 1
|
||||
ld r22, X
|
||||
movw r26, dest_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
ld r20, X
|
||||
movw r18, key_0
|
||||
movw r26, qstack_0
|
||||
rcall mqq_q
|
||||
movw r26, xr1_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
st X, r24
|
||||
inc i
|
||||
dec c
|
||||
brne 20b
|
||||
stack_free 25
|
||||
;-----
|
||||
|
||||
|
||||
movw r28, key_0
|
||||
ldd r30, Y+8
|
||||
ldd r31, Y+9
|
||||
movw r26, xr1_0
|
||||
ldi r18, 20
|
||||
30: ld r20, Z+
|
||||
swap r20
|
||||
andi r20, 0xF0
|
||||
ld r21, Z+
|
||||
andi r21, 0x0F
|
||||
or r20, r21
|
||||
ld r21, X
|
||||
eor r21, r20
|
||||
st X+, r21
|
||||
dec r18
|
||||
brne 30b
|
||||
;----
|
||||
|
||||
movw r24, xr1_0
|
||||
movw r22, dest_0
|
||||
movw r20, key_0
|
||||
rcall mqq_inv_affine_transformation
|
||||
stack_free 20
|
||||
pop_range 28, 29
|
||||
pop_range 2, 11
|
||||
ret
|
||||
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
/* mqq160-sign.c */
|
||||
/*
|
||||
C code for MQQ160-SIGN suitable for 8-bit smart cards
|
||||
|
||||
It is supposed that the private key is "engraved" in
|
||||
the ROM of the smart card - thus it is here stored as
|
||||
predefined const arrays in "MQQ160-SIGN-PrivateKey.h"
|
||||
|
||||
Programmed by
|
||||
Danilo Gligoroski and Rune Jensen and Daniel Otte
|
||||
March 2010.
|
||||
|
||||
Verified by Danilo Gligoroski
|
||||
March 2010.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "memxor.h"
|
||||
#include "mqq160-sign.h"
|
||||
|
||||
#include "cli.h"
|
||||
|
||||
static uint8_t mod20_table[32] PROGMEM = {
|
||||
4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
};
|
||||
|
||||
static void memxor_idx(void* dest, const void* src, uint16_t length, uint8_t dist){
|
||||
while(length--){
|
||||
*((uint8_t*)dest) ^= *((uint8_t*)src);
|
||||
dest = (uint8_t*)dest + 1;
|
||||
src = (uint8_t*)src + dist;
|
||||
}
|
||||
}
|
||||
/*
|
||||
This is just for testing purposes.
|
||||
It should be programmed in a more flexible way
|
||||
in the MQQ160-SIGN C Library.
|
||||
*/
|
||||
|
||||
static void mqq_inv_affine_transformation(const uint8_t* input_bytes, uint8_t* result, const mqq160_sign_key_t* key){
|
||||
/* The matrix SInv is given as two permutations of 160 elements. */
|
||||
uint8_t j, byteindex, bitindex, bitindex_d, byteindex_d, rp1, rp5;
|
||||
uint8_t *rp1_ptr, *rp5_ptr;
|
||||
uint8_t h1[20];
|
||||
|
||||
|
||||
/* Initialize H1 and H2 = 0 */
|
||||
memset(h1, 0, 20);
|
||||
memset(result, 0, 20);
|
||||
|
||||
/*
|
||||
Fill H1 with bits of InputBytes accordingly to RP1 permutation
|
||||
and fill H2 with bits of InputBytes accordingly to RP5 permutation
|
||||
*/
|
||||
j=160;
|
||||
byteindex_d = 0;
|
||||
bitindex_d = 0x80;
|
||||
rp1_ptr = key->rp1;
|
||||
rp5_ptr = key->rp5;
|
||||
do{
|
||||
rp1 = *rp1_ptr++;
|
||||
rp5 = *rp5_ptr++;
|
||||
byteindex = rp1>>3;
|
||||
bitindex = 0x80 >> (rp1&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
h1[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
|
||||
byteindex = rp5>>3;
|
||||
bitindex = 0x80 >> (rp5&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
result[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
bitindex_d >>= 1;
|
||||
if(bitindex_d==0){
|
||||
++byteindex_d;
|
||||
bitindex_d = 0x80;
|
||||
}
|
||||
}while(--j);
|
||||
// cli_putstr_P(PSTR("\r\nDBG (ref): "));
|
||||
// cli_hexdump(h1, 20);
|
||||
for (j=0; j<20; j++){
|
||||
result[j] ^= h1[j] ^ h1[pgm_read_byte(j+mod20_table)]
|
||||
^ h1[pgm_read_byte(8+j+mod20_table)]
|
||||
^ h1[pgm_read_byte(12+j+mod20_table)];
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t MaskShort[8] = {0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100};
|
||||
|
||||
static uint8_t mqq_q(uint8_t i, uint8_t b1, uint8_t b2, const mqq160_sign_key_t* key){
|
||||
uint8_t e[9];
|
||||
uint16_t a[8];
|
||||
uint8_t result, column, row, k;
|
||||
int8_t j;
|
||||
uint16_t temp;
|
||||
uint8_t *tmp_ptr=key->a;
|
||||
if(i&1){
|
||||
memcpy(e, key->cc1, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor_idx((uint8_t*)e, tmp_ptr, 9, 9);
|
||||
}
|
||||
tmp_ptr++;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}else{
|
||||
memcpy(e, key->cc2, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor((uint8_t*)e, tmp_ptr, 9);
|
||||
}
|
||||
tmp_ptr+=9;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}
|
||||
/* So we finished with obtaining e0 .. e7 and e8 */
|
||||
|
||||
/* We XOR e[8] with b2 and that will be initial value to transform in order to solve a linear system of equations */
|
||||
result=b2 ^ e[8];
|
||||
|
||||
/*
|
||||
We can look at the bits of e0 .. e7 as a columns of a given matrix. We want to define 8 variables that have the rows
|
||||
of that matrix. The variables need to be 16-bit because we will put into the upper 8 bits the bits of e0 .. e7,
|
||||
and the bits of the variable result will be the Least Significant Bits of a[0] ... a[7].
|
||||
*/
|
||||
for(j=0; j<8; ++j){
|
||||
row = 0;
|
||||
for(k=0; k<8; ++k){
|
||||
row |= (e[k]&0x80)>>(k);
|
||||
e[k]<<=1;
|
||||
}
|
||||
a[j]=(((uint16_t)row)<<8) | (result>>7);
|
||||
result <<= 1;
|
||||
}
|
||||
|
||||
/* Now we finally realize Gausian elimination */
|
||||
|
||||
/* First we apply upper triangular transformation */
|
||||
for(column=0; column<8; column++)
|
||||
{
|
||||
row=column;
|
||||
while ((a[row] & MaskShort[column]) == 0){
|
||||
row++;
|
||||
}
|
||||
if(row>column)
|
||||
{
|
||||
temp=a[column];
|
||||
a[column]=a[row];
|
||||
a[row]=temp;
|
||||
}
|
||||
for (j=column+1; j<8; j++)
|
||||
if ((a[j]&MaskShort[column]) !=0){
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
}
|
||||
|
||||
/* Then we eliminate 1s above the main diagonal */
|
||||
for (column=7; column>0; column--){
|
||||
for (j=column-1; j>=0; j--){
|
||||
if ((a[j]&MaskShort[column]) !=0){
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* The result is in the Least Significant Bits of a[0] ... a[7] */
|
||||
result = 0;
|
||||
for(j=0; j<8; ++j){
|
||||
result <<=1;
|
||||
result |= a[j]&1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void mqq160_sign(void* dest, const void* hash, const mqq160_sign_key_t* key){
|
||||
uint8_t i, r1[20], byteindex;
|
||||
mqq_inv_affine_transformation((uint8_t*)hash, (uint8_t*)dest, key);
|
||||
r1[0]=((uint8_t*)dest)[0];
|
||||
for(i=1; i<20; ++i){
|
||||
r1[i] = mqq_q(i, r1[i-1], ((uint8_t*)dest)[i], key);
|
||||
}
|
||||
/*
|
||||
Affine transformation is just for the second call. The constant is extracted
|
||||
from the 4 LSBs of the first 40 bytes of RP5[] and xor-ed to input_bytes[].
|
||||
*/
|
||||
byteindex = 0;
|
||||
for (i=0; i<20; i++){
|
||||
r1[i] ^= (uint8_t)((key->rp5[byteindex])<<4)
|
||||
| (uint8_t)(key->rp5[byteindex+1]&0x0F);
|
||||
byteindex += 2;
|
||||
}
|
||||
mqq_inv_affine_transformation(r1, (uint8_t*)dest, key);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* mqq160-sign.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 MQQ160SIGN_H_
|
||||
#define MQQ160SIGN_H_
|
||||
|
||||
typedef struct{
|
||||
uint8_t *a;
|
||||
uint8_t *cc1;
|
||||
uint8_t *cc2;
|
||||
uint8_t *rp1;
|
||||
uint8_t *rp5;
|
||||
} mqq160_sign_key_t;
|
||||
|
||||
void mqq160_sign(void* dest, const void* hash, const mqq160_sign_key_t* key);
|
||||
|
||||
#endif /* MQQ160SIGN_H_ */
|
|
@ -0,0 +1,547 @@
|
|||
/* mqq160-sign_P-asm.S */
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
* \file mqq160-sign_P-asm.S
|
||||
* \email daniel.otte@rub.de
|
||||
* \author Daniel Otte
|
||||
* \date 2010-03-21
|
||||
* \license GPLv3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "avr-asm-macros.S"
|
||||
|
||||
#if 0
|
||||
static void mqq_inv_affine_transformation(uint8_t* input_bytes, uint8_t* result, const mqq160_sign_key_t* key){
|
||||
/* The matrix SInv is given as two permutations of 160 elements. */
|
||||
uint8_t j, byteindex, bitindex, bitindex_d, byteindex_d, rp1, rp5;
|
||||
uint8_t *r1_ptr, *r5_ptr;
|
||||
uint8_t h1[20];
|
||||
|
||||
/* Initialize H1 and H2 = 0 */
|
||||
memset(h1, 0, 20);
|
||||
memset(result, 0, 20);
|
||||
|
||||
/*
|
||||
Fill H1 with bits of InputBytes accordingly to RP1 permutation
|
||||
and fill H2 with bits of InputBytes accordingly to RP5 permutation
|
||||
*/
|
||||
bitindex_d = 0x80;
|
||||
byteindex_d = 0;
|
||||
j=160;
|
||||
r1_ptr = key->rp1;
|
||||
r5_ptr = key->rp5;
|
||||
do{
|
||||
rp1 = pgm_read_byte(r1_ptr++);
|
||||
rp5 = pgm_read_byte(r5_ptr++);
|
||||
byteindex = rp1>>3;
|
||||
bitindex = 0x80 >> (rp1&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
h1[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
|
||||
byteindex = rp5>>3;
|
||||
bitindex = 0x80 >> (rp5&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
result[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
bitindex_d >>= 1;
|
||||
if(bitindex_d==0){
|
||||
++byteindex_d;
|
||||
bitindex_d = 0x80;
|
||||
}
|
||||
}while(--j);
|
||||
|
||||
for (j=0; j<20; j++){
|
||||
result[j] ^= h1[j] ^ h1[pgm_read_byte(j+mod20_table)]
|
||||
^ h1[pgm_read_byte(8+j+mod20_table)]
|
||||
^ h1[pgm_read_byte(12+j+mod20_table)];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fetch_bit:
|
||||
lpm r0, Z+
|
||||
mov r28, r0
|
||||
ldi r29, 0x80
|
||||
andi r28, 7
|
||||
breq 3f
|
||||
2: lsr r29
|
||||
dec r28
|
||||
brne 2b
|
||||
3: mov r28, r0
|
||||
lsr r28
|
||||
lsr r28
|
||||
lsr r28
|
||||
mov r0, r29
|
||||
clr r29
|
||||
add r28, r24
|
||||
adc r29, r25
|
||||
ld r28, Y
|
||||
clt
|
||||
and r28, r0
|
||||
breq 4f
|
||||
set
|
||||
4: ret
|
||||
|
||||
xres_0 = 18
|
||||
xres_1 = 19
|
||||
h_0 = 20
|
||||
h_1 = 21
|
||||
xrp5_0 = 22
|
||||
xrp5_1 = 23
|
||||
inp_0 = 24
|
||||
inp_1 = 25
|
||||
tmp_0 = 22
|
||||
tmp_1 = 23
|
||||
tmp_2 = 24
|
||||
tmp_3 = 25
|
||||
tmp_4 = 18
|
||||
|
||||
/*
|
||||
param input_bytes: r24:r25
|
||||
param result: r22:r23
|
||||
param key: r20:r21
|
||||
*/
|
||||
;.global mqq_inv_affine_transformation
|
||||
mqq_inv_affine_transformation:
|
||||
push r17
|
||||
; push r28
|
||||
; push r29
|
||||
stack_alloc 20
|
||||
adiw r30, 1 /* Z points to stack space for h1 */
|
||||
movw r28, r20 /* Y points to the key struct in RAM */
|
||||
movw xres_0, r22
|
||||
movw r26, r30 /* X points to h1[0] */
|
||||
ldd xrp5_0, Y+8 /* load pointer rp5 to xrp5 */
|
||||
ldd xrp5_1, Y+9
|
||||
movw h_0, r30
|
||||
ldd r30, Y+6 /* load pointer to rp1 in Z */
|
||||
ldd r31, Y+7
|
||||
ldi r17, 20
|
||||
20: rcall fetch_bit
|
||||
bld r1, 7
|
||||
rcall fetch_bit
|
||||
bld r1, 6
|
||||
rcall fetch_bit
|
||||
bld r1, 5
|
||||
rcall fetch_bit
|
||||
bld r1, 4
|
||||
rcall fetch_bit
|
||||
bld r1, 3
|
||||
rcall fetch_bit
|
||||
bld r1, 2
|
||||
rcall fetch_bit
|
||||
bld r1, 1
|
||||
rcall fetch_bit
|
||||
bld r1, 0
|
||||
st X+, r1
|
||||
dec r17
|
||||
brne 20b
|
||||
;----
|
||||
movw r26, xres_0 /* X points to result */
|
||||
movw r30, xrp5_0
|
||||
ldi r17, 20
|
||||
20: rcall fetch_bit
|
||||
bld r1, 7
|
||||
rcall fetch_bit
|
||||
bld r1, 6
|
||||
rcall fetch_bit
|
||||
bld r1, 5
|
||||
rcall fetch_bit
|
||||
bld r1, 4
|
||||
rcall fetch_bit
|
||||
bld r1, 3
|
||||
rcall fetch_bit
|
||||
bld r1, 2
|
||||
rcall fetch_bit
|
||||
bld r1, 1
|
||||
rcall fetch_bit
|
||||
bld r1, 0
|
||||
st X+, r1
|
||||
dec r17
|
||||
brne 20b
|
||||
clr r1
|
||||
; --- now we mix result with h1
|
||||
sbiw r26, 20 /* adjusting X to point at result[0] */
|
||||
movw tmp_2, h_0
|
||||
ldi r30, lo8(affine_mix_lut)
|
||||
ldi r31, hi8(affine_mix_lut)
|
||||
ldi r17, 20
|
||||
30:
|
||||
ld tmp_0, X
|
||||
movw r28, tmp_2
|
||||
ld tmp_1, Y+
|
||||
movw tmp_2, r28
|
||||
eor tmp_0, tmp_1
|
||||
movw r28, h_0
|
||||
lpm r0, Z+
|
||||
mov tmp_4, r0
|
||||
andi tmp_4, 0x0f
|
||||
add r28, tmp_4
|
||||
adc r29, r1
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
adiw r28, 4
|
||||
sbrc r0, 7
|
||||
adiw r28, 4
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
adiw r28, 4
|
||||
sbrc r0, 6
|
||||
adiw r28, 4
|
||||
ld tmp_1, Y
|
||||
eor tmp_0, tmp_1
|
||||
st X+, tmp_0
|
||||
dec r17
|
||||
brne 30b
|
||||
|
||||
stack_free 20
|
||||
; pop r29
|
||||
; pop r28
|
||||
pop r17
|
||||
ret
|
||||
|
||||
affine_mix_lut:
|
||||
.byte 0x84, 0x85, 0x86, 0x87
|
||||
.byte 0xC0, 0xC1, 0xC2, 0xC3
|
||||
.byte 0x40, 0x41, 0x42, 0x43
|
||||
.byte 0x44, 0x45, 0x46, 0x47
|
||||
.byte 0x80, 0x81, 0x82, 0x83
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
xres = 20
|
||||
tmp_0 = 23
|
||||
tmp_1 = 22
|
||||
tmp_2 = 21
|
||||
tmp_3 = 19
|
||||
/*
|
||||
param i: r24
|
||||
param b1: r22
|
||||
param b2: r20
|
||||
param key: r18:r19
|
||||
*/
|
||||
;.global mqq_q
|
||||
mqq_q:
|
||||
; push r28
|
||||
; push r29
|
||||
; stack_alloc 25, r26, r27
|
||||
; adiw r26, 1 /* X points to e[0] */
|
||||
movw r28, r18
|
||||
sbrs r24, 0
|
||||
adiw r28, 2
|
||||
ldd r30, Y+2
|
||||
ldd r31, Y+3
|
||||
ldi r28, 9
|
||||
10: lpm r0, Z+
|
||||
st X+, r0
|
||||
dec r28
|
||||
brne 10b
|
||||
sbiw r26, 9 /* adjust X to point at e[0] */
|
||||
;---
|
||||
movw r28, r18
|
||||
ld r30, Y+ /* Z points to a[0] in progmem */
|
||||
ld r31, Y
|
||||
sbrs r24, 0
|
||||
rjmp 40f
|
||||
20:
|
||||
sbrs r22, 7
|
||||
rjmp 30f
|
||||
ldi r25, 9
|
||||
movw r28, r30
|
||||
25: lpm r0, Z
|
||||
adiw r30, 9
|
||||
ld r24, X
|
||||
eor r24, r0
|
||||
st X+, r24
|
||||
dec r25
|
||||
brne 25b
|
||||
movw r30, r28
|
||||
sbiw r26, 9
|
||||
30:
|
||||
adiw r30, 1
|
||||
lsl r22
|
||||
breq 60f
|
||||
rjmp 20b
|
||||
40:
|
||||
sbrs r22, 7
|
||||
rjmp 50f
|
||||
ldi r25, 9
|
||||
movw r28, r30
|
||||
45: lpm r0, Z+
|
||||
ld r24, X
|
||||
eor r24, r0
|
||||
st X+, r24
|
||||
dec r25
|
||||
brne 45b
|
||||
movw r30, r28
|
||||
sbiw r26, 9
|
||||
50:
|
||||
adiw r30, 9
|
||||
lsl r22
|
||||
breq 60f
|
||||
rjmp 40b
|
||||
60:
|
||||
;------ all inputs are consumed, X points at e[0]
|
||||
;------ So we finished with obtaining e0 .. e7 and e8
|
||||
movw r28, r26
|
||||
ldd r0, Y+8
|
||||
eor xres, r0
|
||||
;---
|
||||
|
||||
/*
|
||||
We can look at the bits of e0 .. e7 as a columns of a given matrix. We want to define 8 variables that have the rows
|
||||
of that matrix. The variables need to be 16-bit because we will put into the upper 8 bits the bits of e0 .. e7,
|
||||
and the bits of the variable result will be the Least Significant Bits of a[0] ... a[7].
|
||||
*/
|
||||
adiw r28, 9 /* Y points at a[0] */
|
||||
ldi r25, 8
|
||||
63:
|
||||
ldi r24, 8
|
||||
clr tmp_0
|
||||
65: ld tmp_1, X
|
||||
lsl tmp_1
|
||||
st X+, tmp_1
|
||||
rol tmp_0
|
||||
dec r24
|
||||
brne 65b
|
||||
;---
|
||||
clr tmp_1
|
||||
lsl xres
|
||||
rol tmp_1
|
||||
st Y+, tmp_1
|
||||
st Y+, tmp_0
|
||||
sbiw r26, 8
|
||||
dec r25
|
||||
brne 63b
|
||||
;------- First we apply upper triangular transformation
|
||||
sbiw r28, 16 /* Y points at a[0] */
|
||||
movw r30, r28 /* Z points at a[0] */
|
||||
|
||||
col = 25
|
||||
ldi r24, 8
|
||||
clr col
|
||||
70:
|
||||
mov r1, col
|
||||
ldi tmp_3, 0x80
|
||||
tst r1
|
||||
breq 72f
|
||||
71: lsr tmp_3
|
||||
dec r1
|
||||
brne 71b
|
||||
72:
|
||||
clt
|
||||
movw r28, r30 /* Y points at a[row]*/
|
||||
73: ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
brne 74f
|
||||
set
|
||||
adiw r28, 2
|
||||
rjmp 73b
|
||||
74:
|
||||
/* Y points at a[row] */
|
||||
/* if T is set we have to permute [Y] and [Z] */
|
||||
brtc 75f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
st Y, tmp_1
|
||||
st Z, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
std Y+1, tmp_1
|
||||
std Z+1, tmp_0
|
||||
75: /* permutation done */
|
||||
ldi r26, 7
|
||||
sub r26, col
|
||||
breq 78f
|
||||
movw r28, r30
|
||||
76: adiw r28, 2
|
||||
ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
breq 77f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
eor tmp_0, tmp_1
|
||||
st Y, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
eor tmp_0, tmp_1
|
||||
std Y+1, tmp_0
|
||||
77:
|
||||
dec r26
|
||||
brne 76b
|
||||
78:
|
||||
adiw r30, 2
|
||||
inc col
|
||||
dec r24
|
||||
brne 70b
|
||||
79:
|
||||
;------ Then we eliminate 1s above the main diagonal
|
||||
|
||||
ldi col, 7
|
||||
ldi tmp_3, 1
|
||||
sbiw r30, 2
|
||||
80:
|
||||
movw r28, r30
|
||||
mov r26, col
|
||||
81:
|
||||
sbiw r28, 2
|
||||
ldd tmp_0, Y+1
|
||||
and tmp_0, tmp_3
|
||||
breq 82f
|
||||
ld tmp_0, Y
|
||||
ld tmp_1, Z
|
||||
eor tmp_0, tmp_1
|
||||
st Y, tmp_0
|
||||
ldd tmp_0, Y+1
|
||||
ldd tmp_1, Z+1
|
||||
eor tmp_0, tmp_1
|
||||
std Y+1, tmp_0
|
||||
82:
|
||||
dec r26
|
||||
brne 81b
|
||||
sbiw r30, 2
|
||||
lsl tmp_3
|
||||
dec col
|
||||
brne 80b
|
||||
89:
|
||||
;------ The result is in the Least Significant Bits of a[0] ... a[7]
|
||||
/* Z should point at a[0] */
|
||||
ldi r25, 8
|
||||
clr r24
|
||||
90:
|
||||
ld tmp_0, Z
|
||||
adiw r30, 2
|
||||
lsr tmp_0
|
||||
rol r24
|
||||
dec r25
|
||||
brne 90b
|
||||
mqq_q_exit:
|
||||
; stack_free 25
|
||||
; pop r29
|
||||
; pop r28
|
||||
ret
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
param dest: r24:r25
|
||||
param hash: r22:r23
|
||||
param key: r20:r21
|
||||
*/
|
||||
|
||||
dest_0 = 2
|
||||
dest_1 = 3
|
||||
xr1_0 = 4
|
||||
xr1_1 = 5
|
||||
key_0 = 6
|
||||
key_1 = 7
|
||||
i = 8
|
||||
c = 9
|
||||
qstack_0 = 10
|
||||
qstack_1 = 11
|
||||
|
||||
.global mqq160_sign_P
|
||||
mqq160_sign_P:
|
||||
push_range 2, 11
|
||||
push_range 28, 29
|
||||
stack_alloc 10+20, r26, r27 /* r1[20] + key */
|
||||
adiw r26, 1 /* X points to stack memory */
|
||||
movw key_0, r26
|
||||
/* load key structure */
|
||||
movw r30, r20
|
||||
ldi r18, 10
|
||||
10: lpm r0, Z+
|
||||
st X+, r0
|
||||
dec r18
|
||||
brne 10b
|
||||
movw xr1_0, r26
|
||||
movw dest_0, r24
|
||||
/* call to mqq_inv_affine_transformation(hash, dest, &key); */
|
||||
movw r24, r22
|
||||
movw r22, dest_0
|
||||
movw r20, key_0
|
||||
rcall mqq_inv_affine_transformation
|
||||
/* r1[0]=((uint8_t*)dest)[0]; */
|
||||
|
||||
movw r26, dest_0
|
||||
movw r30, xr1_0
|
||||
ld r0, X
|
||||
st Z, r0
|
||||
;----
|
||||
ldi r18, 19
|
||||
mov c, r18
|
||||
clr i
|
||||
inc i
|
||||
stack_alloc 25, r28, r29
|
||||
adiw r28, 1
|
||||
movw qstack_0, r28
|
||||
20: mov r24, i
|
||||
movw r26, xr1_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
sbiw r26, 1
|
||||
ld r22, X
|
||||
movw r26, dest_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
ld r20, X
|
||||
movw r18, key_0
|
||||
movw r26, qstack_0
|
||||
rcall mqq_q
|
||||
movw r26, xr1_0
|
||||
add r26, i
|
||||
adc r27, r1
|
||||
st X, r24
|
||||
inc i
|
||||
dec c
|
||||
brne 20b
|
||||
stack_free 25
|
||||
;-----
|
||||
|
||||
|
||||
movw r28, key_0
|
||||
ldd r30, Y+8
|
||||
ldd r31, Y+9
|
||||
movw r26, xr1_0
|
||||
ldi r18, 20
|
||||
30: lpm r20, Z+
|
||||
swap r20
|
||||
andi r20, 0xF0
|
||||
lpm r21, Z+
|
||||
andi r21, 0x0F
|
||||
or r20, r21
|
||||
ld r21, X
|
||||
eor r21, r20
|
||||
st X+, r21
|
||||
dec r18
|
||||
brne 30b
|
||||
;----
|
||||
|
||||
movw r24, xr1_0
|
||||
movw r22, dest_0
|
||||
movw r20, key_0
|
||||
rcall mqq_inv_affine_transformation
|
||||
stack_free 30
|
||||
pop_range 28, 29
|
||||
pop_range 2, 11
|
||||
ret
|
||||
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/* mqq160-sign.c */
|
||||
/*
|
||||
This file is part of the AVR-Crypto-Lib.
|
||||
Copyright (C) 2010 Danilo Gligoroski, 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/>.
|
||||
*/
|
||||
/*
|
||||
C code for MQQ160-SIGN suitable for 8-bit smart cards
|
||||
|
||||
It is supposed that the private key is "engraved" in
|
||||
the ROM of the smart card - thus it is here stored as
|
||||
predefined const arrays in "MQQ160-SIGN-PrivateKey.h"
|
||||
|
||||
Programmed by Danilo Gligoroski, 18 Mar 2010.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "memxor.h"
|
||||
#include "mqq160-sign.h"
|
||||
|
||||
/*
|
||||
This is just for testing purposes.
|
||||
It should be programmed in a more flexible way
|
||||
in the MQQ160-SIGN C Library.
|
||||
*/
|
||||
|
||||
|
||||
void mqq_inv_affine_transformation(uint8_t* input_bytes, uint8_t* result, const mqq160_sign_key_t* key);
|
||||
uint8_t mqq_q(uint8_t i, uint8_t b1, uint8_t b2, const mqq160_sign_key_t* key);
|
||||
|
||||
|
||||
#if 0
|
||||
static uint16_t MaskShort[8] = {0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100};
|
||||
|
||||
static uint8_t mqq_q(uint8_t i, uint8_t b1, uint8_t b2, const mqq160_sign_key_t* key){
|
||||
uint8_t e[9];
|
||||
uint16_t a[8];
|
||||
uint8_t result, column, row, k;
|
||||
int8_t j;
|
||||
uint16_t temp;
|
||||
uint8_t *tmp_ptr=key->a;
|
||||
if(i&1){
|
||||
memcpy_P(e, key->cc1, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor_idx_P((uint8_t*)e, tmp_ptr, 9, 9);
|
||||
}
|
||||
tmp_ptr++;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}else{
|
||||
memcpy_P(e, key->cc2, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor_P((uint8_t*)e, tmp_ptr, 9);
|
||||
}
|
||||
tmp_ptr+=9;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}
|
||||
/* So we finished with obtaining e0 .. e7 and e8 */
|
||||
|
||||
/* We XOR e[8] with b2 and that will be initial value to transform in order to solve a linear system of equations */
|
||||
result=b2 ^ e[8];
|
||||
|
||||
/*
|
||||
We can look at the bits of e0 .. e7 as a columns of a given matrix. We want to define 8 variables that have the rows
|
||||
of that matrix. The variables need to be 16-bit because we will put into the upper 8 bits the bits of e0 .. e7,
|
||||
and the bits of the variable result will be the Least Significant Bits of a[0] ... a[7].
|
||||
*/
|
||||
for(j=0; j<8; ++j){
|
||||
row = 0;
|
||||
for(k=0; k<8; ++k){
|
||||
row |= (e[k]&0x80)>>(k);
|
||||
e[k]<<=1;
|
||||
}
|
||||
a[j]=(((uint16_t)row)<<8) | (result>>7);
|
||||
result <<= 1;
|
||||
}
|
||||
|
||||
/* Now we finally realize Gausian elimination */
|
||||
|
||||
/* First we apply upper triangular transformation */
|
||||
for(column=0; column<8; column++)
|
||||
{
|
||||
row=column;
|
||||
while ((a[row] & MaskShort[column]) == 0){
|
||||
row++;
|
||||
}
|
||||
if(row>column)
|
||||
{
|
||||
temp=a[column];
|
||||
a[column]=a[row];
|
||||
a[row]=temp;
|
||||
}
|
||||
for (j=column+1; j<8; j++)
|
||||
if ((a[j]&MaskShort[column]) !=0)
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
|
||||
/* Then we eliminate 1s above the main diagonal */
|
||||
for (column=7; column>0; column--){
|
||||
for (j=column-1; j>=0; j--){
|
||||
if ((a[j]&MaskShort[column]) !=0){
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* The result is in the Least Significant Bits of a[0] ... a[7] */
|
||||
result = 0;
|
||||
for(j=0; j<8; ++j){
|
||||
result <<=1;
|
||||
result |= a[j]&1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void mqq160_sign_P(void* dest, const void* hash, const mqq160_sign_key_t* key_P){
|
||||
uint8_t i, r1[20], byteindex;
|
||||
mqq160_sign_key_t key;
|
||||
|
||||
memcpy_P(&key, key_P, sizeof(mqq160_sign_key_t));
|
||||
|
||||
mqq_inv_affine_transformation((uint8_t*)hash, (uint8_t*)dest, &key);
|
||||
r1[0]=((uint8_t*)dest)[0];
|
||||
for(i=1; i<20; ++i){
|
||||
r1[i] = mqq_q(i, r1[i-1], ((uint8_t*)dest)[i], &key);
|
||||
}
|
||||
/*
|
||||
Affine transformation is just for the second call. The constant is extracted
|
||||
from the 4 LSBs of the first 40 bytes of RP5[] and xor-ed to input_bytes[].
|
||||
*/
|
||||
byteindex = 0;
|
||||
for (i=0; i<20; i++){
|
||||
r1[i] ^= (uint8_t)(pgm_read_byte(key.rp5+byteindex)<<4)
|
||||
| (uint8_t)(pgm_read_byte(key.rp5+byteindex+1)&0x0F);
|
||||
byteindex += 2;
|
||||
}
|
||||
mqq_inv_affine_transformation(r1, (uint8_t*)dest, &key);
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/* mqq160-sign.c */
|
||||
/*
|
||||
This file is part of the AVR-Crypto-Lib.
|
||||
Copyright (C) 2010 Danilo Gligoroski, 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/>.
|
||||
*/
|
||||
/*
|
||||
C code for MQQ160-SIGN suitable for 8-bit smart cards
|
||||
|
||||
It is supposed that the private key is "engraved" in
|
||||
the ROM of the smart card - thus it is here stored as
|
||||
predefined const arrays in "MQQ160-SIGN-PrivateKey.h"
|
||||
|
||||
Programmed by Danilo Gligoroski, 18 Mar 2010.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "memxor.h"
|
||||
#include "mqq160-sign.h"
|
||||
|
||||
static uint8_t mod20_table[32] PROGMEM = {
|
||||
4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
};
|
||||
|
||||
static void memxor_P(void* dest, const void* src, uint16_t length){
|
||||
while(length--){
|
||||
*((uint8_t*)dest) ^= pgm_read_byte(src);
|
||||
dest = (uint8_t*)dest +1;
|
||||
src = (uint8_t*)src +1;
|
||||
}
|
||||
}
|
||||
|
||||
static void memxor_idx_P(uint8_t* dest, const uint8_t* src, uint16_t length, uint8_t dist){
|
||||
while(length--){
|
||||
*((uint8_t*)dest) ^= pgm_read_byte((uint8_t*)src);
|
||||
dest = (uint8_t*)dest + 1;
|
||||
src = (uint8_t*)src + dist;
|
||||
}
|
||||
}
|
||||
/*
|
||||
This is just for testing purposes.
|
||||
It should be programmed in a more flexible way
|
||||
in the MQQ160-SIGN C Library.
|
||||
*/
|
||||
|
||||
static void mqq_inv_affine_transformation(uint8_t* input_bytes, uint8_t* result, const mqq160_sign_key_t* key){
|
||||
/* The matrix SInv is given as two permutations of 160 elements. */
|
||||
uint8_t j, byteindex, bitindex, bitindex_d, byteindex_d, rp1, rp5;
|
||||
uint8_t *r1_ptr, *r5_ptr;
|
||||
uint8_t h1[20];
|
||||
|
||||
/* Initialize H1 and H2 = 0 */
|
||||
memset(h1, 0, 20);
|
||||
memset(result, 0, 20);
|
||||
|
||||
/*
|
||||
Fill H1 with bits of InputBytes accordingly to RP1 permutation
|
||||
and fill H2 with bits of InputBytes accordingly to RP5 permutation
|
||||
*/
|
||||
bitindex_d = 0x80;
|
||||
byteindex_d = 0;
|
||||
j=160;
|
||||
r1_ptr = key->rp1;
|
||||
r5_ptr = key->rp5;
|
||||
do{
|
||||
rp1 = pgm_read_byte(r1_ptr++);
|
||||
rp5 = pgm_read_byte(r5_ptr++);
|
||||
byteindex = rp1>>3;
|
||||
bitindex = 0x80 >> (rp1&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
h1[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
|
||||
byteindex = rp5>>3;
|
||||
bitindex = 0x80 >> (rp5&0x07);
|
||||
if (input_bytes[byteindex] & bitindex){
|
||||
result[byteindex_d] ^= bitindex_d;
|
||||
}
|
||||
bitindex_d >>= 1;
|
||||
if(bitindex_d==0){
|
||||
++byteindex_d;
|
||||
bitindex_d = 0x80;
|
||||
}
|
||||
}while(--j);
|
||||
|
||||
for (j=0; j<20; j++){
|
||||
result[j] ^= h1[j] ^ h1[pgm_read_byte(j+mod20_table)]
|
||||
^ h1[pgm_read_byte(8+j+mod20_table)]
|
||||
^ h1[pgm_read_byte(12+j+mod20_table)];
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t MaskShort[8] = {0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100};
|
||||
|
||||
static uint8_t mqq_q(uint8_t i, uint8_t b1, uint8_t b2, const mqq160_sign_key_t* key){
|
||||
uint8_t e[9];
|
||||
uint16_t a[8];
|
||||
uint8_t result, column, row, k;
|
||||
int8_t j;
|
||||
uint16_t temp;
|
||||
uint8_t *tmp_ptr=key->a;
|
||||
if(i&1){
|
||||
memcpy_P(e, key->cc1, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor_idx_P((uint8_t*)e, tmp_ptr, 9, 9);
|
||||
}
|
||||
tmp_ptr++;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}else{
|
||||
memcpy_P(e, key->cc2, 9);
|
||||
while(b1){
|
||||
if(b1&0x80){
|
||||
memxor_P((uint8_t*)e, tmp_ptr, 9);
|
||||
}
|
||||
tmp_ptr+=9;
|
||||
b1 <<= 1;
|
||||
}
|
||||
}
|
||||
/* So we finished with obtaining e0 .. e7 and e8 */
|
||||
|
||||
/* We XOR e[8] with b2 and that will be initial value to transform in order to solve a linear system of equations */
|
||||
result=b2 ^ e[8];
|
||||
|
||||
/*
|
||||
We can look at the bits of e0 .. e7 as a columns of a given matrix. We want to define 8 variables that have the rows
|
||||
of that matrix. The variables need to be 16-bit because we will put into the upper 8 bits the bits of e0 .. e7,
|
||||
and the bits of the variable result will be the Least Significant Bits of a[0] ... a[7].
|
||||
*/
|
||||
for(j=0; j<8; ++j){
|
||||
row = 0;
|
||||
for(k=0; k<8; ++k){
|
||||
row |= (e[k]&0x80)>>(k);
|
||||
e[k]<<=1;
|
||||
}
|
||||
a[j]=(((uint16_t)row)<<8) | (result>>7);
|
||||
result <<= 1;
|
||||
}
|
||||
|
||||
/* Now we finally realize Gausian elimination */
|
||||
|
||||
/* First we apply upper triangular transformation */
|
||||
for(column=0; column<8; column++)
|
||||
{
|
||||
row=column;
|
||||
while ((a[row] & MaskShort[column]) == 0){
|
||||
row++;
|
||||
}
|
||||
if(row>column)
|
||||
{
|
||||
temp=a[column];
|
||||
a[column]=a[row];
|
||||
a[row]=temp;
|
||||
}
|
||||
for (j=column+1; j<8; j++)
|
||||
if ((a[j]&MaskShort[column]) !=0)
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
|
||||
/* Then we eliminate 1s above the main diagonal */
|
||||
for (column=7; column>0; column--){
|
||||
for (j=column-1; j>=0; j--){
|
||||
if ((a[j]&MaskShort[column]) !=0){
|
||||
a[j] ^= a[column];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* The result is in the Least Significant Bits of a[0] ... a[7] */
|
||||
result = 0;
|
||||
for(j=0; j<8; ++j){
|
||||
result <<=1;
|
||||
result |= a[j]&1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void mqq160_sign_P(void* dest, const void* hash, const mqq160_sign_key_t* key_P){
|
||||
uint8_t i, r1[20], byteindex;
|
||||
mqq160_sign_key_t key;
|
||||
memcpy_P(&key, key_P, sizeof(mqq160_sign_key_t));
|
||||
mqq_inv_affine_transformation((uint8_t*)hash, (uint8_t*)dest, &key);
|
||||
r1[0]=((uint8_t*)dest)[0];
|
||||
for(i=1; i<20; ++i){
|
||||
r1[i] = mqq_q(i, r1[i-1], ((uint8_t*)dest)[i], &key);
|
||||
}
|
||||
/*
|
||||
Affine transformation is just for the second call. The constant is extracted
|
||||
from the 4 LSBs of the first 40 bytes of RP5[] and xor-ed to input_bytes[].
|
||||
*/
|
||||
byteindex = 0;
|
||||
for (i=0; i<20; i++){
|
||||
r1[i] ^= (uint8_t)(pgm_read_byte(key.rp5+byteindex)<<4)
|
||||
| (uint8_t)(pgm_read_byte(key.rp5+byteindex+1)&0x0F);
|
||||
byteindex += 2;
|
||||
}
|
||||
mqq_inv_affine_transformation(r1, (uint8_t*)dest, &key);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* mqq160-sign.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 MQQ160SIGN_P_H_
|
||||
#define MQQ160SIGN_P_H_
|
||||
|
||||
#include "mqq160-sign.h"
|
||||
|
||||
void mqq160_sign_P(void* dest, const void* hash, const mqq160_sign_key_t* key_P);
|
||||
|
||||
#endif /* MQQ160SIGN_P_H_ */
|
|
@ -0,0 +1,113 @@
|
|||
/* mqq160-sign_testkey.c */
|
||||
/*
|
||||
This file is part of the AVR-Crypto-Lib.
|
||||
Copyright (C) 2010 Danilo Gligoroski, 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/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "mqq160-sign.h"
|
||||
#include "mqq160-sign_testkey.h"
|
||||
|
||||
/*
|
||||
This is the private key of MQQ defined by one
|
||||
quadratic quasigroup of order 2^8 given as 81 uint8_ts
|
||||
and one nonsingular matrix SInv given as two arrays
|
||||
RP1[] and RP5[] of 160 uint8_ts.
|
||||
*/
|
||||
|
||||
|
||||
static uint8_t a[9*9-1] PROGMEM =
|
||||
{ 171, 171, 165, 56, 121, 136, 79, 108, 2,
|
||||
255, 255, 165, 108, 45, 220, 79, 108, 88,
|
||||
54, 108, 103, 21, 74, 119, 141, 204, 221,
|
||||
210, 220, 30, 201, 215, 199, 74, 95, 173,
|
||||
165, 241, 160, 190, 38, 134, 68, 103, 140,
|
||||
84, 84, 68, 157, 81, 65, 30, 11, 48,
|
||||
136, 136, 79, 21, 136, 199, 79, 0, 171,
|
||||
136, 210, 27, 27, 220, 157, 65, 84, 45,
|
||||
225, 61, 8, 232, 235, 49, 22, 146 };
|
||||
|
||||
|
||||
static uint8_t cc1[9] PROGMEM = { 2, 88, 221, 173, 140, 48, 171, 45, 252 };
|
||||
static uint8_t cc2[9] PROGMEM = {225, 61, 8, 232, 235, 49, 22, 146, 252 };
|
||||
|
||||
/* The matrix SInv is stored in ROM as two onedimensional
|
||||
arrays RP1[] and RP5[] of 160 uint8_ts */
|
||||
static uint8_t rp1[160] PROGMEM = {
|
||||
111, 137, 49, 134, 9, 116, 11, 52, 43, 55,
|
||||
74, 130, 119, 144, 31, 7, 72, 79, 105, 59,
|
||||
57, 120, 50, 94, 141, 135, 149, 44, 109, 100,
|
||||
113, 1, 143, 126, 117, 37, 65, 67, 152, 107,
|
||||
10, 98, 15, 23, 138, 19, 121, 18, 28, 156,
|
||||
123, 106, 48, 29, 97, 34, 85, 157, 64, 3,
|
||||
60, 35, 24, 32, 108, 147, 158, 21, 129, 84,
|
||||
5, 70, 118, 112, 30, 68, 47, 40, 150, 13,
|
||||
61, 73, 132, 22, 95, 153, 4, 76, 87, 114,
|
||||
127, 62, 27, 36, 125, 45, 142, 39, 101, 63,
|
||||
88, 96, 12, 115, 82, 91, 159, 93, 155, 154,
|
||||
148, 110, 25, 0, 41, 20, 54, 26, 14, 83,
|
||||
81, 80, 131, 33, 78, 77, 124, 104, 133, 17,
|
||||
145, 139, 122, 102, 42, 56, 75, 66, 2, 16,
|
||||
86, 140, 71, 136, 69, 99, 58, 6, 92, 90,
|
||||
8, 103, 128, 38, 46, 146, 89, 151, 51, 53 };
|
||||
|
||||
static uint8_t rp5[160] PROGMEM = {
|
||||
90, 113, 130, 115, 132, 27, 46, 72, 33, 50,
|
||||
35, 136, 42, 148, 146, 143, 116, 158, 98, 41,
|
||||
39, 5, 54, 86, 106, 56, 30, 138, 80, 44,
|
||||
91, 49, 1, 149, 159, 101, 74, 9, 110, 131,
|
||||
25, 51, 123, 76, 104, 28, 82, 140, 2, 108,
|
||||
120, 144, 10, 145, 124, 119, 62, 57, 117, 121,
|
||||
17, 73, 105, 69, 155, 7, 154, 75, 100, 141,
|
||||
157, 38, 14, 60, 47, 112, 95, 85, 43, 93,
|
||||
24, 12, 4, 71, 81, 13, 94, 68, 107, 67,
|
||||
142, 150, 61, 6, 122, 26, 139, 59, 102, 153,
|
||||
109, 48, 103, 65, 23, 92, 87, 40, 135, 133,
|
||||
129, 134, 8, 55, 83, 125, 31, 96, 147, 36,
|
||||
0, 126, 70, 64, 20, 11, 137, 78, 89, 58,
|
||||
21, 114, 127, 111, 99, 34, 152, 79, 66, 97,
|
||||
22, 15, 151, 32, 84, 37, 77, 88, 16, 29,
|
||||
3, 128, 118, 18, 156, 19, 52, 45, 53, 63 };
|
||||
|
||||
mqq160_sign_key_t testkey_P PROGMEM = {a, cc1, cc2, rp1, rp5 };
|
||||
|
||||
void mqq_load_pgm_key(void* buffer, mqq160_sign_key_t* key, const mqq160_sign_key_t* key_P){
|
||||
uint8_t *buf_ptr;
|
||||
buf_ptr = buffer;
|
||||
memcpy_P(key, key_P, sizeof(mqq160_sign_key_t));
|
||||
|
||||
memcpy_P(buf_ptr, key->a, MQQ160SIGN_A_SIZE);
|
||||
key->a = buf_ptr;
|
||||
buf_ptr += MQQ160SIGN_A_SIZE;
|
||||
|
||||
memcpy_P(buf_ptr, key->cc1, MQQ160SIGN_CC1_SIZE);
|
||||
key->cc1 = buf_ptr;
|
||||
buf_ptr += MQQ160SIGN_CC1_SIZE;
|
||||
|
||||
memcpy_P(buf_ptr, key->cc2, MQQ160SIGN_CC2_SIZE);
|
||||
key->cc2 = buf_ptr;
|
||||
buf_ptr += MQQ160SIGN_CC2_SIZE;
|
||||
|
||||
memcpy_P(buf_ptr, key->rp1, MQQ160SIGN_RP1_SIZE);
|
||||
key->rp1 = buf_ptr;
|
||||
buf_ptr += MQQ160SIGN_RP1_SIZE;
|
||||
|
||||
memcpy_P(buf_ptr, key->rp5, MQQ160SIGN_RP5_SIZE);
|
||||
key->rp5 = buf_ptr;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* mqq160-sign_testkey.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 MQQ160SIGN_TESTKEY_H_
|
||||
#define MQQ160SIGN_TESTKEY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MQQ160SIGN_A_SIZE 80
|
||||
#define MQQ160SIGN_RP1_SIZE 160
|
||||
#define MQQ160SIGN_RP5_SIZE 160
|
||||
#define MQQ160SIGN_CC1_SIZE 9
|
||||
#define MQQ160SIGN_CC2_SIZE 9
|
||||
#define MQQ160SIGN_KEY_SIZE (9+9+160+160+80)
|
||||
|
||||
/*
|
||||
This is the private key of MQQ defined by one
|
||||
quadratic quasigroup of order 2^8 given as 81 uint8_ts
|
||||
and one nonsingular matrix SInv given as two arrays
|
||||
RP1[] and RP5[] of 160 uint8_ts.
|
||||
*/
|
||||
extern mqq160_sign_key_t testkey_P;
|
||||
|
||||
void mqq_load_pgm_key(void* buffer, mqq160_sign_key_t* key, const mqq160_sign_key_t* key_P);
|
||||
|
||||
#endif /* MQQ160SIGN_TESTKEY_H_ */
|
|
@ -61,6 +61,7 @@ uint8_t cli_getsn(char* s, uint16_t n);
|
|||
uint8_t cli_getsn_cecho(char* s, uint16_t n);
|
||||
void cli_putstr(const char* s);
|
||||
void cli_putstr_P(PGM_P s);
|
||||
void cli_hexdump_byte(uint8_t byte);
|
||||
void cli_hexdump(const void* data, uint16_t length);
|
||||
void cli_hexdump_rev(const void* data, uint16_t length);
|
||||
void cli_hexdump2(const void* data, uint16_t length);
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/* main-mqq160-sign-test.c */
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
/*
|
||||
* MQQ160-sign test-suit
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "uart_i.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "cli.h"
|
||||
#include "mqq160-sign.h"
|
||||
#include "mqq160-sign_P.h"
|
||||
#include "mqq160-sign_testkey.h"
|
||||
#include "performance_test.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "stack_measuring.h"
|
||||
|
||||
char* algo_name = "MQQ160-sign";
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* additional validation-functions *
|
||||
*****************************************************************************/
|
||||
uint8_t test_hash[20] PROGMEM =
|
||||
{
|
||||
(uint8_t)0x64, (uint8_t)0xFE, (uint8_t)0x2A, (uint8_t)0x85,
|
||||
(uint8_t)0xBB, (uint8_t)0x8C, (uint8_t)0x54, (uint8_t)0x5C,
|
||||
(uint8_t)0x65, (uint8_t)0x74, (uint8_t)0xA0, (uint8_t)0xF3,
|
||||
(uint8_t)0xD0, (uint8_t)0xAF, (uint8_t)0x96, (uint8_t)0xB9,
|
||||
(uint8_t)0x0F, (uint8_t)0x17, (uint8_t)0xF3, (uint8_t)0xAD
|
||||
};
|
||||
|
||||
void performance_mqq(void){
|
||||
uint8_t hash[20];
|
||||
uint8_t signature[20];
|
||||
long t;
|
||||
char str[3*sizeof(long)+2];
|
||||
uint8_t tmp;
|
||||
uint16_t s1, s2;
|
||||
stack_measuring_ctx_t smctx;
|
||||
memcpy_P(hash, test_hash, 20);
|
||||
|
||||
uint8_t key_buffer[MQQ160SIGN_KEY_SIZE];
|
||||
mqq160_sign_key_t key;
|
||||
mqq_load_pgm_key(key_buffer, &key, &testkey_P);
|
||||
|
||||
cli_putstr_P(PSTR("\r\n=== Performance of MQQ160-SIGN ==="));
|
||||
calibrateTimer();
|
||||
startTimer(0);
|
||||
START_TIMER;
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
STOP_TIMER;
|
||||
t = stopTimer();
|
||||
ltoa(t, str, 10);
|
||||
cli_putstr_P(PSTR("\r\n cycles for mqq160_sign_P: "));
|
||||
tmp = 12-strlen(str);
|
||||
while(tmp--){
|
||||
cli_putc(' ');
|
||||
}
|
||||
cli_putstr(str);
|
||||
|
||||
calibrateTimer();
|
||||
startTimer(0);
|
||||
START_TIMER;
|
||||
mqq160_sign(signature, hash, &key);
|
||||
STOP_TIMER;
|
||||
t = stopTimer();
|
||||
ltoa(t, str, 10);
|
||||
cli_putstr_P(PSTR("\r\n cycles for mqq160_sign: "));
|
||||
tmp = 12-strlen(str);
|
||||
while(tmp--){
|
||||
cli_putc(' ');
|
||||
}
|
||||
cli_putstr(str);
|
||||
|
||||
stack_measure_init(&smctx, 0xAA);
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
s1 = stack_measure_final(&smctx);
|
||||
stack_measure_init(&smctx, 0x55);
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
s2 = stack_measure_final(&smctx);
|
||||
s1 = (s1>s2)?s1:s2;
|
||||
ltoa((long)s1, str, 10);
|
||||
cli_putstr_P(PSTR("\r\n stack for mqq160_sign_P: "));
|
||||
tmp = 12-strlen(str);
|
||||
while(tmp--){
|
||||
cli_putc(' ');
|
||||
}
|
||||
cli_putstr(str);
|
||||
stack_measure_init(&smctx, 0xAA);
|
||||
mqq160_sign(signature, hash, &key);
|
||||
s1 = stack_measure_final(&smctx);
|
||||
stack_measure_init(&smctx, 0x55);
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
s2 = stack_measure_final(&smctx);
|
||||
s1 = (s1>s2)?s1:s2;
|
||||
ltoa((long)s1, str, 10);
|
||||
cli_putstr_P(PSTR("\r\n stack for mqq160_sign: "));
|
||||
tmp = 12-strlen(str);
|
||||
while(tmp--){
|
||||
cli_putc(' ');
|
||||
}
|
||||
cli_putstr(str);
|
||||
|
||||
cli_putstr_P(PSTR("\r\n=== End of performance figures ==="));
|
||||
}
|
||||
|
||||
void testrun_mqq_mem(void){
|
||||
uint8_t hash[20];
|
||||
uint8_t signature[20];
|
||||
memcpy_P(hash, test_hash, 20);
|
||||
|
||||
uint8_t key_buffer[MQQ160SIGN_KEY_SIZE];
|
||||
mqq160_sign_key_t key;
|
||||
mqq_load_pgm_key(key_buffer, &key, &testkey_P);
|
||||
mqq160_sign(signature, hash, &key);
|
||||
cli_putstr_P(PSTR("\r\ntest signature (RAM): "));
|
||||
cli_hexdump(signature, 20);
|
||||
}
|
||||
|
||||
void testrun_mqq_flash(void){
|
||||
uint8_t hash[20];
|
||||
uint8_t signature[20];
|
||||
memcpy_P(hash, test_hash, 20);
|
||||
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
cli_putstr_P(PSTR("\r\ntest signature (FLASH): "));
|
||||
cli_hexdump(signature, 20);
|
||||
}
|
||||
|
||||
void testrun_mqq(void){
|
||||
uint8_t hash[20];
|
||||
uint8_t signature[20];
|
||||
memcpy_P(hash, test_hash, 20);
|
||||
|
||||
uint8_t key_buffer[MQQ160SIGN_KEY_SIZE];
|
||||
mqq160_sign_key_t key;
|
||||
mqq_load_pgm_key(key_buffer, &key, &testkey_P);
|
||||
mqq160_sign(signature, hash, &key);
|
||||
cli_putstr_P(PSTR("\r\ntest signature (RAM): "));
|
||||
cli_hexdump(signature, 20);
|
||||
|
||||
mqq160_sign_P(signature, hash, &testkey_P);
|
||||
cli_putstr_P(PSTR("\r\ntest signature (FLASH): "));
|
||||
cli_hexdump(signature, 20);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* main *
|
||||
*****************************************************************************/
|
||||
|
||||
const char test_str[] PROGMEM = "test";
|
||||
const char test_flash_str[] PROGMEM = "flash";
|
||||
const char test_mem_str[] PROGMEM = "mem";
|
||||
const char performance_str[] PROGMEM = "performance";
|
||||
const char echo_str[] PROGMEM = "echo";
|
||||
|
||||
cmdlist_entry_t cmdlist[] PROGMEM = {
|
||||
{ test_str, NULL, testrun_mqq },
|
||||
{ test_flash_str, NULL, testrun_mqq_flash },
|
||||
{ test_mem_str, NULL, testrun_mqq_mem },
|
||||
{ performance_str, NULL, performance_mqq },
|
||||
{ echo_str, (void*)1, (void_fpt)echo_ctrl },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main (void){
|
||||
DEBUG_INIT();
|
||||
|
||||
cli_rx = (cli_rx_fpt)uart0_getc;
|
||||
cli_tx = (cli_tx_fpt)uart0_putc;
|
||||
for(;;){
|
||||
cli_putstr_P(PSTR("\r\n\r\nCrypto-VS ("));
|
||||
cli_putstr(algo_name);
|
||||
cli_putstr_P(PSTR("; "));
|
||||
cli_putstr(__DATE__);
|
||||
cli_putstr_P(PSTR(" "));
|
||||
cli_putstr(__TIME__);
|
||||
cli_putstr_P(PSTR(")\r\nloaded and running\r\n"));
|
||||
|
||||
cmd_interface(cmdlist);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue