bug fix + docu
This commit is contained in:
parent
8fcc613257
commit
6cddae4d0f
|
@ -78,10 +78,8 @@ SRC_LEN_0 = 20
|
||||||
SRC_LEN_1 = 21
|
SRC_LEN_1 = 21
|
||||||
SCALE_0 = 18
|
SCALE_0 = 18
|
||||||
SCALE_1 = 19
|
SCALE_1 = 19
|
||||||
DST_CTX_0 = 6
|
DST_CTX_0 = 8
|
||||||
DST_CTX_1 = 7
|
DST_CTX_1 = 9
|
||||||
SRC_CTX_0 = 8
|
|
||||||
SRC_CTX_1 = 9
|
|
||||||
TMP_0 = 10
|
TMP_0 = 10
|
||||||
TMP_1 = 11
|
TMP_1 = 11
|
||||||
|
|
||||||
|
@ -89,7 +87,14 @@ bigint_add_scale_u:
|
||||||
movw r30, r24 /* dest ptr */
|
movw r30, r24 /* dest ptr */
|
||||||
movw r26, r22 /* src ptr */
|
movw r26, r22 /* src ptr */
|
||||||
movw r24, r20 /* scale */
|
movw r24, r20 /* scale */
|
||||||
|
/* check if scale is zero */
|
||||||
movw SCALE_0, r24
|
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 r24, X+
|
||||||
ld r25, X+
|
ld r25, X+
|
||||||
adiw r24, 0
|
adiw r24, 0
|
||||||
|
@ -97,9 +102,8 @@ bigint_add_scale_u:
|
||||||
ret
|
ret
|
||||||
10:
|
10:
|
||||||
movw SRC_LEN_0, r24
|
movw SRC_LEN_0, r24
|
||||||
push_range 6, 11
|
push_range 8, 11
|
||||||
movw DST_CTX_0, r30
|
movw DST_CTX_0, r30
|
||||||
movw SRC_CTX_0, r26
|
|
||||||
|
|
||||||
/* pad dest with zeros to length of SRC_LENGTH + scale */
|
/* pad dest with zeros to length of SRC_LENGTH + scale */
|
||||||
adiw r26, 1
|
adiw r26, 1
|
||||||
|
@ -126,7 +130,6 @@ bigint_add_scale_u:
|
||||||
rjmp 10b
|
rjmp 10b
|
||||||
11:
|
11:
|
||||||
/* start of copy */
|
/* start of copy */
|
||||||
|
|
||||||
movw r24, SRC_LEN_0
|
movw r24, SRC_LEN_0
|
||||||
|
|
||||||
12: /* copy loop */
|
12: /* copy loop */
|
||||||
|
@ -144,13 +147,12 @@ bigint_add_scale_u:
|
||||||
std Z+1, TMP_1
|
std Z+1, TMP_1
|
||||||
movw r24, r30
|
movw r24, r30
|
||||||
99:
|
99:
|
||||||
pop_range 6, 11
|
pop_range 8, 11
|
||||||
rjmp bigint_adjust
|
rjmp bigint_adjust
|
||||||
40:
|
40:
|
||||||
/* TODO */
|
|
||||||
/* Z points at DST_WORDV */
|
/* Z points at DST_WORDV */
|
||||||
/* X points at SRC_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 */
|
/* set T bit if DST_LEN > SCR_LEN + scale */
|
||||||
clt
|
clt
|
||||||
add r30, SCALE_0
|
add r30, SCALE_0
|
||||||
|
@ -172,36 +174,24 @@ bigint_add_scale_u:
|
||||||
+-------+-------+ SRC + scale
|
+-------+-------+ SRC + scale
|
||||||
+------------+ DST
|
+------------+ DST
|
||||||
*/
|
*/
|
||||||
com r24 /* negate r24:r25 */
|
com r24 /* negate r24:r25 ==> DST_LEN - scale */
|
||||||
com r25
|
com r25
|
||||||
adiw r24, 1
|
adiw r24, 1
|
||||||
|
breq 50f
|
||||||
44:
|
44:
|
||||||
|
inc r25
|
||||||
clc
|
clc
|
||||||
45:
|
45:
|
||||||
dec r24
|
|
||||||
brpl 46f
|
|
||||||
dec r25
|
|
||||||
brmi 50f
|
|
||||||
46: ld TMP_0, X+
|
46: ld TMP_0, X+
|
||||||
ld TMP_1, Z
|
ld TMP_1, Z
|
||||||
adc TMP_0, TMP_1
|
adc TMP_0, TMP_1
|
||||||
st Z+, TMP_0
|
st Z+, TMP_0
|
||||||
rjmp 45b
|
dec r24
|
||||||
|
brne 46b
|
||||||
|
dec r25
|
||||||
|
brne 46b
|
||||||
|
|
||||||
50:
|
50: ;st Z, r1
|
||||||
/* 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
|
|
||||||
brtc 60f
|
brtc 60f
|
||||||
51: brcc 53f
|
51: brcc 53f
|
||||||
52: ld TMP_0, Z
|
52: ld TMP_0, Z
|
||||||
|
@ -209,34 +199,42 @@ bigint_add_scale_u:
|
||||||
st Z+, TMP_0
|
st Z+, TMP_0
|
||||||
brcs 52b
|
brcs 52b
|
||||||
53:
|
53:
|
||||||
/* TODO */
|
/* epilogue */
|
||||||
movw r24, r30
|
movw r24, r30
|
||||||
movw r30, DST_CTX_0
|
movw r30, DST_CTX_0
|
||||||
ldd TMP_0, Z+3
|
ldd TMP_0, Z+3
|
||||||
ldd TMP_1, Z+4
|
ldd TMP_1, Z+4
|
||||||
sub r24, TMP_0
|
sub r24, TMP_0
|
||||||
sbc r25, TMP_1
|
sbc r25, TMP_1
|
||||||
|
cp r24, DST_LEN_0
|
||||||
|
cpc r25, DST_LEN_1
|
||||||
|
brmi 54f
|
||||||
std Z+0, r24
|
std Z+0, r24
|
||||||
std Z+1, r25
|
std Z+1, r25
|
||||||
movw r24, r30
|
54: movw r24, r30
|
||||||
rjmp 99b
|
rjmp 99b
|
||||||
|
|
||||||
60: rol r1 /* backup carry */
|
60: st Z, r1
|
||||||
|
rol r1 /* backup carry */
|
||||||
movw r24, SRC_LEN_0
|
movw r24, SRC_LEN_0
|
||||||
add r24, SCALE_0
|
add r24, SCALE_0
|
||||||
adc r25, SCALE_1
|
adc r25, SCALE_1
|
||||||
sub r24, DST_LEN_0
|
sub r24, DST_LEN_0
|
||||||
sbc r25, DST_LEN_1
|
sbc r25, DST_LEN_1
|
||||||
|
|
||||||
|
adiw r24, 0
|
||||||
|
breq 63f
|
||||||
|
inc r25
|
||||||
ror r1 /* restore carry */
|
ror r1 /* restore carry */
|
||||||
|
|
||||||
61: dec r24
|
61:
|
||||||
brpl 62f
|
|
||||||
dec r25
|
|
||||||
brmi 63f
|
|
||||||
62: ld TMP_0, X+
|
62: ld TMP_0, X+
|
||||||
adc TMP_0, r1
|
adc TMP_0, r1
|
||||||
st Z+, TMP_0
|
st Z+, TMP_0
|
||||||
rjmp 61b
|
dec r24
|
||||||
|
brne 62b
|
||||||
|
dec r25
|
||||||
|
brne 62b
|
||||||
63:
|
63:
|
||||||
brcc 53b
|
brcc 53b
|
||||||
ldi r24, 1
|
ldi r24, 1
|
||||||
|
|
|
@ -30,8 +30,117 @@ of documenting the structure of the API so you know what to do when you want
|
||||||
to use the library.
|
to use the library.
|
||||||
|
|
||||||
@chapter Generic stuff
|
@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 File organisation
|
||||||
|
|
||||||
|
|
||||||
@section Build process
|
@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 Testing system
|
||||||
@section Sizes in bits and bytes
|
@section Sizes in bits and bytes
|
||||||
Working with cryptographic functions involves working with different
|
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.
|
_b means in bits and _B means in bytes (big b big word) and _w meaning words.
|
||||||
|
|
||||||
@chapter Symmetric primitives
|
@chapter Symmetric primitives
|
||||||
|
@include acl_keysizes.texi
|
||||||
@include acl_blockciphers.texi
|
@include acl_blockciphers.texi
|
||||||
|
|
||||||
@section Modes of operation
|
@section Modes of operation
|
||||||
|
|
|
@ -135,7 +135,7 @@ The BCAL is split up in different parts:
|
||||||
@item BCAL basic functions
|
@item BCAL basic functions
|
||||||
@end itemize
|
@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
|
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
|
modification is unnecessary. It contains all information required to use the
|
||||||
according block cipher.
|
according block cipher.
|
||||||
|
@ -220,7 +220,7 @@ typedef struct {
|
||||||
that the chosen keysize is valid
|
that the chosen keysize is valid
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@subsubsection BCAL-Basic context
|
@subsection BCAL-Basic context
|
||||||
Besides the context types for individual ciphers there is a generic 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.
|
type for BCAL. This is the context to use when using BCAL based functions.
|
||||||
The BCAL context has the following structure:
|
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-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,
|
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 BCAL descriptor file and of course the BCAL-Basic implementation.
|
||||||
|
|
||||||
The following functions are provided:
|
The following functions are provided:
|
||||||
@table @code
|
@subsubsection @code{bcal_cipher_init}
|
||||||
@item 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)}
|
@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
|
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
|
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.
|
for the selected cipher.
|
||||||
@end table
|
@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
|
@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
|
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
|
with BCAL context. It automatically also calls the @code{free} function if
|
||||||
necessary.
|
necessary.
|
||||||
|
|
||||||
@item bcal_cipher_enc
|
@subsubsection @code{bcal_cipher_enc}
|
||||||
@code{void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx)}
|
@code{void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx)}
|
||||||
this function encrypts a block in-place using a given BCAL contex.
|
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)}
|
@code{void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx)}
|
||||||
this function decrypts a block in-place using a given BCAL contex.
|
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)}
|
@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
|
this function returns the block size of a given cipher by using the BCAL
|
||||||
descriptor (to which a pointer must be passed).
|
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)}
|
@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
|
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).
|
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,5 +83,172 @@
|
||||||
|
|
||||||
|
|
||||||
@subsection Hash function abstraction layer (HFAL)
|
@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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,9 @@ end
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
def init_system(test_prog)
|
def init_system(test_prog)
|
||||||
|
begin
|
||||||
|
line = $sp.gets()
|
||||||
|
end while line!=nil
|
||||||
$sp.print("echo off \r")
|
$sp.print("echo off \r")
|
||||||
print("DBG i: " + "echo off \r"+"\n") if $debug
|
print("DBG i: " + "echo off \r"+"\n") if $debug
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
|
@ -135,6 +138,27 @@ def init_system(test_prog)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
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 #
|
# screen_progress #
|
||||||
|
@ -249,59 +273,42 @@ end
|
||||||
################################################################################
|
################################################################################
|
||||||
# add_scale_test #
|
# 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)
|
def add_scale_test(a, b, scale)
|
||||||
begin
|
m = wait_for_prompt("enter a:")
|
||||||
line = $sp.gets()
|
return false if !m
|
||||||
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)
|
|
||||||
puts("DBG put (#{__LINE__}): "+a.to_s(16)+" ") if $debug
|
puts("DBG put (#{__LINE__}): "+a.to_s(16)+" ") if $debug
|
||||||
$sp.print(a.to_s(16)+" ")
|
$sp.print(a.to_s(16)+" ")
|
||||||
begin
|
m = wait_for_prompt("enter b:")
|
||||||
line = $sp.gets()
|
return false if !m
|
||||||
line = "" if line==nil
|
puts("DBG put (#{__LINE__}): "+b.to_s(16)+" ") if $debug
|
||||||
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)
|
|
||||||
$sp.print(b.to_s(16)+" ")
|
$sp.print(b.to_s(16)+" ")
|
||||||
begin
|
m = wait_for_prompt("enter scale:")
|
||||||
line = $sp.gets()
|
return false if !m
|
||||||
line = "" if line==nil
|
puts("DBG put (#{__LINE__}): "+scale.to_s(10)+" ") if $debug
|
||||||
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)
|
|
||||||
$sp.print(scale.to_s(10)+"\r")
|
$sp.print(scale.to_s(10)+"\r")
|
||||||
begin
|
should = a + (b<<(8*scale))
|
||||||
line = $sp.gets()
|
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]+)/)
|
||||||
line = "" if line==nil
|
if !m
|
||||||
puts("DBG got (#{__LINE__}): "+line) if $debug
|
$logfile.printf("[fail (CRASH)]:")
|
||||||
if /^Error:.*/.match(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))
|
||||||
puts line
|
|
||||||
return false
|
return false
|
||||||
end
|
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)
|
line = m[0]
|
||||||
a_ = m[1].to_i(16)
|
a_ = m[1].to_i(16)
|
||||||
b_ = m[2].to_i(16)
|
b_ = m[2].to_i(16)
|
||||||
s_ = m[3].to_i(16)
|
s_ = m[3].to_i(16)
|
||||||
c_ = m[4].to_i(16)
|
c_ = m[4].to_i(16)
|
||||||
line.chomp!
|
line.chomp!
|
||||||
should = a + (b<<(8*scale))
|
|
||||||
if(a_== a && b_ == b && s_ == scale && c_ == should )
|
if(a_== a && b_ == b && s_ == scale && c_ == should )
|
||||||
$logfile.printf("[pass]: %s\n", line)
|
$logfile.printf("[pass]: %s\n", line)
|
||||||
return true
|
return true
|
||||||
else
|
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))
|
$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
|
return false
|
||||||
end
|
end
|
||||||
|
@ -563,7 +570,7 @@ def run_test_add_scale(skip=0)
|
||||||
length_b_B = skip+1
|
length_b_B = skip+1
|
||||||
begin
|
begin
|
||||||
$size = length_a_B
|
$size = length_a_B
|
||||||
(0..16).each do |i|
|
(0..4).each do |i|
|
||||||
scales = [0, 300]
|
scales = [0, 300]
|
||||||
16.times { scales << rand(301) }
|
16.times { scales << rand(301) }
|
||||||
scales.sort!
|
scales.sort!
|
||||||
|
@ -576,7 +583,42 @@ def run_test_add_scale(skip=0)
|
||||||
screen_progress(v)
|
screen_progress(v)
|
||||||
end
|
end
|
||||||
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)+1
|
||||||
|
a = rand(256**length_a_B)
|
||||||
|
b = rand(256**b_size)
|
||||||
|
v = add_scale_test(a, b, scale)
|
||||||
|
screen_progress(v)
|
||||||
|
v = add_scale_test(b, a, scale)
|
||||||
|
screen_progress(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
length_a_B += 10
|
||||||
|
length_b_B += 10
|
||||||
|
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]
|
scales = [0, 300]
|
||||||
16.times { scales << rand(301) }
|
16.times { scales << rand(301) }
|
||||||
scales.sort!
|
scales.sort!
|
||||||
|
@ -584,10 +626,8 @@ def run_test_add_scale(skip=0)
|
||||||
b_size = rand(length_b_B+1)
|
b_size = rand(length_b_B+1)
|
||||||
a = rand(256**length_a_B)
|
a = rand(256**length_a_B)
|
||||||
b = rand(256**b_size)
|
b = rand(256**b_size)
|
||||||
v = add_scale_test(a, b, scale)
|
v = add_scale_test_dummy(a, b, scale)
|
||||||
screen_progress(v)
|
v = add_scale_test_dummy(b, a, scale)
|
||||||
v = add_scale_test(b, a, scale)
|
|
||||||
screen_progress(v)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
length_a_B += 10
|
length_a_B += 10
|
||||||
|
@ -733,20 +773,7 @@ def run_test_gcdext(skip=0)
|
||||||
end while length_a_B<4096/8
|
end while length_a_B<4096/8
|
||||||
end
|
end
|
||||||
|
|
||||||
################################################################################
|
def init_serialport(conf)
|
||||||
# MAIN #
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
opts = Getopt::Std.getopts("s:f:i:a:hd")
|
|
||||||
|
|
||||||
conf = Hash.new
|
|
||||||
conf = readconfigfile("/etc/testport.conf", conf)
|
|
||||||
conf = readconfigfile("~/.testport.conf", conf)
|
|
||||||
conf = readconfigfile("testport.conf", conf)
|
|
||||||
conf = readconfigfile(opts["f"], conf) if opts["f"]
|
|
||||||
|
|
||||||
#puts conf.inspect
|
|
||||||
|
|
||||||
puts("serial port interface version: " + SerialPort::VERSION);
|
puts("serial port interface version: " + SerialPort::VERSION);
|
||||||
$linewidth = 64
|
$linewidth = 64
|
||||||
$linepos = 0
|
$linepos = 0
|
||||||
|
@ -774,6 +801,24 @@ $sp.read_timeout=1000; # 5 minutes
|
||||||
$sp.flow_control = SerialPort::SOFT
|
$sp.flow_control = SerialPort::SOFT
|
||||||
|
|
||||||
reset_system()
|
reset_system()
|
||||||
|
end
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# MAIN #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
opts = Getopt::Std.getopts("s:f:i:a:hd")
|
||||||
|
|
||||||
|
conf = Hash.new
|
||||||
|
conf = readconfigfile("/etc/testport.conf", conf)
|
||||||
|
conf = readconfigfile("~/.testport.conf", conf)
|
||||||
|
conf = readconfigfile("testport.conf", conf)
|
||||||
|
conf = readconfigfile(opts["f"], conf) if opts["f"]
|
||||||
|
|
||||||
|
#puts conf.inspect
|
||||||
|
init_serialport(conf)
|
||||||
|
|
||||||
|
$max_timeout = 2 * 60
|
||||||
|
|
||||||
if opts['d']
|
if opts['d']
|
||||||
$debug = true
|
$debug = true
|
||||||
|
|
|
@ -125,13 +125,6 @@ void test_add_scale_bigint(void){
|
||||||
return;
|
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;
|
uint8_t *c_b;
|
||||||
c_b = malloc(((a.length_B>(b.length_B+scale))?a.length_B:(b.length_B+scale))+2);
|
c_b = malloc(((a.length_B>(b.length_B+scale))?a.length_B:(b.length_B+scale))+2);
|
||||||
if(c_b==NULL){
|
if(c_b==NULL){
|
||||||
|
@ -143,6 +136,13 @@ void test_add_scale_bigint(void){
|
||||||
c.wordv = c_b;
|
c.wordv = c_b;
|
||||||
bigint_copy(&c, &a);
|
bigint_copy(&c, &a);
|
||||||
bigint_add_scale_u(&c, &b, scale);
|
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);
|
bigint_print_hex(&c);
|
||||||
cli_putstr_P(PSTR("\r\n"));
|
cli_putstr_P(PSTR("\r\n"));
|
||||||
free(a.wordv);
|
free(a.wordv);
|
||||||
|
|
Loading…
Reference in New Issue