From c58f43febaefd188708dca010198629c0935728c Mon Sep 17 00:00:00 2001 From: bg Date: Wed, 6 Aug 2008 18:04:23 +0000 Subject: [PATCH] changed arcfour api --- USAGE.blockciphers | 4 +- USAGE.streamciphers | 71 ++++++++++++++++++++ arcfour-asm.S | 126 +++++++++++++++++++++++------------ arcfour.c | 5 +- arcfour.h | 2 +- test_src/main-arcfour-test.c | 13 +++- 6 files changed, 171 insertions(+), 50 deletions(-) create mode 100644 USAGE.streamciphers diff --git a/USAGE.blockciphers b/USAGE.blockciphers index f0bc9d8..54fb783 100644 --- a/USAGE.blockciphers +++ b/USAGE.blockciphers @@ -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. diff --git a/USAGE.streamciphers b/USAGE.streamciphers new file mode 100644 index 0000000..68fb197 --- /dev/null +++ b/USAGE.streamciphers @@ -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. + + + \ No newline at end of file diff --git a/arcfour-asm.S b/arcfour-asm.S index d3ecadb..05cac92 100644 --- a/arcfour-asm.S +++ b/arcfour-asm.S @@ -26,68 +26,106 @@ * */ +#include + + +.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 /* diff --git a/arcfour.c b/arcfour.c index 13fb159..7c35a03 100644 --- a/arcfour.c +++ b/arcfour.c @@ -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; diff --git a/arcfour.h b/arcfour.h index 1f5af2f..23fb458 100644 --- a/arcfour.h +++ b/arcfour.h @@ -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 diff --git a/test_src/main-arcfour-test.c b/test_src/main-arcfour-test.c index 0e0be91..7ebe527 100644 --- a/test_src/main-arcfour-test.c +++ b/test_src/main-arcfour-test.c @@ -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(); +} /***************************************************************************** -- 2.39.5