From 6cddae4d0fa8acf9d3bfd5e0f42c789c32f3a992 Mon Sep 17 00:00:00 2001 From: bg Date: Mon, 11 Jul 2011 00:54:16 +0000 Subject: [PATCH] bug fix + docu --- bigint/bigint_asm.S | 74 +++++++-------- doc/acl-guide.texi | 111 +++++++++++++++++++++- doc/acl_blockciphers.texi | 99 ++------------------ doc/acl_hashes.texi | 167 +++++++++++++++++++++++++++++++++ doc/acl_keysizes.texi | 82 ++++++++++++++++ host/bigint_test.rb | 181 ++++++++++++++++++++++-------------- test_src/main-bigint-test.c | 14 +-- 7 files changed, 524 insertions(+), 204 deletions(-) create mode 100644 doc/acl_keysizes.texi diff --git a/bigint/bigint_asm.S b/bigint/bigint_asm.S index 4255714..1942fa3 100644 --- a/bigint/bigint_asm.S +++ b/bigint/bigint_asm.S @@ -78,10 +78,8 @@ SRC_LEN_0 = 20 SRC_LEN_1 = 21 SCALE_0 = 18 SCALE_1 = 19 -DST_CTX_0 = 6 -DST_CTX_1 = 7 -SRC_CTX_0 = 8 -SRC_CTX_1 = 9 +DST_CTX_0 = 8 +DST_CTX_1 = 9 TMP_0 = 10 TMP_1 = 11 @@ -89,7 +87,14 @@ bigint_add_scale_u: movw r30, r24 /* dest ptr */ movw r26, r22 /* src ptr */ movw r24, r20 /* scale */ + /* check if scale is zero */ movw SCALE_0, r24 + adiw r24, 0 + brne 10f + movw r24, r30 + movw r20, r30 + rjmp bigint_add_u +10: /* check if src is zero */ ld r24, X+ ld r25, X+ adiw r24, 0 @@ -97,9 +102,8 @@ bigint_add_scale_u: ret 10: movw SRC_LEN_0, r24 - push_range 6, 11 + push_range 8, 11 movw DST_CTX_0, r30 - movw SRC_CTX_0, r26 /* pad dest with zeros to length of SRC_LENGTH + scale */ adiw r26, 1 @@ -126,7 +130,6 @@ bigint_add_scale_u: rjmp 10b 11: /* start of copy */ - movw r24, SRC_LEN_0 12: /* copy loop */ @@ -144,13 +147,12 @@ bigint_add_scale_u: std Z+1, TMP_1 movw r24, r30 99: - pop_range 6, 11 + pop_range 8, 11 rjmp bigint_adjust 40: - /* TODO */ /* Z points at DST_WORDV */ /* X points at SRC_WORDV */ - /* r24:r25 contains scale - DST_LEN (negativ) */ + /* r24:r25 and TMP contain scale - DST_LEN (negativ) */ /* set T bit if DST_LEN > SCR_LEN + scale */ clt add r30, SCALE_0 @@ -172,36 +174,24 @@ bigint_add_scale_u: +-------+-------+ SRC + scale +------------+ DST */ - com r24 /* negate r24:r25 */ + com r24 /* negate r24:r25 ==> DST_LEN - scale */ com r25 adiw r24, 1 + breq 50f 44: + inc r25 clc 45: - dec r24 - brpl 46f - dec r25 - brmi 50f 46: ld TMP_0, X+ ld TMP_1, Z adc TMP_0, TMP_1 st Z+, TMP_0 - rjmp 45b + dec r24 + brne 46b + dec r25 + brne 46b -50: - /* do the overhaning part */ - rol r1 - movw r24, r30 - movw r30, DST_CTX_0 - ldd TMP_0, Z+3 - ldd TMP_1, Z+4 - movw r30, TMP_0 - add r30, DST_LEN_0 - adc r31, DST_LEN_1 - adiw r30, 1 - st Z, r1 - movw r30, r24 - ror r1 +50: ;st Z, r1 brtc 60f 51: brcc 53f 52: ld TMP_0, Z @@ -209,34 +199,42 @@ bigint_add_scale_u: st Z+, TMP_0 brcs 52b 53: - /* TODO */ + /* epilogue */ movw r24, r30 movw r30, DST_CTX_0 ldd TMP_0, Z+3 ldd TMP_1, Z+4 sub r24, TMP_0 sbc r25, TMP_1 + cp r24, DST_LEN_0 + cpc r25, DST_LEN_1 + brmi 54f std Z+0, r24 std Z+1, r25 - movw r24, r30 +54: movw r24, r30 rjmp 99b -60: rol r1 /* backup carry */ +60: st Z, r1 + rol r1 /* backup carry */ movw r24, SRC_LEN_0 add r24, SCALE_0 adc r25, SCALE_1 sub r24, DST_LEN_0 sbc r25, DST_LEN_1 + + adiw r24, 0 + breq 63f + inc r25 ror r1 /* restore carry */ -61: dec r24 - brpl 62f - dec r25 - brmi 63f +61: 62: ld TMP_0, X+ adc TMP_0, r1 st Z+, TMP_0 - rjmp 61b + dec r24 + brne 62b + dec r25 + brne 62b 63: brcc 53b ldi r24, 1 diff --git a/doc/acl-guide.texi b/doc/acl-guide.texi index bf004ab..7a0e52c 100644 --- a/doc/acl-guide.texi +++ b/doc/acl-guide.texi @@ -30,8 +30,117 @@ of documenting the structure of the API so you know what to do when you want to use the library. @chapter Generic stuff +@section Requirements +You should have the following software tools to build the library, the version +mentioned is the version used on the test system, older or newer versions may +or may not work): +@table @asis + @item a recent toolchain + for AVR targets: + @table @asis + @item gcc for AVR (avr-gcc) + 4.3.5 + @item GNU binutils for AVR + 2.21 + @item avr-libc + 1.6.8-2 + @end table + for ARM targets: + @table @asis + @item gcc for ARM (arm-elf-gcc) + @item GNU binutils for ARM + @item newlib with enabled malloc() + @end table + @item a flash tool to program your device + for AVR targets: + @table @asis + @item avrdude + 5.10 + @end table + for ARM targets: + @table @asis + @item openocd + 0.4.0 + @end table + + @item GNU make + 3.81 + @item ruby (for the testing system) + 1.8.7.302-2 + @table @asis + @item rubygems + 1.3.7 + @item serialport + 1.0.4 + @item getopt + 1.4.0 + @end table +@end table + @section File organisation + + @section Build process +The build process is managed by a large relative complex @file{Makefile} and +a bunch of more specific Makefile-stubs (@file{*.mk} in the @file{mkfiles} +directory). + + + +@subsection make-stubs +All stubs are included by the main Makefile automatically, so the addition of +algorithms should not require modifications to the Makefile. + +Because all stubs are included by the main Makefile you can use all features +of your make system when writing them. Currently we use GNU make and we +recommend using GNU make when building the crypto library. + +Each algorithm implementation has its own stub. A stub looks like the following: +@verbatim +# Makefile for AES +ALGO_NAME := AES128_C + +# comment out the following line for removement of AES from the build process +BLOCK_CIPHERS += $(ALGO_NAME) + +$(ALGO_NAME)_DIR := aes/ +$(ALGO_NAME)_INCDIR := gf256mul/ bcal/ +$(ALGO_NAME)_OBJ := aes_enc.o aes_dec.o aes_sbox.o aes_invsbox.o \ + aes_keyschedule.o gf256mul.o aes128_enc.o aes128_dec.o +$(ALGO_NAME)_TEST_BIN := main-aes128-test.o $(CLI_STD) $(BCAL_STD) \ + bcal_aes128.o +$(ALGO_NAME)_NESSIE_TEST := test nessie +$(ALGO_NAME)_PERFORMANCE_TEST := performance +@end verbatim + +The most important thing is defining an unambiguous name for the implementation, +in this case it is AES128_C. +The next step is chaining the implementation into a category. Uncategorized +implementations will be ignored. So if you want to exclude an implementation +from the build process you can simply comment out the line which chains it into +a category. + +The following lines declare ''Attributes'' of the implementation. +@table @var +@item _DIR + defines the directory where the implementation resides +@item _INCDIR + defines directorys to search for additional files +@item _OBJ + defines the names of the objects which shoud be considered the implementations + core +@item _TESTBIN + defines the names of the objects required to build the test suit +@item _NESSIE_TEST + (currently unused) defines the string which should be send to the test system + to perform nessie standard tests +@item _NESSIE_TEST + (currently unused) defines the string which should be send to the test system + to perform a performance tests +@item _DEF + defines macros to use while compiling +@end table + @section Testing system @section Sizes in bits and bytes Working with cryptographic functions involves working with different @@ -42,7 +151,7 @@ to use the library. _b means in bits and _B means in bytes (big b big word) and _w meaning words. @chapter Symmetric primitives - +@include acl_keysizes.texi @include acl_blockciphers.texi @section Modes of operation diff --git a/doc/acl_blockciphers.texi b/doc/acl_blockciphers.texi index d256019..f274676 100644 --- a/doc/acl_blockciphers.texi +++ b/doc/acl_blockciphers.texi @@ -135,7 +135,7 @@ The BCAL is split up in different parts: @item BCAL basic functions @end itemize -@subsubsection BCAL declaration for BCAL decriptors +@subsection BCAL declaration for BCAL decriptors The BCAL descriptor is a structure which is usually placed in FLASH or ROM since modification is unnecessary. It contains all information required to use the according block cipher. @@ -220,7 +220,7 @@ typedef struct { that the chosen keysize is valid @end table -@subsubsection BCAL-Basic context +@subsection BCAL-Basic context Besides the context types for individual ciphers there is a generic context type for BCAL. This is the context to use when using BCAL based functions. The BCAL context has the following structure: @@ -242,14 +242,13 @@ pointer to the cipher specific context -@subsubsection BCAL-Basic +@subsection BCAL-Basic BCAL-Basic provides the basic features of an block cipher on top of the BCAL. To use it you simply have to include the algorithms you want to use, the BCAL descriptor file and of course the BCAL-Basic implementation. The following functions are provided: -@table @code -@item bcal_cipher_init +@subsubsection @code{bcal_cipher_init} @code{uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor, const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx)} this function initializes a BCAL context based on the given BCAL descriptor pointer (first parameter) with a given key (second parameter) of a given length @@ -270,109 +269,29 @@ The following functions are provided: for the selected cipher. @end table -@item bcal_cipher_free +@subsubsection @code{bcal_cipher_free} @code{void bcal_cipher_free(bcgen_ctx_t* ctx)} this function frees the memory allocated by the init function and should be called whenever you are finished with BCAL context. It automatically also calls the @code{free} function if necessary. -@item bcal_cipher_enc +@subsubsection @code{bcal_cipher_enc} @code{void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx)} this function encrypts a block in-place using a given BCAL contex. -@item bcal_cipher_dec +@subsubsection @code{bcal_cipher_dec} @code{void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx)} this function decrypts a block in-place using a given BCAL contex. -@item bcal_cipher_getBlocksize_b +@subsubsection @code{bcal_cipher_getBlocksize_b} @code{uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc)} this function returns the block size of a given cipher by using the BCAL descriptor (to which a pointer must be passed). -@item bcal_cipher_getKeysizeDesc +@subsubsection @code{bcal_cipher_getKeysizeDesc} @code{PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc)} this function returns a pointer to the keysize descriptor of a given cipher by using the BCAL descriptor (to which a pointer must be passed). -@end table - -@subsection Keysize descriptors -There are a lot of different block ciphers or cryptographic algorithms in -general which put several constrains to the number of bits which can be used -as key. - -Our approach is to find a simple and compact way do specify which lengths are -valid and which are not. The system is quite simple, we use a list of patterns -(with parameters) and if any matches the keysize is valid, if none matches the -keysize is unsupported. - -The patterns are: -@itemize @bullet -@item simple list of valid keysizes -@item range of keysizes -@item augmented range of keysizes -@end itemize - -@subsubsection simple list of valid keysizes -The simple keysize list has the following structure: -@verbatim -typedef struct{ /* keysize is valid if listed in items */ - uint8_t n_items; /* number of items (value 0 is reserved) */ - uint16_t items[]; /* list of valid lengths */ -}keysize_desc_list_t; -@end verbatim -First we specify how many keysizes we want to declare valid (this is limited to -255 keysizes but that should not impose any real world constrains). And follow -it by the keysizes as 16bit unsigned values. - -If you want to declare a lot of keys please check first the other methods since -they may give a more compact definition. - -@subsubsection range of keysizes -This method specifies an entire range of keys a valid using the following -structure: -@verbatim -typedef struct{ /* keysize is valid if min<=keysize<=max */ - uint16_t min; - uint16_t max; -}keysize_desc_range_t; -@end verbatim -So all keysizes between @code{min} and @code{max} (including @code{min} and -@code{max}) are valid. Please note that in most cases also keysizes which -are not a multiple of 8 (so are not full bytes) are also matched. -If you want to avoid this see the augmented range of keysizes. - -@subsubsection augmented range of keysizes -The augmented range of keysizes uses the following structure: -@verbatim -typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */ - uint16_t min; - uint16_t max; - uint16_t distance; - uint16_t offset; -}keysize_desc_arg_range_t; -@end verbatim -The restriction to a range is the same as with the simpler range of keysizes, -but also another restriction is imposed. A valid keysize must have a reminder -of @code{offset} when divided by @code{distance}. So you can limit a keysize -to full bytes by simply setting @code{distance} to @samp{8} and @code{offset} -to @samp{0}. - -@subsubsection the actual descriptor -The keysize descriptor is a list of the former patterns. Each pattern is -preceded by byte designating the type of pattern and the list is terminated -by a @code{NULL} byte. - -The designator byte can have one of the following values: -@table @samp -@item 0x00 -Terminator byte, signals the end of the list -@item 0x01 -simple list of keysizes -@item 0x02 -simple range of keysizes -@item 0x03 -augmented range of keysizes -@end table diff --git a/doc/acl_hashes.texi b/doc/acl_hashes.texi index 29a0ca0..8b351ca 100644 --- a/doc/acl_hashes.texi +++ b/doc/acl_hashes.texi @@ -83,5 +83,172 @@ @subsection Hash function abstraction layer (HFAL) +The HashFunctionAbstractionLayer (BCAL) is an abstraction layer which allows +usage of all implemented hash functions in a simple way. It abstracts specific +function details and is suitable for implementations which want to be flexible +in the choosing of specific hash functions. Another important aspect is that this +abstraction layer enables the implementation of hash function operating modes +independently from concrete hash function. It is very simple to use and reassembles +the API used to implement individual hash functions. + +The main component is a hash function descriptor which contains the details of +the individual hash functions. + +@subsection Parts of HFAL +The HFAL is split up in different parts: +@itemize @bullet + @item HFAL declaration for HFAL decriptors + @item algorithm specific definitions of HFAL decriptors + @item HFAL basic context type + @item HFAL basic functions +@end itemize + +@subsection HFAL declaration for HFAL decriptors +The HFAL descriptor is a structure which is usually placed in FLASH or ROM since +modification is unnecessary. It contains all information required to use the +according hash function. + +@verbatim +typedef struct { + uint8_t type; /* 2 == hashfunction */ + uint8_t flags; + PGM_P name; + uint16_t ctxsize_B; + uint16_t blocksize_b; + uint16_t hashsize_b; + hf_init_fpt init; + hf_nextBlock_fpt nextBlock; + hf_lastBlock_fpt lastBlock; + hf_ctx2hash_fpt ctx2hash; + hf_free_fpt free; + hf_mem_fpt mem; +} hfdesc_t; /* hashfunction descriptor type */ +@end verbatim + +@table @var + @item type + should be set to @samp{2} to indicate that this descriptor is for a + hash function. + + @item flags + currently unused, should be set to zero. + + @item name + is a pointer to a zero terminated ASCII string giving the name of the + implemented primitive. On targets with Harvard-architecture the string resides + in code memory (FLASH, ROM, ...). + + @item ctxsize_B + is the number of bytes which should be allocated for the context variable. + + @item blocksize_b + is the number of bits on which are hashed by one iteration of the nextBlock + function. + + @item hashsize_b + is the number of bits on which are outputed as final hash value. + + @item init + is a pointer to the init function. + + @item nextBlock + is a pointer to the algorithm specific nextBlock function. + + @item lastBlock + is a pointer to the algorithm specific lastBlock function. + + @item ctx2hash + is a pointer to the algorithm specific ctx2hash function. + + @item free + is a pointer to the free function or NULL if there is no free function. + + @item mem + is a pointer to the algorithm specific mem function. This function hashes + a complete message which has to reside entirely in RAM. This value may be + NULL if there is no such function. +@end table + +@subsection HFAL-Basic context +Besides the context types for individual hash functions there is a generic context +type for HFAL. This is the context to use when using HFAL based functions. +The HFAL context has the following structure: +@verbatim +typedef struct{ + hfdesc_t* desc_ptr; + void* ctx; +} hfgen_ctx_t; +@end verbatim +@table @code +@item desc_ptr +a pointer to the HFAL descriptor +@item ctx +pointer to the hash function specific context +@end table + +@subsection HFAL-Basic +HFAL-Basic provides the basic features of an hash function on top of the +HFAL. To use it you simply have to include the algorithms you want to use, +the HFAL descriptor file and of course the HFAL-Basic implementation. + +The following functions are provided: + +@subsubsection @code{hfal_hash_init} +@code{uint8_t hfal_hash_init(const hfdesc_t* hash_descriptor, hfgen_ctx_t* ctx)} + this function initializes a HFAL context based on the given HFAL descriptor + pointer (first parameter). The context to initialize is designated by the + pointer passed as second parameter. + + If everything works fine @samp{0} is returned. In the case something fails + the following codes are returned: +@table @samp + @item 3 + It was not possible to allocate enough memory to hold the context variable + for the selected hash function. +@end table + +@subsubsection @code{hfal_hash_nextBlock} +@code{ void hfal_hash_nextBlock(hfgen_ctx_t* ctx, const void* block)} + this function hashes a block of memory (of algorithm specific length) and + updates the context accordingly. + +@subsubsection @code{hfal_hash_lastBlock} +@code{ void hfal_hash_lastBlock(hfgen_ctx_t* ctx, const void* block, uint16_t length_b)} + this function is used to hash the last block of a message. Since messages are + not required to consist of full blocks (or even full bytes) the length of the + block must be given in bits. The context is updated accordingly. This function + already performs padding and related stuff. + +@subsubsection @code{hfal_hash_ctx2hash} +@code{ void hfal_hash_ctx2hash(void* dest, hfgen_ctx_t* ctx)} + this function converts a context into an actual hash value which is stored in + @code{dest}. The application is responsible for allocating enough room. + +@subsubsection @code{hfal_hash_free} +@code{ void hfal_hash_free(hfgen_ctx_t* ctx)} + this function differs from the individual hash functions @code{free} function + in that it is allways provided and must be called to avoid memory holes. + This function also automatically calls the implementation specific @code{free} + function if one is provided. + +@subsubsection @code{hfal_hash_mem} +@code{ void hfal_hash_mem(const hfdesc_t* hash_descriptor, void* dest, const void* msg, uint32_t length_b)} + this function is allways provided (even if the actual algorithm does not + specify a @code{mem} function. It hashes an entire message which resides in + RAM and stores the hash value in @code{dest}. @code{msg} is the pointer to the + message and @code{length_b} is the message length in bits. + +@subsubsection @code{hfal_hash_getBlocksize} +@code{ uint16_t hfal_hash_getBlocksize(const hfdesc_t* hash_descriptor)} + returns the blocksize of the described (@code{hash_descriptor}) hash function. + +@subsubsection @code{hfal_hash_getHashsize} +@code{ uint16_t hfal_hash_getHashsize(const hfdesc_t* hash_descriptor)} + returns the hash value size of the described (@code{hash_descriptor}) hash function. + +@subsubsection @code{hfal_hash_getCtxsize} +@code{ uint16_t hfal_hash_getCtxsize_B(const hfdesc_t* hash_descriptor)} + returns the size of a context variable of the described (@code{hash_descriptor}) hash function. + diff --git a/doc/acl_keysizes.texi b/doc/acl_keysizes.texi new file mode 100644 index 0000000..fdda705 --- /dev/null +++ b/doc/acl_keysizes.texi @@ -0,0 +1,82 @@ +@c acl_keysizes.texi + +@section Keysize descriptors +There are a lot of different block ciphers or cryptographic algorithms in +general which put several constrains to the number of bits which can be used +as key. + +Our approach is to find a simple and compact way do specify which lengths are +valid and which are not. The system is quite simple, we use a list of patterns +(with parameters) and if any matches the keysize is valid, if none matches the +keysize is unsupported. + +The patterns are: +@itemize @bullet +@item simple list of valid keysizes +@item range of keysizes +@item augmented range of keysizes +@end itemize + +@subsection simple list of valid keysizes +The simple keysize list has the following structure: +@verbatim +typedef struct{ /* keysize is valid if listed in items */ + uint8_t n_items; /* number of items (value 0 is reserved) */ + uint16_t items[]; /* list of valid lengths */ +}keysize_desc_list_t; +@end verbatim +First we specify how many keysizes we want to declare valid (this is limited to +255 keysizes but that should not impose any real world constrains). And follow +it by the keysizes as 16bit unsigned values. + +If you want to declare a lot of keys please check first the other methods since +they may give a more compact definition. + +@subsection range of keysizes +This method specifies an entire range of keys a valid using the following +structure: +@verbatim +typedef struct{ /* keysize is valid if min<=keysize<=max */ + uint16_t min; + uint16_t max; +}keysize_desc_range_t; +@end verbatim +So all keysizes between @code{min} and @code{max} (including @code{min} and +@code{max}) are valid. Please note that in most cases also keysizes which +are not a multiple of 8 (so are not full bytes) are also matched. +If you want to avoid this see the augmented range of keysizes. + +@subsection augmented range of keysizes +The augmented range of keysizes uses the following structure: +@verbatim +typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */ + uint16_t min; + uint16_t max; + uint16_t distance; + uint16_t offset; +}keysize_desc_arg_range_t; +@end verbatim +The restriction to a range is the same as with the simpler range of keysizes, +but also another restriction is imposed. A valid keysize must have a reminder +of @code{offset} when divided by @code{distance}. So you can limit a keysize +to full bytes by simply setting @code{distance} to @samp{8} and @code{offset} +to @samp{0}. + +@subsection the actual descriptor +The keysize descriptor is a list of the former patterns. Each pattern is +preceded by byte designating the type of pattern and the list is terminated +by a @code{NULL} byte. + +The designator byte can have one of the following values: +@table @samp +@item 0x00 +Terminator byte, signals the end of the list +@item 0x01 +simple list of keysizes +@item 0x02 +simple range of keysizes +@item 0x03 +augmented range of keysizes +@end table + + diff --git a/host/bigint_test.rb b/host/bigint_test.rb index df16e7d..cb9de13 100644 --- a/host/bigint_test.rb +++ b/host/bigint_test.rb @@ -127,6 +127,9 @@ end ################################################################################ def init_system(test_prog) + begin + line = $sp.gets() + end while line!=nil $sp.print("echo off \r") print("DBG i: " + "echo off \r"+"\n") if $debug sleep 0.1 @@ -135,6 +138,27 @@ def init_system(test_prog) sleep 1 end +################################################################################ +# wait_for_prompt # +################################################################################ + +def wait_for_prompt(prompt) + prompt = /[\s]*#{prompt}[\s]*/ if(prompt.class == String) + start_time = Time.now.to_i + begin + line = $sp.gets() + puts("DBG got (#{__LINE__}): "+line) if $debug && line + line = "" if line==nil + if /^(Error:|Crypto-VS).*/.match(line) + puts line + return false + end + if (Time.now.to_i- start_time) > $max_timeout + return false + end + end while not m=prompt.match(line) + return m +end ################################################################################ # screen_progress # @@ -249,59 +273,42 @@ end ################################################################################ # add_scale_test # ################################################################################ +def add_scale_test_dummy(a, b, scale) + should = a + (b<<(8*scale)) + printf("[dummy] %s + %s <<8*%04x = %s\n",a.to_s(16), b.to_s(16), scale, should.to_s(16)) +end def add_scale_test(a, b, scale) - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got (#{__LINE__}): "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter a:[\s]*/.match(line) + m = wait_for_prompt("enter a:") + return false if !m puts("DBG put (#{__LINE__}): "+a.to_s(16)+" ") if $debug $sp.print(a.to_s(16)+" ") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got (#{__LINE__}): "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter b:[\s]*/.match(line) + m = wait_for_prompt("enter b:") + return false if !m + puts("DBG put (#{__LINE__}): "+b.to_s(16)+" ") if $debug $sp.print(b.to_s(16)+" ") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got (#{__LINE__}): "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter scale:[\s]*/.match(line) + m = wait_for_prompt("enter scale:") + return false if !m + puts("DBG put (#{__LINE__}): "+scale.to_s(10)+" ") if $debug $sp.print(scale.to_s(10)+"\r") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got (#{__LINE__}): "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not m=/[\s]*([-]?[0-9a-fA-F]*)[\s]+\+[\s]+([+-]?[0-9a-fA-F]*)[\s]*<<8\*[\s]*([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) + should = a + (b<<(8*scale)) + m = wait_for_prompt(/[\s]*([-]?[0-9a-fA-F]+)[\s]+\+[\s]+([+-]?[0-9a-fA-F]+)[\s]*<<8\*[\s]*([+-]?[0-9a-fA-F]+)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/) + if !m + $logfile.printf("[fail (CRASH)]:") + $logfile.printf(" ; should %s + %s << 8*%s = %s\n", a.to_s(16), b.to_s(16), scale.to_s(16), should.to_s(16)) + return false + end + line = m[0] a_ = m[1].to_i(16) b_ = m[2].to_i(16) s_ = m[3].to_i(16) c_ = m[4].to_i(16) line.chomp! - should = a + (b<<(8*scale)) if(a_== a && b_ == b && s_ == scale && c_ == should ) $logfile.printf("[pass]: %s\n", line) return true else - $logfile.printf("[fail (%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (scale==s_)?"":"s",(c_==should)?"":"c",line) + $logfile.printf("[fail (%s%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (scale==s_)?"":"s",(c_==should)?"":"c",line) $logfile.printf(" ; should %s + %s << 8*%s = %s\n", a.to_s(16), b.to_s(16), scale.to_s(16), should.to_s(16)) return false end @@ -563,7 +570,7 @@ def run_test_add_scale(skip=0) length_b_B = skip+1 begin $size = length_a_B - (0..16).each do |i| + (0..4).each do |i| scales = [0, 300] 16.times { scales << rand(301) } scales.sort! @@ -576,12 +583,12 @@ def run_test_add_scale(skip=0) screen_progress(v) end end - (0..16).each do |i| + (0..4).each do |i| scales = [0, 300] 16.times { scales << rand(301) } scales.sort! scales.each do |scale| - b_size = rand(length_b_B+1) + b_size = rand(length_b_B+1)+1 a = rand(256**length_a_B) b = rand(256**b_size) v = add_scale_test(a, b, scale) @@ -595,6 +602,39 @@ def run_test_add_scale(skip=0) end while length_a_B<4096/8 end +def run_test_add_scale_dummy(skip=0) + length_a_B = skip+1 + length_b_B = skip+1 + begin + $size = length_a_B + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + a = rand(256**length_a_B) + b = rand(256**length_a_B) + v = add_scale_test_dummy(a, b, scale) + v = add_scale_test_dummy(b, a, scale) + end + end + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + b_size = rand(length_b_B+1) + a = rand(256**length_a_B) + b = rand(256**b_size) + v = add_scale_test_dummy(a, b, scale) + v = add_scale_test_dummy(b, a, scale) + end + end + length_a_B += 10 + length_b_B += 10 + end while length_a_B<4096/8 +end + ################################################################################ # run_test_mul # ################################################################################ @@ -733,6 +773,36 @@ def run_test_gcdext(skip=0) end while length_a_B<4096/8 end +def init_serialport(conf) + puts("serial port interface version: " + SerialPort::VERSION); + $linewidth = 64 + $linepos = 0 + $testno = 0 + params = { "baud" => conf["PORT"]["baud"].to_i, + "data_bits" => conf["PORT"]["databits"].to_i, + "stop_bits" => conf["PORT"]["stopbits"].to_i, + "parity" => SerialPort::NONE } + params["paraty"] = SerialPort::ODD if conf["PORT"]["paraty"].downcase == "odd" + params["paraty"] = SerialPort::EVEN if conf["PORT"]["paraty"].downcase == "even" + params["paraty"] = SerialPort::MARK if conf["PORT"]["paraty"].downcase == "mark" + params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space" + + puts("\nPort: "+conf["PORT"]["port"]+"@" + + params["baud"].to_s + + " " + + params["data_bits"].to_s + + conf["PORT"]["paraty"][0,1].upcase + + params["stop_bits"].to_s + + "\n") + + $sp = SerialPort.new(conf["PORT"]["port"], params) + + $sp.read_timeout=1000; # 5 minutes + $sp.flow_control = SerialPort::SOFT + + reset_system() +end + ################################################################################ # MAIN # ################################################################################ @@ -746,34 +816,9 @@ conf = readconfigfile("testport.conf", conf) conf = readconfigfile(opts["f"], conf) if opts["f"] #puts conf.inspect +init_serialport(conf) -puts("serial port interface version: " + SerialPort::VERSION); -$linewidth = 64 -$linepos = 0 -$testno = 0 -params = { "baud" => conf["PORT"]["baud"].to_i, - "data_bits" => conf["PORT"]["databits"].to_i, - "stop_bits" => conf["PORT"]["stopbits"].to_i, - "parity" => SerialPort::NONE } -params["paraty"] = SerialPort::ODD if conf["PORT"]["paraty"].downcase == "odd" -params["paraty"] = SerialPort::EVEN if conf["PORT"]["paraty"].downcase == "even" -params["paraty"] = SerialPort::MARK if conf["PORT"]["paraty"].downcase == "mark" -params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space" - -puts("\nPort: "+conf["PORT"]["port"]+"@" + - params["baud"].to_s + - " " + - params["data_bits"].to_s + - conf["PORT"]["paraty"][0,1].upcase + - params["stop_bits"].to_s + - "\n") - -$sp = SerialPort.new(conf["PORT"]["port"], params) - -$sp.read_timeout=1000; # 5 minutes -$sp.flow_control = SerialPort::SOFT - -reset_system() + $max_timeout = 2 * 60 if opts['d'] $debug = true diff --git a/test_src/main-bigint-test.c b/test_src/main-bigint-test.c index 4daf319..787a7cb 100644 --- a/test_src/main-bigint-test.c +++ b/test_src/main-bigint-test.c @@ -125,13 +125,6 @@ void test_add_scale_bigint(void){ return; } */ - cli_putstr_P(PSTR("\r\n ")); - bigint_print_hex(&a); - cli_putstr_P(PSTR(" + ")); - bigint_print_hex(&b); - cli_putstr_P(PSTR("<<8*")); - cli_hexdump_rev(&scale, 2); - cli_putstr_P(PSTR(" = ")); uint8_t *c_b; c_b = malloc(((a.length_B>(b.length_B+scale))?a.length_B:(b.length_B+scale))+2); if(c_b==NULL){ @@ -143,6 +136,13 @@ void test_add_scale_bigint(void){ c.wordv = c_b; bigint_copy(&c, &a); bigint_add_scale_u(&c, &b, scale); + cli_putstr_P(PSTR("\r\n ")); + bigint_print_hex(&a); + cli_putstr_P(PSTR(" + ")); + bigint_print_hex(&b); + cli_putstr_P(PSTR("<<8*")); + cli_hexdump_rev(&scale, 2); + cli_putstr_P(PSTR(" = ")); bigint_print_hex(&c); cli_putstr_P(PSTR("\r\n")); free(a.wordv); -- 2.39.5