changed arcfour api

This commit is contained in:
bg 2008-08-06 18:04:23 +00:00
parent b07fb998ba
commit c58f43feba
6 changed files with 171 additions and 50 deletions

View File

@ -66,8 +66,8 @@ email: daniel.otte@rub.de
3.2. *_init function
The *_init function generally takes a pointer to the key as first parameter.
For ciphers where the keysize is not fixed the second parameter gives the
keysize (in bits regularly) and the last parameter points to a context variable
to fill.
keysize (in bits regularly) and the last parameter points to the context
variable to fill.
For some ciphers there are additonal parameters like the number of rounds,
these parameters generally occur before the context pointer.

71
USAGE.streamciphers Normal file
View File

@ -0,0 +1,71 @@
====================================
= Usage of streamciphers =
====================================
Author: Daniel Otte
email: daniel.otte@rub.de
0. Foreword
This file will describe how to use the streramcipher implementations provided
by this library. It will not only show how to call the cryptographic functions
but also discuss a little how to build security mechanisms from that.
1. What a streamcipher does
A streamcipher normaly generates a deterministic, random looking stream of
bits, known as keystream. For encryption purpose this keystream is XORed with
the data stream. So decryption is exactly the same as encryption. The
datastream is XORed with the keystream giving the plaintext. So both sides need
exactly the same streamcipher in the same state.
1.1. high frequent parameters:
outputsize: 8 bit, 1 bit
keysize: 64 bit, 80 bit, 128 bit
IVsize: 64 bit
2. Parts of a streamcipher
* generation algorithm
* initialisation algorithm
* state
As we can see all streamciphers seem to utilize an internal state which
determines the output. This state is initialized by the initialisation
algorithm with a key and an IV (initialisation vector). It is very important
for security that _never_ the same key with the same IV is used again. The
IV is not required to be kept secret.
3. streamcipher API
The API is not always consistent due to the fact that we tried to optimize the
code for size (flash, heap and stack) and speed (runtime of the different
components).
Generally the API of the implemented streamciphers consists of:
*_init function, which implements the initialisation
*_gen function, which implements the streamcipher algorithm and generates a
keystream output
*_ctx_t context type, which contains internal state information
3.1 look at the prototypes
Generally the prototypes (defined in the *.h files) will tell you what
parameter means what.
3.1.2 sizes in bits and bytes
Working with cryptographical functions involves working with different lengths.
Some times you want to know it in bits and sometimes in bytes. To reduce
frustration and to avoid bugs we suffix a length parameter with either _b or _B
depending on the meaning. _b means in bits and _B means in bytes
(big b big word).
3.2. *_init function
The *_init function generally takes a pointer to the key as first parameter.
For ciphers where the keysize is not fixed the second parameter gives the
keysize (in bits regularly) followed by a pointer to the IV and a length
parameter for not fixed IV sizes (both are omitted if the algorithm does not
specify IV handling, in this case a part of the key should be used as IV).
The last parameter points to the context variable to fill.
3.3. *_gen function
The *_gen function updates the internal state to which a pointer is given as
parameter and returns a fixed length part of the keystream as return value.

View File

