changed arcfour api
This commit is contained in:
parent
b07fb998ba
commit
c58f43feba
|
@ -66,8 +66,8 @@ email: daniel.otte@rub.de
|
||||||
3.2. *_init function
|
3.2. *_init function
|
||||||
The *_init function generally takes a pointer to the key as first parameter.
|
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
|
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
|
keysize (in bits regularly) and the last parameter points to the context
|
||||||
to fill.
|
variable to fill.
|
||||||
For some ciphers there are additonal parameters like the number of rounds,
|
For some ciphers there are additonal parameters like the number of rounds,
|
||||||
these parameters generally occur before the context pointer.
|
these parameters generally occur before the context pointer.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
126
arcfour-asm.S
126
arcfour-asm.S
|
@ -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>........ |
|
* | i | j | ......<256>........ |
|
||||||
* +---+---+---------------------+
|
* +---+---+---------------------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.global arcfour_init
|
.global arcfour_init
|
||||||
|
/*
|
||||||
;== arcfour_init ==
|
*== arcfour_init ==
|
||||||
; this function initialises the context
|
* this function initialises the context
|
||||||
; param1: 16-bit pointer to a ctx struct
|
* param1: 16-bit pointer to the key
|
||||||
; given in r25,r24
|
* given in r24:r25
|
||||||
; param2: 16-bit pointer to a key
|
* param2: 8-bit integer indicating keylength in byte
|
||||||
; given in r23,r22
|
* given in r22
|
||||||
; param1: 8-bit integer indicating keylength in byte
|
* param3: 16-bit pointer to a ctx struct
|
||||||
; given in r20
|
* given in r20:r21
|
||||||
|
*/
|
||||||
arcfour_init:
|
arcfour_init:
|
||||||
push r29
|
push_ r2, r28, r29
|
||||||
push r28
|
movw r26, r20 /* X points to ctx */
|
||||||
push r2
|
movw r30, r24 /* Z points to key */
|
||||||
|
|
||||||
movw r26, r24 /* X points to ctx */
|
|
||||||
movw r30, r22 /* Z points to key */
|
|
||||||
st X+, r1
|
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:
|
1:
|
||||||
st X+, r1
|
st X+, r1
|
||||||
inc r1
|
inc r1
|
||||||
brne 1b
|
brne 1b
|
||||||
|
|
||||||
adiw r24, 2 /* r24:r25 points to S */
|
movw r26, r20
|
||||||
clr r21 /* r21 is j */
|
clr r18 /* r18 is keyindex counter */
|
||||||
mov r18, r20 /* r18 is keyindex counter */
|
|
||||||
clr r0
|
clr r0
|
||||||
|
clr r19
|
||||||
2:
|
2:
|
||||||
movw r26, r24
|
ld r23, X
|
||||||
ld r19, Z+
|
ld r2, Z+
|
||||||
add r21, r19 /* j+= key[i%length] */
|
add r19, r2
|
||||||
|
add r19, r23
|
||||||
add r26, r1
|
movw r28, r20 /* load pointer to S in Y */
|
||||||
adc r27, r0
|
add r28, r19
|
||||||
ld r19, X
|
adc r29, r1
|
||||||
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 r2, Y
|
ld r2, Y
|
||||||
st Y, r19
|
st Y, r23
|
||||||
st X, r2
|
st X+, r2
|
||||||
inc r1
|
inc r18
|
||||||
|
cp r18, r22
|
||||||
|
brne 3f
|
||||||
|
movw r30, r24
|
||||||
|
clr r18
|
||||||
|
3:
|
||||||
|
inc r0
|
||||||
brne 2b
|
brne 2b
|
||||||
|
pop_ r29, r28, r2
|
||||||
pop r2
|
|
||||||
pop r28
|
|
||||||
pop r29
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -33,15 +33,16 @@
|
||||||
* length is length of key in bytes!
|
* 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;
|
uint8_t t;
|
||||||
unsigned x,y=0;
|
uint16_t x,y=0;
|
||||||
for(x=0; x<= 255; ++x)
|
for(x=0; x<= 255; ++x)
|
||||||
ctx->s[x]=x;
|
ctx->s[x]=x;
|
||||||
|
|
||||||
for(x=0; x<= 255; ++x){
|
for(x=0; x<= 255; ++x){
|
||||||
y += ctx->s[x] + ((uint8_t*)key)[x % length_B];
|
y += ctx->s[x] + ((uint8_t*)key)[x % length_B];
|
||||||
y &= 0xff;
|
y &= 0xff;
|
||||||
|
/* ctx->s[y] <--> ctx->s[x] */
|
||||||
t = ctx->s[y];
|
t = ctx->s[y];
|
||||||
ctx->s[y] = ctx->s[x];
|
ctx->s[y] = ctx->s[x];
|
||||||
ctx->s[x] = t;
|
ctx->s[x] = t;
|
||||||
|
|
|
@ -74,7 +74,7 @@ typedef struct arcfour_ctx_st {
|
||||||
* \param length_B length of the key in bytes (between 1 and 255)
|
* \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)
|
/** \fn uint8_t arcfour_gen(arcfour_ctx_t *ctx)
|
||||||
* \brief generates a byte of keystream
|
* \brief generates a byte of keystream
|
||||||
|
|
|
@ -38,7 +38,7 @@ char* cipher_name = "Arcfour";
|
||||||
* additional validation-functions *
|
* additional validation-functions *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void arcfour_genctx_dummy(uint8_t* key, uint16_t keysize, void* ctx){
|
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();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
Loading…
Reference in New Issue