@ -26,68 +26,106 @@
*
*/
#include <avr/io.h>
.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 \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
sbiw r30, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
.endm
.macro stack_free size:req, reg1=r30, reg2=r31
in \reg1, _SFR_IO_ADDR(SPL)
in \reg2, _SFR_IO_ADDR(SPH)
adiw r30, \size
out _SFR_IO_ADDR(SPH), \reg2
out _SFR_IO_ADDR(SPL), \reg1
.endm
/* +---+---+---------------------+
* | i | j | ......<256>........ |
* +---+---+---------------------+
*/
.global arcfour_init
;== arcfour_init ==
; this function initialises the context
; param1: 16-bit pointer to a ctx struct
; given in r25,r24
; param2: 16-bit pointer to a key
; given in r23,r22
; param1: 8-bit integer indicating keylength in byte
; given in r20
/*
*== arcfour_init ==
* this function initialises the context
* param1: 16-bit pointer to the key
* given in r24:r25
* param2: 8-bit integer indicating keylength in byte
* given in r22
* param3: 16-bit pointer to a ctx struct
* given in r20:r21
*/
arcfour_init:
push r29
push r28
push r2
movw r26, r24 /* X points to ctx */
movw r30, r22 /* Z points to key */
push_ r2, r28, r29
movw r26, r20 /* X points to ctx */
movw r30, r24 /* Z points to key */
st X+, r1
st X+, r1 /* X points to S */
st X+, r1 /* X points to S */
movw r20, r26 /* store pointer to S in r21:r20 */
1:
st X+, r1
inc r1
brne 1b
adiw r24, 2 /* r24:r25 points to S */
clr r21 /* r21 is j */
mov r18, r20 /* r18 is keyindex counter */
movw r26, r20
clr r18 /* r18 is keyindex counter */
clr r0
clr r19
2:
movw r26, r24
ld r19, Z+
add r21, r19 /* j+= key[i%length] */
add r26, r1
adc r27, r0
ld r19, X
add r21, r19 /* j += S[i] */
dec r18 /* check the key-index counter */
brne 3f
movw r30, r22
mov r18, r20
3: /* now swap(S[i], S[j]) */ /* r19 is still S[i] */
movw r28, r24
add r28, r21
adc r29, r0 /* Y points to S[j]*/
ld r23, X
ld r2, Z+
add r19, r2
add r19, r23
movw r28, r20 /* load pointer to S in Y */
add r28, r19
adc r29, r1
ld r2, Y
st Y, r19
st X, r2
inc r1
st Y, r23
st X+, r2
inc r18
cp r18, r22
brne 3f
movw r30, r24
clr r18
3:
inc r0
brne 2b
pop r2
pop r28
pop r29
pop_ r29, r28, r2
ret
/*

View File

@ -33,15 +33,16 @@
* length is length of key in bytes!
*/
void arcfour_init(arcfour_ctx_t *ctx, void *key, uint8_t length_B){
void arcfour_init(const void *key, uint8_t length_B, arcfour_ctx_t *ctx){
uint8_t t;
unsigned x,y=0;
uint16_t x,y=0;
for(x=0; x<= 255; ++x)
ctx->s[x]=x;
for(x=0; x<= 255; ++x){
y += ctx->s[x] + ((uint8_t*)key)[x % length_B];
y &= 0xff;
/* ctx->s[y] <--> ctx->s[x] */
t = ctx->s[y];
ctx->s[y] = ctx->s[x];
ctx->s[x] = t;

View File

@ -74,7 +74,7 @@ typedef struct arcfour_ctx_st {
* \param length_B length of the key in bytes (between 1 and 255)
*/
void arcfour_init(arcfour_ctx_t *ctx, void *key, uint8_t length_B);
void arcfour_init(const void *key, uint8_t length_B, arcfour_ctx_t *ctx);
/** \fn uint8_t arcfour_gen(arcfour_ctx_t *ctx)
* \brief generates a byte of keystream

View File

@ -38,7 +38,7 @@ char* cipher_name = "Arcfour";
* additional validation-functions *
*****************************************************************************/
void arcfour_genctx_dummy(uint8_t* key, uint16_t keysize, void* ctx){
arcfour_init(ctx, key, (keysize+7)/8);
arcfour_init(key, (uint8_t)((keysize+7)/8), ctx);
}
@ -55,6 +55,17 @@ void testrun_nessie_arcfour(void){
nessie_stream_run();
}
void testrun_performance_arcfour(void){
nessie_stream_ctx.outsize_b = 8; /* actually unused */
nessie_stream_ctx.keysize_b = 128; /* this is theone we have refrence vectors for */
nessie_stream_ctx.ivsize_b = (uint16_t)-1;
nessie_stream_ctx.name = cipher_name;
nessie_stream_ctx.ctx_size_B = sizeof(arcfour_ctx_t);
nessie_stream_ctx.cipher_genctx = (nessie_stream_genctx_fpt)arcfour_genctx_dummy;
nessie_stream_ctx.cipher_enc = (nessie_stream_genenc_fpt)arcfour_gen;
nessie_stream_run();
}
/*****************************************************************************